728x90
반응형

2021.06.26

문제명 : 2020 카카오 인턴십 - 키패드 누르기

사용언어 : Javascript

개발 시간 : 70분

 

 

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

[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은 왼손 3,6,9는 오른손 그 외는 가까운 손이 누릅니다.

만약 거리가 같다면 왼손잡이는 왼손이, 오른손잡이는 오른손이 누릅니다.

 

📢 입출력 예

차근히 따라 하시면 입출력 예는 이해가 될 것입니다.

 

🔑 문제 풀이

키패드의 최하단에  *  0  # → 10  11  12 라고 바꿔서 생각해보았습니다.

그럼 1부터 12까지의 키패드가 됩니다.

(1,4,7)과 (3,6,9)는 각각 왼손, 오른손이 누르기로 정해져 있으므로 가운데 숫자를 누를 때만 생각해봤습니다.

 

⁕ 왼손 시작일 경우

예를 들어, 만약 왼손이 1에 위치하고, 다음 눌러야 할 숫자가 5일 경우를 생각해봅시다.

무조건 오른쪽으로 한 칸은 이동해야 합니다.

그리고, 줄마다의 차이는 3씩이므로 3씩 몇 번 이동해야 하는지를 확인합니다.

1(현재 위치) + 1 + (3 * n번) = 5(도착 위치)

1+n 만큼 이동하는 횟수가 필요합니다. n은 1이므로 총 거리 2만큼 이동합니다.

 

⁕ 오른손 시작일 경우

예를 들어, 만약 오른손이 6에 위치하고, 다음 눌러야 할 숫자가 2일 경우를 생각해봅시다.

무조건 왼쪽으로 한 칸은 이동해야 합니다.

그리고, 줄마다의 차이는 3씩이므로 3씩 몇 번 이동해야 하는지를 확인합니다.

6(현재 위치) - 1 + (3 * n번) = 2(도착 위치)

1+n 만큼 이동하는 횟수가 필요합니다. 

여기서 n은 -1입니다.

6에서 2로 이동하기까지는 2칸이 걸리는 것을 고려해보았을 때, n은 절댓값 처리가 필요할 것으로 예상됩니다.

따라서 1+(|-1|) = 2만큼 이동합니다.

 

 

왼손, 오른손 모두

만약 손가락이 가운데 위치해 있을 때 가운데 숫자를 눌러야 한다면 처음 +1 또는 -1 과정은 생략될 것입니다.

이미 가운데로 이동되어있기 때문입니다.

 

 

이를 코드로 옮겨보면,

function solution(numbers, hand) {
    var answer = '';
    var left = 10;	// *
    var right = 12;	// #
    
    for(var i=0; i<numbers.length; i++){
        if(numbers[i] == 0){ // 0
            numbers[i] = 11;
        }
         
        // 무조건 왼손
        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 {
            var L = 0; // 현재 왼손이 위치한 숫자 키패드
            var R = 0; // 현재 오른손이 위치한 숫자 키패드
            
            // 왼손이 좌측에 위치해있다면
            if(left == 1 || left == 4 || left == 7 || left == 10){
                L = Math.abs((numbers[i] - (left + 1)) / 3) + 1;
            }
            // 왼손이 가운데 위치해있다면
            else{ // 2 5 8 0(11)
                L = Math.abs((numbers[i] - left) / 3);
            }
            
            // 오른이 좌측에 위치해있다면
            if(right == 3 || right == 6 || right == 9 || right == 12){
                R = Math.abs((numbers[i] - (right - 1)) / 3) + 1;
            }
            // 오른손이 가운데 위치해있다면
            else{ // 2 5 8 0(11)
                R = Math.abs((numbers[i] - right) / 3);
            }
        
        
        	// 거리가 같다면
            if(L == R){
                if(hand == "right"){
                    answer += 'R';
                    right = numbers[i];
                }else if(hand == "left"){
                    answer += 'L';
                    left = numbers[i];
                }
            }else if(L < R){	// 왼손이 가깝다면
                answer += 'L';
                left = numbers[i];
            }else if(L > R){	// 오른손이 가깝다면
                answer += 'R';
                right = numbers[i];
            }
    }
    }
    
    return answer;
}

 

🔔 새로 알게 된 점

정답을 제출 후 다른 사람 풀이를 확인하니, 키패드의 숫자들은 배열에 담고 관리하는 소스들이 많았습니다.

그중 인상적이었던 것은 키패드 숫자들을 행렬처럼 관리하는 것입니다.

const grid = [

                [0,-2], [-1,1], [0,1],

                [1,1], [-1,0], [0,0],

                [1,0], [-1,-1], [0,-1],

                [1,-1], [-1,-2], [1,-2]

];

이렇게 관리하면 행끼리의 거리 + 열끼리의 거리만큼 이동거리가 구해진다는 것을 이용했다면 더 간단하게 소스를 짤 수 있었을 것 같습니다.

728x90
반응형

+ Recent posts