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
스마트폰 전화 키패드의 각 칸에 다음과 같이 숫자들이 적혀 있습니다.

이 전화 키패드에서 왼손과 오른손의 엄지손가락만을 이용해서 숫자만을 입력하려고 합니다.
맨 처음 왼손 엄지손가락은 * 키패드에 오른손 엄지손가락은 # 키패드 위치에서 시작하며, 엄지손가락을 사용하는 규칙은 다음과 같습니다.
- 엄지손가락은 상하좌우 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 해주세요.
--------------------------------------------------------
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 |