[프로그래머스] (C++) 키패드 누르기 <2020 카카오 인턴십>

winluck·2023년 7월 4일
1

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

문제

문제에서 추출할 수 있는 정보는 다음과 같다.

  • 1, 4, 7은 무조건 left가, 3, 6, 9는 무조건 right가 담당한다.
  • 초기 왼손 엄지는 *에서, 오른손 엄지는 #에서 시작한다.
  • 2, 5, 8, 0의 경우 양 엄지의 현재 키패드로부터 그곳까지의 거리가 가장 짧은 엄지가 움직인다.
  • 거리가 같을 경우 hand 문자열의 값에 따라 결정한다.

입출력

왼손 거리와 오른손 거리를 그때마다 계산하거나 따로 저장해야 함을 알 수 있다.

먼저 1, 4, 7과 3, 6, 9에 대해서는 큰 문제가 없다는 것을 바로 알 수 있다.
문제는 가운데 다이얼을 어느 쪽이 눌러야 하냐인데.. 이는 결국 위와 같이 거리를 계산해야 한다는 필연적인 과제가 나타난다.

나는 직접 모든 다이얼들의 2, 5, 8, 0까지의 거리를 배열을 선언하여 계산해주었다.

*을 10으로, #을 12로 하여 양쪽 다이얼들의 2,5,8,0까지의 거리(즉 32개의 값)를 직접 저장하고, 가운데 다이얼들의 서로간의 거리 역시 계산해두자.

시행착오

  • 처음에 이 문제를 각각의 위치에 따라 거리를 계산하는 깔끔한 공식을 도출하기 위해 고민했으나, 시간이 너무 지체되어 직접 거리를 저장하는 방식을 채택하였다.

  • 당연히 훨씬 더 깔끔한 로직들이 많겠지만... 일단 문제를 통과하는게 우선이 아닐까? 라는 생각에 정면돌파하기로 했다. 만약에 다이얼이 많아지면 절대 이렇게 할 수 없을 것이기에, 세련된 방법에 대해서도 찾아보는 시간을 가져야겠다.

소스 코드

#include <string>
#include <vector>
#include <algorithm>

using namespace std;

string solution(vector<int> numbers, string hand) {
    string answer = "";
    int nowleft = 10; // 초기 위치
    int nowright = 12; 
    
    int move[13][13];
    
    // 각 다이얼에서 2까지의 거리
    move[1][2] = move[3][2] = 1;
    move[4][2] = move[6][2] = 2;
    move[7][2] = move[9][2] = 3;
    move[10][2] = move[12][2] = 4; 
    
    // 각 다이얼에서 5까지의 거리
    move[1][5] = move[3][5] = 2;
    move[4][5] = move[6][5] = 1;
    move[7][5] = move[9][5] = 2;
    move[10][5] = move[12][5] = 3; 
    
    // 각 다이얼에서 8까지의 거리
    move[1][8] = move[3][8] = 3;
    move[4][8] = move[6][8] = 2;
    move[7][8] = move[9][8] = 1;
    move[10][8] = move[12][8] = 2; 
    
    // 각 다이얼에서 0까지의 거리
    move[1][0] = move[3][0] = 4;
    move[4][0] = move[6][0] = 3;
    move[7][0] = move[9][0] = 2;
    move[10][0] = move[12][0] = 1; 
    
    // 2, 5, 8, 0 다이얼의 서로간의 거리
    move[2][2] = move[5][5] = move[8][8] = move[0][0] = 0; 
    move[2][5] = move [5][8] = move[8][0] = move[5][2] = move[8][5] = move[0][8] = 1;
    move[2][8] = move[5][0] = move[8][2] = move[0][5] = 2;
    move[2][0] = move[0][2] = 3;
    
    for(int i=0; i<numbers.size(); i++){
        if(numbers[i] %3 == 1){ // 1, 4, 7은 왼쪽이 담당
            nowleft = numbers[i];
            answer += 'L';
        } else if(numbers[i] %3 == 0 && numbers[i] != 0){ // 3, 6, 9는 오른쪽이 담당
            nowright = numbers[i];
            answer += 'R';
        } else{ // 2, 5, 8, 0인 경우
            if(move[nowleft][numbers[i]] > move[nowright][numbers[i]]){ // 두 엄지와 다이얼 간 거리 비교
                answer += 'R';
                nowright = numbers[i];
            } else if(move[nowleft][numbers[i]] < move[nowright][numbers[i]]){
                answer += 'L';
                nowleft = numbers[i];
            } else { // 두 거리가 같을 경우 오른손잡이인지 왼손잡이인지 판단
                if(hand == "right"){
                    answer += 'R';
                    nowright = numbers[i];
                } else {
                    answer += 'L';
                    nowleft = numbers[i];
                }
            }
        } 
    }
    return answer;
}

교훈

  • 처음부터 세련된 방법으로 해결하는 것도 좋지만, 코드 퀄리티가 낮더라도 일단 총력전으로 문제를 통과하는 것도 중요한 능력이다.
profile
Discover Tomorrow

0개의 댓글