[프로그래머스 Lv.1] 키패드 누르기

Minha Ahn·2024년 10월 26일
0

데브코스

목록 보기
11/29
post-thumbnail

◼️ 문제

키패드 누르기

1. 문제 설명


2. 제한사항


3. 입출력



◼️ 풀이

✏️ 전반적인 풀이과정

  1. 문제 풀이에 필요한 값(키패드 위치, 왼손으로 반드시 누르는 수, 오른손으로 반드시 누르는 수) 등을 준비한다.
  2. numbers를 for문으로 돌며 사용해야 하는 손을 결정한다.
    2-1. 타겟 숫자가 왼손, 오른손으로 반드시 눌러야 하는 숫자인지 확인한다. (1단계)
    2-2. 타겟 숫자가 가운데 열인 경우, 현재 왼손, 오른손 위치로 거리를 비교한다. (2단계)
    2-3. 왼손, 오른손 거리가 동일한 경우, hand로 결정한다. (3단계)
  3. 결과를 리턴한다.

📃 풀이과정 추가 설명

객체로 키패드 숫자 위치 관리

키패드 각 숫자의 위치를 배열처럼 접근하는 것은 바로 떠올렸지만,
타겟 숫자가 어떤 위치에 있는지를 알아내는 방법을 어떻게 해야하는지 고민을 많이 했다.

처음엔 숫자의 몫과 나머지를 이용한 방식으로 할까 하다가 매번 계산하는 것도 좋지 않을 것 같았고
계산도 깔끔하게 떨어지지 않아 오히려 더 복잡해질 것 같아서 넘겼다.

그래서 생각한 다음 방식은 각 타겟 숫자의 위치를 저장한 배열을 만들고
타겟 숫자를 인덱스로 삼아 접근해야 겠다고 생각했다.
특수 문자인 *과 #은 각각 10번, 11번으로 삼고 구현하려고 했다.

그러다가 이 방식은 코드 파악도 쉽지 않고 (근데 코드 파악을 고려해야할 지는 잘 모르겠다)
이렇게 일일이 위치를 저장할 바에는 객체로 더 직관적으로 표현해도 되겠다 싶어서 객체를 선택했다.

사용해야 할 손을 결정하는 3단계 로직 구현

처음에는 if와 else if, else로 주구장창 나열했더니 가독성이 너무 안 좋았다.
너무 잦은 if로 뎁스도 깊어지고, 내가 짠 코드임에도 복잡해서 파악이 힘들었다.

그래서 if ~ else를 각 단계별로만 묶고
3단계 이전의 경우로 해결하는 건 continue를 이용해 이후 로직을 실행하지 않도록 구현했다.

continue를 적절하게 사용하면 if ~ else를 2중, 3중으로 만들지 않아도 되기 때문에
훨씬 코드가 개선되는 것 같다고 느꼈다.

calDistance 함수 따로 구현

거리를 계산하는 건 타켓 숫자 위치와 현재 손의 위치의 0번 인덱스와 1번 인덱스의 차이를 더하는 방식으로 구현했다.
다만, 왼손 오른손을 둘다 구현해야 하고 계산하는 식이 너무 길어 따로 빼두는 게 더 좋을 것 같았다.
그래서 calDistance 함수를 만들었고, 함수 내부에서 키패드 숫자 위치를 알아야 하는 점 때문에 solution 내부에 함수를 위치시켰다.


💻 코드

function solution(numbers, hand) {
  const leftLine = [1, 4, 7];
  const rightLine = [3, 6, 9];
  const keypad = {
    1: [0, 0], 2: [0, 1], 3: [0, 2],
    4: [1, 0], 5: [1, 1], 6: [1, 2],
    7: [2, 0], 8: [2, 1], 9: [2, 2],
    "*": [3, 0], 0: [3, 1], "#": [3, 2],
  };

  let left = "*";
  let right = "#";
  const result = [];

  function calDistance(target, current) {
    return (
      Math.abs(keypad[target][0] - keypad[current][0]) +
      Math.abs(keypad[target][1] - keypad[current][1])
    );
  }

  for (const target of numbers) {
    // 1단계
    if (leftLine.includes(target)) {
      result.push("L");
      left = target;
      continue;
    } else if (rightLine.includes(target)) {
      result.push("R");
      right = target;
      continue;
    }

    // 2단계
    const leftDistance = calDistance(target, left);
    const rightDistance = calDistance(target, right);

    if (leftDistance < rightDistance) {
      result.push("L");
      left = target;
      continue;
    } else if (leftDistance > rightDistance) {
      result.push("R");
      right = target;
      continue;
    }

    // 3단계
    if (hand === "right") {
      result.push("R");
      right = target;
    } else {
      result.push("L");
      left = target;
    }
  }
  return result.join("");
}
profile
프론트엔드를 공부하고 있는 학생입니다🐌

0개의 댓글