안녕하세요

프로그래머스 JS [방문 길이] 본문

프로그래머스/Lv.2

프로그래머스 JS [방문 길이]

sakuraop 2022. 12. 3. 19:44

방문 길이 문제보기

게임 캐릭터를 4가지 명령어를 통해 움직이려 합니다. 명령어는 다음과 같습니다.
  • U: 위쪽으로 한 칸 가기
  • D: 아래쪽으로 한 칸 가기
  • R: 오른쪽으로 한 칸 가기
  • L: 왼쪽으로 한 칸 가기

캐릭터는 좌표평면의 (0, 0) 위치에서 시작합니다. 좌표평면의 경계는 왼쪽 위(-5, 5), 왼쪽 아래(-5, -5), 오른쪽 위(5, 5), 오른쪽 아래(5, -5)로 이루어져 있습니다.

예를 들어, "ULURRDLLU"로 명령했다면

  • 1번 명령어부터 7번 명령어까지 다음과 같이 움직입니다.
  • 8번 명령어부터 9번 명령어까지 다음과 같이 움직입니다.

이때, 우리는 게임 캐릭터가 지나간 길 중 캐릭터가 처음 걸어본 길의 길이를 구하려고 합니다. 예를 들어 위의 예시에서 게임 캐릭터가 움직인 길이는 9이지만, 캐릭터가 처음 걸어본 길의 길이는 7이 됩니다. (8, 9번 명령어에서 움직인 길은 2, 3번 명령어에서 이미 거쳐 간 길입니다)

단, 좌표평면의 경계를 넘어가는 명령어는 무시합니다.

예를 들어, "LULLLLLLU"로 명령했다면

  • 1번 명령어부터 6번 명령어대로 움직인 후, 7, 8번 명령어는 무시합니다. 다시 9번 명령어대로 움직입니다.

이때 캐릭터가 처음 걸어본 길의 길이는 7이 됩니다.

명령어가 매개변수 dirs로 주어질 때, 게임 캐릭터가 처음 걸어본 길의 길이를 구하여 return 하는 solution 함수를 완성해 주세요.

제한사항
  • dirs는 string형으로 주어지며, 'U', 'D', 'R', 'L' 이외에 문자는 주어지지 않습니다.
  • dirs의 길이는 500 이하의 자연수입니다.
입출력 예dirsanswer
"ULURRDLLU" 7
"LULLLLLLU" 7

첫번째 시도 (실패함)

1) set함수를 이용하여 추가하려는 이동경로의 모양이 이미 존재하면 추가되지 않도록 한다.

    const moveHistorySet = new Set();


2) LR과 같이 이동할 경우 같은 경로로 인식하지 못하고 2로 표시되는 것을 막기 위해서
지나간 경로에는 0.5 라는 흔적을 남긴다.

        const trace = [direction[0] / 2, direction[1] / 2];


3) 0.5라는 흔적이 남은 장소는 반대 방향에서 다시 지나가게 되어도 새로운 경로에 추가하지 않도록 했다.


        if (!moveHistorySet.has(`${[player[0] - trace[0], player[1] - trace[1]]}`)) {
            moveHistorySet.add(`${[player[0] - trace[0], player[1] - trace[1]]}`, 0);
        }


그리고 실패한 이유

UUUUURRRRR 을 시행할 때

Set(11) {
  '-0.5,0',
  '-1.5,0',
  '-2.5,0',
  '-3.5,0',
  '-4.5,0',
  '-5,-0.5',
  '-5,-1.5',
  '-5,-2.5',
  '-5,-3.5',
  '-5,-4.5',
  '-4.5,-5'
}

abs = 절대값

abs(x) + abs(y) + abs(trace) 의 값이 10.5가 먼저 된 이후에

        const trace = [direction[0] / 2, direction[1] / 2];
        direction.forEach((el, index) => {
            if (player[index] + el >= -5 && player[index] + el <= 5) {
                player[index] += el;
            }
        });


실제 trace의 좌표를 반영해 빼주어 5, 4.5 를 표시하도록 했다.

        if (!moveHistorySet.has(`${[player[0] - trace[0], player[1] - trace[1]]}`)) {
            moveHistorySet.add(`${[player[0] - trace[0], player[1] - trace[1]]}`, 0);
        }


이로 인해서 이미 5,0 좌표인데도 불구하고 5.5, 0 좌표까지 이동하는 듯한 모양이 되었다.


해결 방법 

플레이어가 5,5로 이동하기 전 좌표인 5,4에서 trace를 더해주도록 했다.

abs(x) + abs(y) + abs(trace) 의 값이 9.5가 되어 (항상 10보다 작도록)
10을 넘어가는 경우에는 trace 표시를 하지 않도록 하였다.

        if (Math.abs(player[0] + direction[0]) <= 5 && Math.abs(player[1] + direction[1]) <= 5) {
            if (!moveHistorySet.has(`${[player[0] + trace[0], player[1] + trace[1]]}`)) {
                moveHistorySet.add(`${[player[0] + trace[0], player[1] + trace[1]]}`, null);
            }
            player[0] += direction[0];
            player[1] += direction[1];
        }



첫번째 시도 실패한 코드

function solution(dirs) {
    const dirsArray = dirs.split("");
    const dirObject = {
        U: [0, +1], D: [0, -1], L: [-1, 0], R: [+1, 0],
    };

    const player = [0, 0];
    const moveHistorySet = new Set();

    const move = (direction) => {
        const trace = [direction[0] / 2, direction[1] / 2];
        direction.forEach((el, index) => {
            if (player[index] + el >= -5 && player[index] + el <= 5) {
                player[index] += el;
            }
        });
        if (!moveHistorySet.has(`${[player[0] - trace[0], player[1] - trace[1]]}`)) {
            moveHistorySet.add(`${[player[0] - trace[0], player[1] - trace[1]]}`, 0);
        }
    };

    dirsArray.forEach((el) => {
        move(dirObject[el]);
    });

    return moveHistorySet.size;
}

solution("LDLDLDLDLD"); //10
solution("LDLDLDLDLDL"); // 10 이어야 하는데 11이 나옴





성공한 코드 

function
 solution(dirs) {
    const dirsArray = dirs.split("");
    const dirObject = {
        U: [0, +1], D: [0, -1],  L: [-1, 0],  R: [+1, 0],
    };

    const player = [0, 0];
    const moveHistorySet = new Set();

    const move = (direction) => {
        const trace = [direction[0] / 2, direction[1] / 2];

        if (Math.abs(player[0] + direction[0]) <= 5 && Math.abs(player[1] + direction[1]) <= 5) {
            if (!moveHistorySet.has(`${[player[0] + trace[0], player[1] + trace[1]]}`)) {
                moveHistorySet.add(`${[player[0] + trace[0], player[1] + trace[1]]}`, null);
            }
            player[0] += direction[0];
            player[1] += direction[1];
        }
    };

    dirsArray.forEach((el) => {
        move(dirObject[el]);
    });

    return moveHistorySet.size;
}

solution("LLLLLDDDDDLL");