본문 바로가기

CS ﹒ Algorithm/Programmers

프로그래머스 문제풀이 (5) 키패드 누르기

 

 

그냥 각 키패드를 좌표 (배열)로 생각하고 하면 전혀 어려울 게 없는 문제다.

그런데 좌표 하드코딩하는 게 자존심 상해서 다른 방법을 찾아 헤매다가 3시간을 날렸다.

근데 기껏 풀고나서 확인해보니 그냥 배열 하드코딩하는 게 더 직관적이고 깔끔하다.

쩝.. 물론 내가 조금 희한하게 풀기도 했다.

 

아무튼 문제를 풀고 싶어서 찾아온 누군가가 있을 수 있으니 빠르게 설명하겠다.

 

 

 

키패드의 *, 0, #을 10, 11, 12로 치환하고

y축을 각 숫자 n에 대해 n-1/3을 한다면 0,1,2,3을 얻을 수 있다.

x축도 마찬가지로 각 숫자 n에 대해 n-1%3을 한다면 0,1,2를 얻을 수 있다.

이게 배열을 하드코딩하지 않고 푸는 방법이고.

 

만약 좌표를 하드코딩할 거라면 저건 필요 없다.

다만 n에 대해 n%3을 했을 때 x축은 각각 1,2,0을 얻을 수 있다는 점을 활용해 조건문을 조금이나마 간소화시킬 수 있다.

몰라도 푸는 것에 아무 지장 없음.

 

성의 없어보일 수도 있지만 여기까지 봤으면 다 본 것이다.

혹시 여기까지 봤어도 못 풀겠다면 조금만 더 내려보자.

 

 

 

 

 

 

 

 

 

 

 

 

 

1. n은 우리가 임의로 11이라고 정한 거지 문제에서는 0으로 들어온다.

n을 변경해주고 있는지 확인해보자.

 

2. 좌표 거리 계산은 그냥 x축 y축 각각 빼주고 절대값으로 반환 받으면 그만이다.

 

 

 

 

 

 

 

 

 

 

 

 

 

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
class Solution {
    public String solution(int[] numbers, String hand) {
        int left = 10;
        int right = 12;
        StringBuilder sb = new StringBuilder();
        
        for (int n : numbers) {
            if ( n == 0 ) { n = 11; }
            
            if ( n%3 == 1 ) {
                left = n;
                sb.append("L");
            }
            
            if ( n%3 == 2 ) {
                if (getPosition(left,right,n).equals("LEFT")) {
                    left = n;
                    sb.append("L");
                }
                else if (getPosition(left,right,n).equals("RIGHT")) {
                    right = n;
                    sb.append("R");
                }
                else {
                    if (hand.equals("left")) {
                        left = n;
                        sb.append("L");
                    } else {
                        right = n;
                        sb.append("R");
                    }
                }
            }
            
            if ( n%3 == 0 ) {
                right = n;
                sb.append("R");
            }
        }
        
        return sb.toString();
    }
    
    public String getPosition(int left, int right, int num) {
        
        int leftX = (left-1)/3;
        int leftY = (left-1)%3;
        
        int rightX = (right-1)/3;
        int rightY = (right-1)%3;
        
        int numX = (num-1)/3;
        int numY = (num-1)%3;
        
        int resultL = Math.abs(leftX-numX) + Math.abs(leftY-numY);
        int resultR = Math.abs(rightX-numX) + Math.abs(rightY-numY);
        
        if (resultL == resultR) return "DRAW";
        
        return (resultL > resultR) ? "RIGHT" : "LEFT";
    }
}
cs

 

첫번째 방식.

아마 별다른 설명이 없어도 위에 좌표 구하는 방법을 설명해놨으니 다 이해가 될 것이다.

 

String으로 반환해서 답을 구하는 특이한 행동을 했는데 왜 그랬는지는 모르겠다..

너무 오래동안 한 문제만 보다보니 잠시 영혼이 가출했었나보다.

 

리팩터링으로 코드를 조금 더 짧게 만들 수는 있지만, 이미 내가 생각한 것보다 너무 복잡하게 만들어져서 의욕을 상실했다

내가 이걸 작성하기 위해 3시간을 썼다고..?

 

다른 사람들 풀이도 찾아봤는데 큰 틀에서는 별 차이가 없다.

가독성도 여전히 구리다.

 

 

 

 

 

 

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
class Solution {
    public String solution(int[] numbers, String hand) {
        int[][] keypad = { {0,0}, {0,1}, {0,2},
                          {1,0}, {1,1}, {1,2},
                          {2,0}, {2,1}, {2,2},
                          {3,0}, {3,1}, {3,2} };
        StringBuilder sb = new StringBuilder();
        int left = 10;
        int right = 12;
        
        for ( int n : numbers ) {
            if (n==0) n=11;
            if (n%3 == 0) {
                right = n;
                sb.append("R");
            }
            if (n%3 == 1) {
                left = n;
                sb.append("L");
            }
            if (n%3 == 2) {
                int distanceFromLeft = getDistance(keypad[left-1], keypad[n-1]);
                int distanceFromRight = getDistance(keypad[right-1], keypad[n-1]);
                
                if ( distanceFromLeft > distanceFromRight ) {
                    right = n;
                    sb.append("R");
                }
                if ( distanceFromLeft < distanceFromRight ) {
                    left = n;
                    sb.append("L");                
                }
                if ( distanceFromLeft == distanceFromRight ) {
                    if ( hand.equals("right") ) {
                        right = n;
                        sb.append("R");
                    } else {
                        left = n;
                        sb.append("L");
                    }
                }
            }
        }   
        return sb.toString();
    }
    
    public static int getDistance(int[] keypadPos, int[] numPos) {
            int y = Math.abs(keypadPos[0- numPos[0]);
            int x = Math.abs(keypadPos[1- numPos[1]);       
            return x+y;
        }
}
cs

 

두번째 방식. 내 기준에서는 그냥 좌표 하드코딩하는 게 제일 깔끔해 보이더라.

나는 빨리 풀고 공부하고 싶어서 if로 도배했는데 switch를 활용하면 훨씬 더 보기 좋아질 것 같다.