배워서 남 주자

프로그래머스 Lv.1 | 키패드 누르기 (JavaScript)

미래에서 온 개발자 2023. 6. 8. 11:59
 

프로그래머스

코드 중심의 개발자 채용. 스택 기반의 포지션 매칭. 프로그래머스의 개발자 맞춤형 프로필을 등록하고, 나와 기술 궁합이 잘 맞는 기업들을 매칭 받으세요.

programmers.co.kr

 

알고리즘 문제를 풀 때면 항상 다음과 같은 순서를 따른다.

1) 입출력 예시를 보면서 구체적인 예시를 통해 일반적인 법칙을 찾는다. 
2) 일반적인 법칙을 코드로 옮긴다. 

 

아래는 문제를 풀 때 적은 노트를 캡처한 화면이다. 

 

 

1. 입력값인 numbers 배열을 number 값에 따라 "L" 또는 "R"로 리턴한다. 

2. 2, 5, 8, 0 값의 경우, 현재 왼손과 오른손의 위치 정보에 따라 더 가까운 손으로 입력을 해야 하기에 '현재 손의 위치 정보'를 변수로 만들어 갱신해 준다. 

3. 어느 손이 더 가까운지 알려면 스마트폰 키패드의 위치 정보가 필요하기에 이중 배열로 키패드를 정의하여 인덱스 정보를 활용한다. 

4. target까지의 dL(distance left)와 dR(distance right)를 비교한다. 

5. dL과 dR을 구하려면 target과의 x좌표와 y좌표 사이의 차를 계산한 다음 둘을 더한다. 

 

이제 1~5번까지의 내용을 코드로 작성한다. 

function solution(numbers, hand) {
  const phoneMap = [ // (3) 키패드 정의
    [1, 2, 3],
    [4, 5, 6],
    [7, 8, 9],
    ["*", 0, "#"],
  ];
  let curL = "*",
    curR = "#"; // (2) 현재 손의 위치 정보를 저장할 변수를 만든다

// (1) numbers에 .map()을 돌려서 "L" 또는 "R"을 리턴한 후 .join()으로 최종 문자열 반환
  return numbers
    .map((number) => {
      if (number === 1 || number === 4 || number === 7) {
        curL = number; // (2) 위치 정보 갱신
        return "L";
      } else if (number === 3 || number === 6 || number === 9) {
        curR = number; // (2) 위치 정보 갱신
        return "R";
      } else {
        let curLeftCoord, curRightCoord, targetCoord;

        phoneMap.forEach((row, rowIdx) => {
          const leftIdx = row.indexOf(curL);
          if (leftIdx !== -1) curLeftCoord = [rowIdx, leftIdx];

          const rightIdx = row.indexOf(curR);
          if (rightIdx !== -1) curRightCoord = [rowIdx, rightIdx];

          const targetIdx = row.indexOf(number);
          if (targetIdx !== -1) targetCoord = [rowIdx, targetIdx]
        });

		// (5) dL과 dR을 계산
        const dL = calculateDistance(targetCoord, curLeftCoord);
        const dR = calculateDistance(targetCoord, curRightCoord);

		// (4) dL과 dR을 비교
        if (dL < dR || (dL === dR && hand === "left")) {
          curL = number;
          return "L";
        } else if (dL > dR || (dL === dR && hand === "right")) {
          curR = number;
          return "R";
        }
      }
    })
    .join("");
}

const calculateDistance = (targetCoord, currentHandCoord) =>
  Math.abs(targetCoord[0] - currentHandCoord[0]) +
  Math.abs(targetCoord[1] - currentHandCoord[1]);

 

귀납 추론을 통해 일반적인 법칙을 찾았다면 어떻게 코드로 옮길 수 있을까? 

 

예를 들어 위의 메모에서 'distance 작은 손가락으로 터치, 같다면 hand에 따라'라고 적었는데, 이를 코드로 옮기면 다음과 같다.

 

if (dL < dR) return "L" : distance 작은 손가락으로 터치 

dL === dR && hand === "left" : 같다면 hand에 따라 

 

알고리즘 문제는 귀납 추론을 할 수 있는 사고력 훈련과 이를 컴퓨터가 이해할 수 있는 언어로 옮기는 훈련 두 가지가 동시에 필요하다. 둘 다 통역 연습할 때 했던 훈련 방식과 유사해서 재밌다.