프로그래머스 키패드 (카카오 2020 인턴쉽) java

최준호·2021년 7월 13일
0

algorithm

목록 보기
6/39

문제

스마트폰 전화 키패드의 각 칸에 다음과 같이 숫자들이 적혀 있습니다.

이 전화 키패드에서 왼손과 오른손의 엄지손가락만을 이용해서 숫자만을 입력하려고 합니다.
맨 처음 왼손 엄지손가락은 * 키패드에 오른손 엄지손가락은 # 키패드 위치에서 시작하며, 엄지손가락을 사용하는 규칙은 다음과 같습니다.

엄지손가락은 상하좌우 4가지 방향으로만 이동할 수 있으며 키패드 이동 한 칸은 거리로 1에 해당합니다.
왼쪽 열의 3개의 숫자 1, 4, 7을 입력할 때는 왼손 엄지손가락을 사용합니다.
오른쪽 열의 3개의 숫자 3, 6, 9를 입력할 때는 오른손 엄지손가락을 사용합니다.
가운데 열의 4개의 숫자 2, 5, 8, 0을 입력할 때는 두 엄지손가락의 현재 키패드의 위치에서 더 가까운 엄지손가락을 사용합니다.
4-1. 만약 두 엄지손가락의 거리가 같다면, 오른손잡이는 오른손 엄지손가락, 왼손잡이는 왼손 엄지손가락을 사용합니다.
순서대로 누를 번호가 담긴 배열 numbers, 왼손잡이인지 오른손잡이인 지를 나타내는 문자열 hand가 매개변수로 주어질 때, 각 번호를 누른 엄지손가락이 왼손인 지 오른손인 지를 나타내는 연속된 문자열 형태로 return 하도록 solution 함수를 완성해주세요.

제한 사항

  • numbers 배열의 크기는 1 이상 1,000 이하입니다.
  • numbers 배열 원소의 값은 0 이상 9 이하인 정수입니다.
  • hand는 "left" 또는 "right" 입니다.
  • "left"는 왼손잡이, "right"는 오른손잡이를 의미합니다.
  • 왼손 엄지손가락을 사용한 경우는 L, 오른손 엄지손가락을 사용한 경우는 R을 순서대로 이어붙여 문자열 형태로 return 해주세요.

입출력 예시

풀이

public class Kakao2020InternKeypad {
    public static void main(String[] args) {
        Kakao2020InternKeypad k = new Kakao2020InternKeypad();
        int[] numbers = {7, 0, 8, 2, 8, 3, 1, 5, 7, 6, 2};
        String hand = "left";
        String solution = k.solution(numbers, hand);
        System.out.println("solution = " + solution);
    }
    public String solution(int[] numbers, String hand) {
        String answer = "";
        StringBuilder sb = new StringBuilder();
        //2차 배열로 키패드를 구성
        int[][] keypad = {
                {1,2,3},
                {4,5,6},
                {7,8,9},
                {-1,0,-1}
        };
        int[] leftPoint = new int[2];
        int[] rightPoint = new int[2];

        leftPoint[0] = 3;
        leftPoint[1] = 0;

        rightPoint[0] = 3;
        rightPoint[1] = 2;
        //1,4,7은 왼손 3,6,9는 오른손
        for(int num : numbers){
            if(num==1 || num==4 || num == 7){
                sb.append("L");
                //포인터 값 변경
                leftPoint = search(keypad,num);
            }else if(num==3 || num==6 || num==9){
                sb.append("R");
                rightPoint = search(keypad,num);
            }else{
                int[] result = search(keypad,num);
                int left = 0;
                int right = 0;
                //2,5,8,0은 2차 배열의 배열 값으로 얼마나 가까운지 검사
                left = Math.abs(leftPoint[0]-result[0]) + Math.abs(leftPoint[1]-result[1]);
                right = Math.abs(rightPoint[0]-result[0]) + Math.abs(rightPoint[1]-result[1]);

                if(left > right){
                    sb.append("R");
                    rightPoint = result;
                }else if(right > left){
                    sb.append("L");
                    leftPoint = result;
                }else{
                    //같다면 주로 사용하는 손 검사
                    if(hand.equals("left")){
                        sb.append("L");
                        leftPoint = result;
                    }else{
                        sb.append("R");
                        rightPoint = result;
                    }
                }
            }
        }
        answer = sb.toString();
        return answer;
    }

    private int[] search(int[][] keypad, int num){
        int[] result = new int[2];
        int row = 0;
        for(int[] padRow : keypad){
            int key=0;
            for(int p : padRow){
                if(p == num){
                    result[0] = row;
                    result[1] = key;
                    return result;
                }
                key++;
            }
            row++;
        }
        return result;
    }
}

문제를 처음보고 2차원 배열로 풀어야겠다! 라는 생각보다 와 이게 왜 1레벨 문제지? 읽기도 힘든 문젠데... 라고 생각하고 안풀까 했었는데 문제를 다 읽어보고 정리를 해보니 생각보다 어려운 문제는 아니였다. 또한 문제를 풀어보고 다른 분들의 풀이를 보니 대부분 2차원 배열로 풀었더라ㅎㅎ 다행이다 증말 ㅜㅜ

  1. 2차원 배열로 키패드 구성하기
  2. 왼손의 위치와 오른손의 위치를 기억할 포인터 역할 배열 만들기
  3. 포인터의 위치를 계산하기 위한 절대값으로 계산

이 세가지만 기억하면 될거 같다. 물론 포인터를 나처럼 배열로 만들 필요는 없다. 다른 풀이를 보니 x1,y1 / x2, y2로 해서도 푸셨더라... 난 왜 그 생각을 못했지?ㅜ 하지만 그 풀이 방법도 저 위에 3가지 방법으로 푼거 같았다. 전 문제가 완전 탐색 문제여서 오히려 더 쉬웠던 것 같다.

문제가 길어도 잘 읽어보면 쉬울지도?

profile
코딩을 깔끔하게 하고 싶어하는 초보 개발자 (편하게 글을 쓰기위해 반말체를 사용하고 있습니다! 양해 부탁드려요!) 현재 KakaoVX 근무중입니다!

0개의 댓글