알고리즘/프로그래머스

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

정석이 2021. 11. 22. 20:07

 

https://programmers.co.kr/learn/courses/30/lessons/67256

 

코딩테스트 연습 - 키패드 누르기

[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"

programmers.co.kr

 

 

문제

 

 

 


 

내가 푼 방법

 

 

우선 1 4 7 나오면 무조건 L, 3 6 9 나오면 무조건 R인건 자명하다.

 

그리고 2 5 8 0 에서 가까운걸 찾아야하니까 마지막에 누른 L과 R을 따로 저장해놓는다.

 

 

2 5 8 0 얘네가 것참 어려웠는데.. 2차원 배열을 써야하나 싶다가도 그 안에 숫자 찾으려면 2중 for문 써야할 것 같고... 좀 아닌 것 같아서 헤맸다^^

 

 

 

그냥 1차원 배열에 얘네의 행열 배열을 저장하기로 했다.

 

 

 

 

요렇게 패드 숫자는 numbers[] 배열에 들어있으니까 numbers[] - 1 의 행값을 사용한다.

 

 

 

 

패드

 

요런 느낌이닷. 그리고 예를 들어 left = 4, right = 9에 있는데 8을 입력받았다.

 

그러면 left = |2-1| + |1-0| = 2

         right = |2-2| + |1-2| = 1 로 right 손이 가게된다.

 

이런식으로 좌표가 필요하기 때문에 배열에 넣어줬다.

 

 

 

 

코드

 

class Solution {
    public String solution(int[] numbers, String hand) {
        String answer = "";
        
        int phone[][] = {{0,0}, {0,1}, {0,2}, {1,0}, {1,1}, {1,2}, {2,0}, {2,1}, {2,2}, {3,0}, {3,1}, {3,2}};
        int left = 10, right = 12;
        String middle;
        
        if(hand.equals("right")) middle = "R";
        else middle = "L";
        
        
        for(int i = 0; i < numbers.length; i++){
            if(numbers[i] == 1 || numbers[i] == 4 || numbers[i] == 7){ // 왼손
                answer += "L";
                left = numbers[i];
            }
            else if(numbers[i] == 3 || numbers[i] == 6 || numbers[i] == 9){ // 오른손
                answer += "R";
                right = numbers[i];
            }
            else{ // 가운데 누를 때

                if(numbers[i] == 0) numbers[i] = 11;
                else if(left == 0) left = 11;
                else if(right == 0) right = 11;
                ///0은 phone 배열에서 10행이다.
                
                    int leftPoint = Math.abs(phone[numbers[i]-1][0] - phone[left-1][0]) + Math.abs(phone[numbers[i]-1][1] - phone[left-1][1]);
                    int rightPoint = Math.abs(phone[numbers[i]-1][0] - phone[right-1][0]) + Math.abs(phone[numbers[i]-1][1] - phone[right-1][1]);
                    
                    if(leftPoint > rightPoint) {
                        answer += "R";
                        right = numbers[i];
                    }
                    else if(leftPoint < rightPoint) {
                        answer += "L";
                        left = numbers[i];
                    }
                    else{ 
                        answer += middle;
                        if(middle.equals("R")) right = numbers[i];
                        else left = numbers[i];
                    }
            }
            
        }
        
        return answer;
    }
}

 

 

 

Math.abs()을 사용해서 절댓값을 사용한다.

 

중간값을 하고 left, right 업데이트 안해서 오류났었따....ㅋ

 

 

사실 2차원 배열은 쓰기 싫은데.. 뭐 규칙도 못찾겠고.... 그래서 배열 쓰는법 다른사람꺼 살짝 봤다.ㅎㅎ

 

 

 

 

 

 


 

다른사람 코드

 

 

 

 

오 내가 

 

String middle;       
if(hand.equals("right")) middle = "R";
else middle = "L";

 

요따구로 짠 코드를

 

 this.hand = (hand.equals("right")) ? "R" : "L";

 

일케 깔끔하게 짰다. 오오....

 

pushNumber라는 함수를 만들어서 코드가 굉장히 깔끔하다. 가운데 숫자를 누르는 경우도 getDist 함수를 사용...

 

numpadPos 배열이 0부터 시작해서 매우 편리함.... 왜 저렇게 안했지??

 

 

 

 

 

다음 코드

class Solution {
    public String solution(int[] numbers, String hand) {
        String answer = "";
        StringBuilder answerBuilder = new StringBuilder();
        String[][] phone = {
                {"1", "2", "3"},
                {"4", "5", "6"},
                {"7", "8", "9"},
                {"*", "0", "#"},
        };
        int leftX = 3;
        int leftY = 0;
        int rightX = 3;
        int rightY = 2;
        for (int i = 0; i < numbers.length; i++) {
            for (int j = 0; j < phone.length; j++) {
                    for (int k = 0; k < phone[j].length; k++) {
                    if (String.valueOf(numbers[i]).equalsIgnoreCase(phone[j][k])) {
                        System.out.println("number[====="+numbers[i]);
                        if (k == 0) {
                            answerBuilder.append("L");
                            leftX = j;
                            leftY = k;
                        } else if (k == 2) {
                            answerBuilder.append("R");
                            rightX = j;
                            rightY = k;
                        } else {
                            int leftDistinct = Math.abs(j-leftX)+Math.abs(k-leftY);
                            int rightDistinct = Math.abs(j-rightX)+Math.abs(k-rightY);
                            if (leftDistinct > rightDistinct) {
                                answerBuilder.append("R");
                                rightX = j;
                                rightY = k;
                            } else if (leftDistinct < rightDistinct) {
                                answerBuilder.append("L");
                                leftX = j;
                                leftY = k;
                            } else {
                                answerBuilder.append(hand.equalsIgnoreCase("right") ? "R" : "L");
                                if (hand.equalsIgnoreCase("right")) {
                                    rightX = j;
                                    rightY = k;
                                } else {
                                    leftX = j;
                                    leftY = k;
                                }
                            }
                        }
                    }
                }
            }
        }
        answer = String.valueOf(answerBuilder);
        return answer;
    }
}

 

ㄹㅇ 키패드대로 2차원 배열을 만든 코드.... 진짜 짜기 힘들어보인다.ㄷㄷ

 

 

numbers[] 값을 string.valueOf()를 사용해 string화 하고 equalsIgnoreCase를 사용해서 비교했다.

 

equalsIgnoreCase는 대소문자 구분 없이 문자열만 비교할 때 자주 사용한다고 한다. 문자열이 같으면 true, 다르면 false를 리턴한다.

 

 

phone 2차원 배열의 값과 비교해서 x,y 좌표를 업데이트하는 식으로 아주아주 직관적으로 푼 코드...

 

 

equalsIgnoreCase를 쓴게 신기하다...