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

jaemin·2020년 12월 14일
0

프로그래머스

목록 보기
15/18
post-thumbnail

키패드 누르기

문제 설명

참조 : 프로그래머스 키패드 누르기

풀이 설계

처음 문제를 설계할때는 이전 숫자와의 거리가 1 혹은 3인 경우는 왼손잡이인지 오른손잡이인지 따져서 누르도록 하고 1 혹은 3이 아니라면
거리 차이가 적게 나는 손가락으로 누르도록 했다. 그런데, 7번에서 8번을 누를 때와 0번에서 8번을 누를 때 거리가 같은데, 이렇게 설계할경우 다르다고 판단하게 된다.

따라서 좌표를 도입하여 설계하도록 했다. 각 키패드 번호마다 [0, 0], [0, 1]처럼 좌표를 도입해서 x좌표값과 y좌표값의 차이를 구한 후 이 차이값을 더하면 서로 떨어진 거리가 된다. 이 거리를 왼손, 오른손 비교하여 적은 값인 손을 누르도록 하자.

풀이 과정

일단, 좌표를 만들어주고 왼손과 오른손이 이전에 뭘 눌렀는지 기억해야 하므로 변수를 만든다. 그리고 문제 기본 설정인 값들을 채워준다.

function solution(numbers, hand) {
  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 answer = '';
  let left = '*';
  let right = '#';

  numbers.forEach(num => {
    if (num % 3 === 1) {
      left = num;
      answer += 'L';
    } else if (num % 3 === 0 && num !== 0) {
      right = num;
      answer += 'R';
    } else {
      // 여기서 좌표들의 차이를 계산해 줘야한다.
    }
  });

  return answer;
}

이제, 주석에 해당하는 부분을 채워야 하는데, 이 거리 차이값만 계산해주는 함수를 따로 만들어주는 것이 더 좋을 것 같다.
항상 함수는 최소한의 일만 하도록 구현해주자.

  function difference(left, right, num) {
    const leftDiff = Math.abs(keypad[left + ''][0] - keypad[num + ''][0]) + Math.abs(keypad[left + ''][1] - keypad[num + ''][1]);
    const rightDiff = Math.abs(keypad[right + ''][0] - keypad[num + ''][0]) + Math.abs(keypad[right + ''][1] - keypad[num + ''][1]);

    if (leftDiff === rightDiff) return hand === 'left' ? 'L' : 'R';
    return leftDiff < rightDiff ? 'L' : 'R';
  }

  numbers.forEach(num => {
    if (num % 3 === 1) {
      left = num;
      answer += 'L';
    } else if (num % 3 === 0 && num !== 0) {
      right = num;
      answer += 'R';
    } else {
      answer += difference(left, right, num);
    }
  });

처음에는 difference 함수를 아예 solution 함수 밖으로 빼냈는데, 그렇게 하니 difference의 매개변수가 5개가 되었다. 강사님께서 함수의 매개변수의 개수는 최대 3개까지만 받도록 하셨던게 기억나 굉장히 마음에 찔려 solution 함수 안으로 가져왔다.

이렇게 작성한 후, 잘 작동할 줄 알았는데 몇 가지 틀리게 나오는 부분이 있었다. num이 2, 5, 8, 0인 경우에는 answer에 왼손인지 오른손인지 할당했지만 변수 left와 right에게는 이전 숫자가 무엇이었는지 재할당해주는 부분이 없었다.

이 부분을 수정해 완성하면,

function solution(numbers, hand) {
  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 answer = '';
  let left = '*';
  let right = '#';

  function difference(left, right, num) {
    const leftDiff = Math.abs(keypad[left + ''][0] - keypad[num + ''][0]) + Math.abs(keypad[left + ''][1] - keypad[num + ''][1]);
    const rightDiff = Math.abs(keypad[right + ''][0] - keypad[num + ''][0]) + Math.abs(keypad[right + ''][1] - keypad[num + ''][1]);

    if (leftDiff === rightDiff) return hand === 'left' ? 'L' : 'R';
    return leftDiff < rightDiff ? 'L' : 'R';
  }

  numbers.forEach(num => {
    if (num % 3 === 1) {
      left = num;
      answer += 'L';
    } else if (num % 3 === 0 && num !== 0) {
      right = num;
      answer += 'R';
    } else {
      answer += difference(left, right, num);
      answer[answer.length - 1] === 'L' ? left = num : right = num;
    }
  });

  return answer;
}

좌표 도입만 생각할 수 있다면 그렇게 어려운 문제는 아니었다.

profile
프론트엔드 개발자가 되기 위해 공부 중입니다.

0개의 댓글