Coding/코딩테스트

#67256 키패드 누르기

서머스 2021. 7. 17. 20:49

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가지 방향으로만 이동할 수 있으며 키패드 이동 한 칸은 거리로 1에 해당합니다.
  2. 왼쪽 열의 3개의 숫자 1, 4, 7을 입력할 때는 왼손 엄지손가락을 사용합니다.
  3. 오른쪽 열의 3개의 숫자 3, 6, 9를 입력할 때는 오른손 엄지손가락을 사용합니다.
  4. 가운데 열의 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 해주세요.

 

--------------------------------------------------------

 

level1 문제인데도 생각보다 쉽지 않아서 난항을 겪었던 문제.. 😑

 

이 문제에서 가장 핵심인 점은, 키패드간의 거리가 정말 말그대로 '거리'를 구하는게 아니라는 것이다.

1에서 5를 간다고 가정하면, 1에서 바로 5를 가니까 루트2! 가 아니고

1에서 2를거쳐 5를 가기 때문에 거리는 2이다.

그리고 2에서 5를 갈 때는 2->3->4->5 가 아니고, 아래로 한칸만 내려가면 되기 때문에 거리가 1이다.

 

 

처음에는 2차원 배열을 만들어서 [i][j] 인덱스 값을 비교하려고 했다.

그렇게 했더니 식이 너무 복잡해져서, 다른 방법을 강구했다.

(사실 l1 문제가 이렇게 어려울 리가 없다고 생각하기도 했다.)

 

 

위 아래로 값을 구할 때는 어떻게 할까 고민했다

그래서 처음에는 while문을 이용해서, 각각의 차이값 = 절댓값(왼손/오른손-numbers[i]) 이 3을 넘으면 2를 계속 빼도록 했다.

// while(left_diff>=3)    left_diff-=2;
// while(right_diff>=3)   right_diff-=2;

내가 하면서도 이건좀 아닌것같은데? 했는데 역시 문제가 발생했다.

3->8 로 간다고 가정했을 때, 3->6->9->8 로 정말 거리값이 3인 경우도 있기 때문이었다.

 

질문탭과 구글링을 통해 

int calculate_diff(int fin_num, int number){
    int diff= abs(fin_num-number);
    diff= diff/3 + diff%3;
    return diff;
}

차이값 =차이값/3 + 차이값%3

의 수식으로 해결했다!

차이값/3 의 경우, 위<->아래로 움직일 때를 count해준다.

차이값%3 의 경우, 좌우로 움직일 때의 값이다. 좌 우로는 그래봤자 1,2값 밖에 없기 때문에.

 

인턴도 아무나 하는게 아니구나 싶었던 ... 😑

 

코드 전문

#include <string>
#include <vector>
#include <iostream>
#include <cctype>
#include <cmath>
using namespace std;

int calculate_diff(int fin_num, int number){
    int diff= abs(fin_num-number);
    diff= diff/3 + diff%3;
    return diff;
}
string solution(vector<int> numbers, string hand) { // hand: left or right
    string answer = ""; //각 번호를 누른 엄지손가락이 왼손인 지 오른손인 지 LRLRRR 이런식
    int left_num=10, right_num=12;
    for(int i=0 ; i< numbers.size();i++)
    {
        switch(numbers[i]){
            case 1: case 4: case 7:
                answer.push_back('L'); 
                left_num = numbers[i];
                cout<<"왼쪽1"<<endl;
                break;
            case 3: case 6: case 9:
                answer.push_back('R'); 
                right_num = numbers[i];
                cout<<"오른쪽1"<<endl;
                break;
            case 0: 
                numbers[i]= 11;//로 해야함
            case 2:
            case 5:
            case 8:
                //왼손기준 ~ numbers[i]값까지의 인덱스값의 차이를 구한다
                int left_diff = calculate_diff(left_num, numbers[i]);
                int right_diff = calculate_diff(right_num, numbers[i]);
               // while(left_diff>=3)    left_diff-=2;
               // while(right_diff>=3)   right_diff-=2;
                if (left_diff == right_diff )
                {
                    //char temp_hand = toupper(hand.substr(0,1));
                    char temp_hand = toupper(hand[0]);//hand.substr(0,1);
                    answer.push_back(temp_hand);//hand(뭔손잡이)의 앞에 한글자만 추가
                    if(temp_hand == 'L')
                        left_num = numbers[i];
                    else// if(temp_hand == 'R')
                        right_num = numbers[i];
                }
                else if (left_diff > right_diff )//왼쪽 더클때 = 오른쪽이 더 가까움
                {
                    answer.push_back('R'); 
                    right_num = numbers[i];       
                }
                else//오른쪽이 더 클때 = 왼쪽이 더 가까움
                {
                    answer.push_back('L'); // >3일 때는 -3해줘야 함
                    left_num = numbers[i];
                }
        }
    }
    return answer;

}

조금 지저분하다.

'Coding > 코딩테스트' 카테고리의 다른 글

#12921 에라토스테네스의 체  (0) 2021.07.28
LNK2019 관련 에러 해결하기  (0) 2021.07.27
#12926 시저 암호  (0) 2021.02.17
#17677 뉴스 클러스터링  (0) 2020.11.05
#1181 단어 정렬  (0) 2020.10.29