hoon's bLog

[Java] 프로그래머스 키패드 누르기 자바 본문

코딩테스트/프로그래머스

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

개발한기발자 2022. 6. 18. 12:42
반응형

문제 출처 : 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


문제에 텍스트가 많아지면

여김없이 찾아오는 난독증.....

하지만 그럼에도 불구하고 풀어야 한다

 

"우리는 답을 찾을 것이다. 늘 그랬듯이."

-인터스텔라-

[나의 풀이]

- 우리가 스마트폰을 사용할 때, 왼손은 왼쪽, 오른손은 오른쪽을 사용하여 고정으로 사용하는 좌/우측 패드 배열 선언

- '*' 과 '#' 버튼은 숫자가 아니므로 계산을 쉽게 하기 위해 각각 *=10, #=12로 대치

- 화면에서 보이는 전체 키패드를 가진 2차원 배열 선언

- 2차원 배열 기준, 왼손의 처음 위치는 '*'(mainKey[3][0]), 오른손은 '#'(mainKey[3][2])이고 그림은 다음과 같다.

1
mainKey[0][0]
2
mainKey[0][1]
3
mainKey[0][2]
4
mainKey[1][0]
5
mainKey[1][1]
6
mainKey[1][2]
7
mainKey[2][0]
8
mainKey[2][1]
9
mainKey[2][2]
*
mainKey[3][0]
0
mainKey[3][1]
#
mainKey[3][2]

 

import java.util.Arrays;

public class Solution {
    public String solution(int[] numbers, String hand) {
        String answer = "";
        Integer[] keypadL = {1,4,7,10};          //왼쪽손 고정 키패드, *=10
        Integer[] keypadR = {3,6,9,12};          //오른쪽손 고정 키패드, #=12
        Integer[][] mainKey = {                  //실제 키패드판
                {1,2,3},
                {4,5,6},
                {7,8,9},
                {10,0,12}
        };

        int xl = 3; //왼손 엄지 처음 위치
        int yl = 0;
        int xr = 3; //오른손 엄지 처음 위치
        int yr = 2;

        for (int i=0; i<numbers.length ; i++) { //누를 버튼 만큼 반복
            int pushNo = numbers[i];
            int rLen=0, lLen=0;                 //각 손과 누를 버튼 위치의 거리를 담을 변수

            for (int j=0; j< mainKey.length; j++) {
                for (int k=0; k< mainKey[k].length ; k++) { //실제 키패드판과 누를 버튼과 같은값 찾을때 까지 반복
                    if (pushNo == mainKey[j][k]){
                        if(Arrays.asList(keypadL).contains(pushNo)){    //왼쪽고정
                            answer += "L";
                            xl = j;
                            yl = k;
                        }else if(Arrays.asList(keypadR).contains(pushNo)){//오른쪽고정
                            answer += "R";
                            xr = j;
                            yr = k;
                        }else{	//가운데 줄인 경우, 절대값으로 좌/우측 가까운 거리 확인
                            rLen = Math.abs(xr-j) + Math.abs(yr-k);
                            lLen = Math.abs(xl-j) + Math.abs(yl-k);
                            if(rLen < lLen){
                                answer+="R";
                                xr = j;
                                yr = k;
                            }else if(rLen > lLen){
                                answer+="L";
                                xl = j;
                                yl = k;
                            }else{  //같을 때 주손으로 판별하기
                                if (hand.equals("right")){
                                    answer+="R";
                                    xr = j;
                                    yr = k;
                                }else{
                                    answer+="L";
                                    xl = j;
                                    yl = k;
                                }
                            }
                        }
                    }else{
                        continue;
                    }
                }
            }
        }
        return answer;
    }
}

으으.....정말 내가 짜고 돌아가는 코드지만 정말 극혐이다...

19년도의 여파였을까? 덕분에 20년도 문제는 선녀였지만...

나의 풀이는 너무 역하다ㅠㅠㅠㅠㅠㅠㅠㅠㅠㅠㅠ

설마 이런 문제도 Stream으로 되는건 아니겠...지??...

[다른 사람의 풀이-1]

class Solution {
    //0부터 9까지 좌표 {y,x}
    int[][] numpadPos = {
            {3,1}, //0
            {0,0}, //1
            {0,1}, //2
            {0,2}, //3
            {1,0}, //4
            {1,1}, //5
            {1,2}, //6
            {2,0}, //7
            {2,1}, //8
            {2,2}  //9
    };
    
    //초기 위치
    int[] leftPos = {3,0};
    int[] rightPos = {3,2};
    String hand;
    
    public String solution(int[] numbers, String hand) {
        this.hand = (hand.equals("right")) ? "R" : "L";

        String answer = "";
        for (int num : numbers) {
            String Umji = pushNumber(num);
            answer += Umji;

            if(Umji.equals("L")) {leftPos = numpadPos[num]; continue;}
            if(Umji.equals("R")) {rightPos = numpadPos[num]; continue;}
        }
        return answer;
    }

    //num 버튼을 누를 때 어디 손을 사용하는가
    private String pushNumber(int num) {
        if(num==1 || num==4 || num==7) return "L";
        if(num==3 || num==6 || num==9) return "R";

        // 2,5,8,0 일때 어디 손가락이 가까운가
        if(getDist(leftPos, num) > getDist(rightPos, num)) return "R";
        if(getDist(leftPos, num) < getDist(rightPos, num)) return "L";

        //같으면 손잡이
        return this.hand;
    }

    //해당 위치와 번호 위치의 거리
    private int getDist(int[] pos, int num) {
        return Math.abs(pos[0]-numpadPos[num][0]) + Math.abs(pos[1]-numpadPos[num][1]);
    }
}

[정리]

- 핵심은 눌러야 할 버튼의 거리계산, 가운데 줄 버튼 시 조건, 주 사용손에 따른 조건을 나누는 것이 관건!

- 각종 조건과 반복을 해야하는 상황이 발생 하다보니 for문과 if문이 많아질 수 밖에 없는 문제...

- 함수를 기능별로 분리해서 코딩하는 방법을 통해, 좀 더 기능별로 알아보기 쉽게 하는 것도 중요할 듯!

 

개인피셜 난이도 : ★☆☆

다소 노가다가 요구되는 문제이지만,

노가다도 빠른 사고로 이해하고 정리하는게 중요한 것 같다!

저번 2019년 문제에 비하면 그렇게 어렵지 않은 문제였다.

모든 알고리즘 문제가 그렇겠지만,

규칙과 패턴을 빨리 파악하는게 중요한 것 같다.

 

뭔가 카카오 문제를 연이어 해결하니 뿌듯하지만,

하지만 이 역시 1단계! 1단계이기 때문에,

정진, 또 정진!!!!!!

 

끝!

728x90
반응형