핸드폰 키패드

YEONGHUN KO·2021년 12월 23일
0

ALGORITHMS - PRACTICE

목록 보기
45/50
post-thumbnail

1. 핸드폰 키패드

  • 1.엄지손가락은 상하좌우 4가지 방향으로만 이동할 수 있으며 키패드 이동 한 칸은 거리로 1에 해당합니다.

  • 2.왼쪽 열의 3개의 숫자 1, 4, 7을 입력할 때는 왼손 엄지손가락을 사용합니다.

  • 3.오른쪽 열의 3개의 숫자 3, 6, 9를 입력할 때는 오른손 엄지손가락을 사용합니다.

  • 4.가운데 열의 4개의 숫자 2, 5, 8, 0을 입력할 때는 두 엄지손가락의 현재 키패드의 위치에서 더 가까운 엄지손가락을 사용합니다.

    • 4-1. 만약 두 엄지손가락의 거리가 같다면, 오른손잡이는 오른손 엄지손가락, 왼손잡이는 왼손 엄지손가락을 사용합니다.
//  numbers	                            hand	      result
// [1, 3, 4, 5, 8, 2, 1, 4, 5, 9, 5]	"right"	   "LRLLLRLLRRL"
// [7, 0, 8, 2, 8, 3, 1, 5, 7, 6, 2]	"left"	   "LRLLRRLLLRR"
// [1, 2, 3, 4, 5, 6, 7, 8, 9, 0]	    "right"	   "LLRLLRLLRL"

2. 접근방법

  • pseudo code

  • L = [1,4,7] / R = [3,6,9] 로 설정

  • 그리고 현재 왼손과 오른속의 위치를 기록하기 위해 LH RH의 변수를 생성

  • forEach를 사용해서 numbers를 순회

    • 순회하면서 L / R에 속해있는것에 따라 RESULT를 build up 해감.
    • 문제는 2,5,8,0일때 왼손과 오른손의 위치를 측정해서 거리를 구함
    • 그리고 거리가 같으면 hand에 따라서 달라짐.
    • LH RH의 위치를 새로 갱신

결국 관건은 2,5,8,0일때 오르손과 왼손의 위치를 측정해서 거리를 구하는 것이다.

function solution(numbers, hand) {
  const pos = {
    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 lh = "*";
  let rh = "#";
  let result = "";

  function dis(num) {
    // 현채 lh,rh에서 누르려는 num 까지의 거리가 얼마냐를 측정
    const ld =
      Math.abs(pos[lh][0] - pos[num][0]) + Math.abs(pos[lh][1] - pos[num][1]);

    const rd =
      Math.abs(pos[rh][0] - pos[num][0]) + Math.abs(pos[rh][1] - pos[num][1]);

    if (ld === rd) return hand === "left" ? "L" : "R";
    return ld < rd ? "L" : "R";
  }

  for (let num of numbers) {
    if (num % 3 === 1) {
      result += "L";
      lh = num;
    } else if (num !== 0 && num % 3 === 0) {
      result += "R";
      rh = num;
    } else {
      result += dis(num);
      result[result.length - 1] === "R" ? (rh = num) : (lh = num);
    }
  }

  return result;
}

아하!! 거리는 POS라는 배열안에다가 각번호의 위치를 적어두고 최종거리= 상하 거리(POS[0]) + 좌우 거리(POS[1])의 공식을 두고 오른손과 왼손의 거리를 비교
계산.

또 다른 방법을 발견해서 공유해본다

function solution(numbers, hand) {
  hand = hand[0] === 'r' ? 'R' : 'L';
  let position = [1, 4, 4, 4, 3, 3, 3, 2, 2, 2];
  let h = { L: [1, 1], R: [1, 1] };
  return numbers
    .map(x => {
      if (/[147]/.test(x)) {
        h.L = [position[x], 1];
        return 'L';
      }
      if (/[369]/.test(x)) {
        h.R = [position[x], 1];
        return 'R';
      }
      let distL = Math.abs(position[x] - h.L[0]) + h.L[1];
      let distR = Math.abs(position[x] - h.R[0]) + h.R[1];
      if (distL === distR) {
        h[hand] = [position[x], 0];
        return hand;
      }
      if (distL < distR) {
        h.L = [position[x], 0];
        return 'L';
      }
      h.R = [position[x], 0];
      return 'R';
    })
    .join('');
}

regX.test() 로 더 간결해진 모습이 돋보인다. hand, h = {L,R} 를 사용하여 가독성을 높인점도 주목할만한 포인트이다.

결국 POS를 모두 기록해서 일일이 계산해야하는 구나. 난 한큐에 해결하는 식이 있는줄알고 계속 골머리를 싸맴.

profile
'과연 이게 최선일까?' 끊임없이 생각하기

0개의 댓글