본문 바로가기
카테고리 없음

[프로그래머스] 정수를 나선형으로 배치하기 JS

by limew 2023. 12. 21.

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

 

양의 정수 n이 매개변수로 주어집니다. n × n 배열에 1부터 n2 까지 정수를 인덱스 [0][0]부터 시계방향 나선형으로 배치한 이차원 배열을 return 하는 solution 함수를 작성해 주세요.


제한사항

  • 1 ≤ n ≤ 30

 

 

 


 

lv0이라 만만하게 봤는데 정답률이 낮은 이유가 있었다.

특별한 알고리즘이나 자료구조는 쓰지 않는 구현 문제이지만 이차배열을 나선형으로 순회하는 것을 40분 동안 고민했다.

이런건 그냥 뇌를 비우고 한 스텝씩 실수 없이 처리하는게 방법인 것 같다.

 

currNum 1부터 시작해서 n*n까지 while을 돌리며 →  ↓  ←  ↑  순으로 이차배열을 순회했다.

이동방향은  0: → 1: ↓  2: ← 3:   이 처럼 숫자로 판단했고 방향이 바뀔때마다 ++ 한 뒤 Mod로 갱신해주었다.

 

현재row = 0, 현재 col = 0, 현재 이동하는 방향 = 오른쪽 으로 초기 세팅을 하고

한 방향으로 이동할 때마다 다음 좌표가 유효한지 확인한다

  • 유효하면 계속 동일한 방향으로 이동한다
  • 유효하지 않으면  다음 방향으로 바꿔준다.

단 주의할 점이 있는데 순회 할 수록 다음 좌표의 유효성을 판단하는 범위가 좁아진다는 것이다

예를 들어 첫번째 순회의  로 이동할 때 다음 좌표가 0과 4사이여야지만 유효하다

하지만 두번째 순회에서   로 이동할 때는 1과 3사이만 유효하다

 

이를 padding으로 기록했고 ← 에서 ↑ 로 바뀔때 padding++해주었다.

 

 


풀이 (성공)

function solution(n) {
  var answer = Array.from({ length: n }, () =>
    Array.from({ length: n }, () => 0)
  );
  const lastNum = n * n;
  let currRow = 0;
  let currCol = 0;
  let currNum = 1;

  let currDir = 0; // 0: right, 1: down, 2: left, 3: top
  let padding = 0;

  while (currNum <= lastNum) {
    answer[currRow][currCol] = currNum;

    // 현재 진행방향이 오른쪽
    if (currDir === 0) {
      // 그 다음 좌표가 범위를 넘어가면 진행방향 바꾸기
      if (currCol + 1 >= n - padding) {
        currDir = getNextDir(currDir);
        currRow++;
      } else {
        currCol++;
      }
    }
    // 현재 진행방향이 아래쪽
    else if (currDir === 1) {
      // 그 다음 좌표가 범위를 넘어가면 진행방향 바꾸기
      if (currRow + 1 >= n - padding) {
        currDir = getNextDir(currDir);
        currCol--;
      } else {
        currRow++;
      }
    }
    // 현재 진행방향이 왼쪽
    else if (currDir === 2) {
      // 그 다음 좌표가 범위를 넘어가면 진행방향 바꾸기
      if (currCol - 1 < 0 + padding) {
        currDir = getNextDir(currDir);
        currRow--;
        padding++;
      } else {
        currCol--;
      }
    } else {
      // 그 다음 좌표가 범위를 넘어가면 진행방향 바꾸기
      if (currRow - 1 < 0 + padding) {
        currDir = getNextDir(currDir);
        currCol++;
      } else {
        currRow--;
      }
    }
    currNum++;
  }
  return answer;
}

function getNextDir(currDir) {
  return currDir + 1 <= 3 ? currDir + 1 : (currDir + 1) % 4;
}