Level 2 ) 방문 길이

Doozuu·2023년 7월 31일
0

프로그래머스 (JS)

목록 보기
136/183

문제 설명

게임 캐릭터를 4가지 명령어를 통해 움직이려 합니다. 명령어는 다음과 같습니다.

  • U: 위쪽으로 한 칸 가기
  • D: 아래쪽으로 한 칸 가기
  • R: 오른쪽으로 한 칸 가기
  • L: 왼쪽으로 한 칸 가기

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

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

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

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

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

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

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

제한사항

dirs는 string형으로 주어지며, 'U', 'D', 'R', 'L' 이외에 문자는 주어지지 않습니다.
dirs의 길이는 500 이하의 자연수입니다.

입출력 예

dirs	answer
"ULURRDLLU"	7
"LULLLLLLU"	7

풀이

  1. 크기가 10x10인 빈 배열 만들기 -> false로 채우기 (방문 여부 체크)
  2. 시작지점 : (5,5)
  3. 명령어에 따라 움직이며 방문 여부 체크 (출발한 지점을 true로)
  4. 이미 방문한건 continue
  5. 다 끝난후 true인 갯수 반환

-> 1/4만 맞았다.

function solution(dirs) {
    let visited = Array.from({length: 11}, () => Array(11).fill(false));
    let current = [5,5];
    let answer = 0;
    let move = {"U": 1, "D": -1, "R": 1, "L": -1};
    for(let i=0;i<dirs.length;i++){
        let action = dirs[i];
        let [x,y] = current;
        let newX = x, newY = y;
        if(action === "U" || action === "D"){
            newX = x + move[action];
        }else{
            newY = y + move[action];
        }
        if(newX < 0 || newX > 10 || newY < 0 || newY > 10 || visited[x][y]){
             current = [x,y];
             continue;
        }
        visited[x][y] = true;
        current = [newX, newY];
    }
    for(let i=0;i<11;i++){
        for(let j=0;j<11;j++){
            if(visited[i][j]) answer++;
        }
    }
    return answer;
}

정답 풀이

⭐️ 한 번 지나갈 때 A -> B, B -> A를 모두 저장해주어야 한다.
만약 A -> B만 저장하게 되면 나중에 B -> A로 갈 때 이미 지나간 길이 아닌 것으로 인식하기 때문이다.

function solution(dirs) {
    const set = new Set(); // 지나친 경로 배열(중복x)
        const [min, max] = [-5, 5]; // x, y좌표의 최소, 최대값
        let curX = 0; // x좌표
        let curY = 0; // y좌표
        let prev = ""; // 바뀌기전 경로

        for (let i = 0; i < dirs.length; i++) {
          prev = "" + curX + curY; // [0, 0] => '00' string으로 저장.
          if (dirs[i] === "U" && curY + 1 <= max) { // Y좌표 증가
            curY++;
          } else if (dirs[i] === "D" && curY - 1 >= min) { // Y좌표 감소
            curY--;
          } else if (dirs[i] === "R" && curX + 1 <= max) { // X좌표 증가
            curX++;
          } else if (dirs[i] === "L" && curX - 1 >= min) { // X좌표 감소
            curX--;
          } else { // 범위를 벗어나면 continue.
            continue;
          }

          // [0, 0] => [0, 1] 로 이동 했다면 '0001', '0100' 양방향 경로저장.
          set.add(curX + (curY + prev)); 
          set.add(prev + curX + curY);
        }

        return set.size / 2; // 양방향경로가 저장되어있으므로 size / 2.
}
profile
모든게 새롭고 재밌는 프론트엔드 새싹

1개의 댓글

comment-user-thumbnail
2023년 7월 31일

개발자로서 성장하는 데 큰 도움이 된 글이었습니다. 감사합니다.

답글 달기