[JavaScript] 키패드 누르기 Lv1

Date:     Last Updated:

키패드 누르기

문제 프로그래머스 FAQ 내용을 보니 카카오나 기업의 문제들은 저작권이 있으니 풀이를
github나 개인블로그에 올리지 말라고 되어 있어서 링크로 대체합니다.

출처: Programmers
키패드 누르기

문제의 이해

문제를 처음 봤을 때는 뭔가 어려울 것.. 같은데? 라고 생각했는데 읽어보이 그렇게 어려운 문제는 아니었다. 다른 조건은 쉬운데, 가운데 2,5,8,0 을 누를 때 왼손으로 누를 것인지 오른손으로 누를 것인지 누를 버튼과 손가락간의 거리 측정을 하는 부분이 까다로운 부분이었다. 질문하기에 먼저 들어가서 봤는데 이걸 피타고라스의 정리를 이용해서 푸는 경우도 있었다. 물론 피타고라서 정리를 이용해서 풀어도 충분히 풀릴 문제라고 생각했다. 다만 문제에서 요구한 것은 아닌 것 같다.

내가 생각한 풀이 방법

  1. 주어진 그림처럼 키패드를 만들기 위해서 2차원 배열을 이용해서 키패드를 만든다.(이때 index가 각 키패드의 위치이다.)
  2. 왼손과 오른손도 위치를 가지고 있어야 하기 때문에 각 손을 배열2개를 가지게 한다. (index 0 은 x index 1은 y)
  3. numbers의 데이터를 가져와서 비교한다. 1,4,7이면 왼손, 3,6,9는 오른손, 2,5,8,0은 현재 두손의 위치와 어느 손잡이 인지 비교
  4. 2,5,8,0을 누를 때는 누르는 번호와 양손의 위치를 비교해서 더 가까운 손으로 누른다. 이때 비교는 Math.abs(누를 번호 x,y - 왼손의 위치 x,y) 비교 Math.abs(누를 번호 x,y - 오른손의 위치 x,y) 를 해서 더 작은 값이 더 가까운 손이다.

풀이

첫 번째 풀이

풀이방법을 적은 그대로 코드를 짜려고 노력했다. 다른 부분들은 크게 달라진 것 같지 않은데, 생각해보니 배열로 키패드까지는 잘 만든것 같은데 [x][y] 배열에 들어있는 값이 키패드 숫자. 이런 형식으로 되어 있는데 키패드 값은 알기 쉽지만 생각해보니 배열의 index가 위치 정보인데 뭔가 배열에 접근하기가 어려웠다. 무슨 문제냐면 주어지는 조건은 키패드의 숫자(1,3,4)로 들어오는데 이떄 들어온 숫자가 key로 되어서 배열을 찾아야 하는데 그럴려면 배열을 일일이 돌아서 비교해서 찾아야 했는데 그건 너무 비효율적이었다. 그래서 저번에 문제 풀때 시도하지 못했던 js의 map을 써보기로 했다. js에는 c++이나 자바처럼 자료구조가 지원되거나 stl처럼 만들어진 것이 없어서 Object라는 형식으로 이용했다. key로 0~9까지 주고 각 key에 배열로 만든 키패드처럼 활용할 수 있도록 좌표를 줬다. 왼손의 시작점은 * 오른손은 # 이니까 각각 그에 맞는 좌표를 줬다. 1,4,7의 숫자가 오면 answer += ‘L’하고 왼손의 좌표를 해당 번호의 좌표로 변경. 3,6,9가 오면 answer += ‘R’ 추가 후 오른손 좌표 변경. 2.5.8.0 이 오면 먼저 각각의 손과 거리를 계산해서 더 가까이 있는 손이 번호를 클릭하게 하고 만약 같은 거리라면 어느 손잡이 인지에 따라서 누르도록 한다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
const KEYPAD_ROW = 4;
const KEYPAD_COLUNM = 3;

function solution(numbers, hand) {
    var answer = '';
    var leftHand = new Array(2);
    var rightHand = new Array(2);

    //js object로 map 비슷하게 구현
    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],
        0: [3, 1]
    };

    //각 손의 xy 초기 좌표를 index 를 저장함
    leftHand[0] = 3;
    leftHand[1] = 0;
    rightHand[0] = 3;
    rightHand[1] = 2;

    //로직함수인데 이렇게 모든 데이터를 다 줄거면 굳이 따로 함수로 뺄 이유가 없고, 각 기능마다 빼는 게 좋겠다.
    answer = checkData(numbers, hand, keypad, leftHand, rightHand, answer);

    return answer;
}


function checkData(numbers, hand, keypad, leftHand, rightHand, answer){
    var checkHand;
    for(let i = 0; i < numbers.length; i++){

        switch(numbers[i]){
            case 1:
            case 4:
            case 7:
                //왼손의 좌표를 누르는 번호의 위치로 바꿈
                leftHand[0] = keypad[numbers[i]][0]; 
                leftHand[1] = keypad[numbers[i]][1];
                answer += 'L';
                //해당 번호를 왼손으로 누름.
                break;
            case 3:
            case 6:
            case 9:
                rightHand[0] = keypad[numbers[i]][0];
                rightHand[1] = keypad[numbers[i]][1];
                answer += 'R';
                //해당 번호를 오른손으로 누름.
                break;
            case 2:
            case 5:
            case 8:
            case 0:
                //왼손과 오른손의 거리를 비교해서 누르는 손을 리턴 받음
                checkHand = distanceCheck(leftHand, rightHand, keypad[numbers[i]], hand);
                if(checkHand == 'R'){
                    rightHand[0] = keypad[numbers[i]][0];
                    rightHand[1] = keypad[numbers[i]][1];
                }
                else{
                    leftHand[0] = keypad[numbers[i]][0]; 
                    leftHand[1] = keypad[numbers[i]][1];
                }
                answer += checkHand;

                break;
            default:
                console.log("default");
                //오류일듯?
                break;
        }
    }
    return answer;
}

function distanceCheck(leftHand, rightHand, numberCoord, hand){
    var pressedHand;

    if(Math.abs(numberCoord[0] - leftHand[0]) + Math.abs(numberCoord[1] - leftHand[1])
      > Math.abs(numberCoord[0] - rightHand[0]) + Math.abs(numberCoord[1] - rightHand[1]))
        {
            pressedHand = "R";
        }
    else if(Math.abs(numberCoord[0] - leftHand[0]) + Math.abs(numberCoord[1] - leftHand[1])
      < Math.abs(numberCoord[0] - rightHand[0]) + Math.abs(numberCoord[1] - rightHand[1]))
        {
            pressedHand = "L";
        }
    else{
        pressedHand = (hand == "left") ? "L" : "R";
    }

    //리턴 값으로 왼손인지 오른손인지를 문자열로 반환
    return pressedHand;
}


Leave a comment