본문 바로가기
언리얼_엔진_게임개발_공부/알고리즘&자료구조

코드카타 - 문제에서 시키는 대로 하는 것에서 멈추지 마!!!

by jaboy 2025. 2. 5.

https://school.programmers.co.kr/learn/courses/30/lessons/172928

위 그리드는 공원! 나는 동서남북 방향으로 주어진 칸 수만큼 움직이며 로봇 강아지!

park - 공원을 나타내는 vector<string> - ["SOO", "OOX", "OOO"] - S 는 시작, O는 이동 가능, X는 이동 불가

routes - 이동 명령이 담긴 vector<string> - "E 2" 동쪽으로 2칸, "N 3" 북쪽으로 3칸 등

 

아주 literal 한 나의 풀이

routes 에서 주어진 string 의 첫번째와 세번째 글자를 변수에 저장하고,

switch 문을 활용해 현재 위치에서 동/서/남/북 방향 (첫번째 변수) 으로 몇칸 (두번째 변수) 이동할 때

1. 범위를 넘어가지 않는지 / 2. 경로에 X 가 없는지

확인하여 두 조건을 모두 충족하면 현재 위치를 해당 방향으로 칸 수만큼 이동시키는 코드를 작성하여 제출했다.

당연히 (문제에서 제시된 프로세스를 word to word 그대로 구현했으므로...) 문제 없이 넘어가지만, 장황한 풀이가 되어버렸다.

 

//...inside loop iterating routes
        char op = routes[i][0];
        int n = routes[i][2] - '0';
        switch (op)
        {
            case 'E':
                if (CurrCol + n < Width)
                {
                    bool FoundX = false;
                    for (int i = CurrCol; i <= CurrCol + n; i++)
                    {
                        if (park[CurrRow][i] == 'X')
                        {
                            FoundX = true;
                            break;
                        }
                    }
                    if (!FoundX) CurrCol += n;
                }
                break;

            case 'W':
                if (CurrCol - n >= 0)
                {
                    bool FoundX = false;
                    for (int i = CurrCol; i >= CurrCol - n; i--)
                    {
                        if (park[CurrRow][i] == 'X')
                        {
                            FoundX = true;
                            break;
                        }
                    }
                    if (!FoundX) CurrCol -= n;
                }
                break;

            case 'N':
                if (CurrRow - n >= 0)
                {
                    bool FoundX = false;
                    for (int i = CurrRow; i >= CurrRow - n; i--)
                    {
                        if (park[i][CurrCol] == 'X')
                        {
                            FoundX = true;
                            break;
                        }
                    }
                    if (!FoundX) CurrRow -= n;
                }
                break;

            case 'S':
                if (CurrRow + n < Height)
                {
                    bool FoundX = false;
                    for (int i = CurrRow; i <= CurrRow + n; i++)
                    {
                        if (park[i][CurrCol] == 'X')
                        {
                            FoundX = true;
                            break;
                        }
                    }
                    if (!FoundX) CurrRow += n;
                }
                break;
        }
//.....

 

 

특히 EWSN 각 케이스마다 아주 비슷한 프로세스를 수행하고 있기에, 더 나은 풀이가 없을까 고민해보았다.

EWSN 의 경우 각각의 방향이므로, 이를 unordered_map<char, int> 로 만들어 배열의 인덱스로 활용할 수 있다는 생각까지는 했지만, EW / SN 를 각각 column / row 로 구별해야 한다는 생각에 적당한 방법을 떠올리지 못했다.

그래서 다른 사람의 풀이를 참고하였다.

 

EWSN 각각 이동값을 배열로 사용 / map 으로 EWSN 을 인덱스화

1. EWSN 를 각각 0, 1, 2, 3 으로 map 하여 인덱스로 사용

--> unordered_map<char, int> opMap = { {‘E’, 0}, {‘W’, 1}, {‘S’, 2}, {‘N’, 3} };

 

2. EWSN 각각에 해당하는 델타 (이동) 값을 배열로 저장

--> int dRow[4] = {0, 0, 1, -1}; (EW 는 0, SN 은 +-1)
int dCol[4] = {1, -1, 0, 0}; (EW 는 +-1, SN 은 0)

그렇다, EW SN 각각 이동하지 않는 부분에 대해서는 0을 가져가게 하면 된다...!

 

이렇게 되면 routes 를 iterate 하며 현재 row 와 col 을 어느 방향으로, 얼만큼 이동시켜야 하는지에 상관 없이

배열에서 인덱스로 접근하여 바로 연산 가능하다.

 

//----inside the loop iterating routes
    int n = routes[i][2] - '0'; // n = number of steps
    int op = opMap[routes[i][0]]; // op = EWSN as an index

    while (n--)
    {
        row += dRow[op];
        col += dCol[op];

        if (row or col is out of range) break;
        if (park[row][col] == 'X') break;
    }

    if (n < 0)
    {
        currRow = row; currCol = col;
    }
//----

 

n 이 계속 감소하며 0이 되었을 때 while loop 은 종료되고 n 은 마지막으로 1 감소하므로 n < 0 인 경우 break; 없이 while 을 빠져나왔으므로 이동 가능함을 알 수 있다.

 

코드카타를 하면서, '이러면 되겠다' 해서 코드를 작성하고, 테스트 케이스 통과하면 바로 제출 누르....기 전에!!!... 꼭 이 코드가 최선인지 고민하기로 (수십번째) 다짐을 한다...