설명
스마트폰 전화 키패드의 각 칸에 다음과 같이 숫자들이 적혀 있습니다.
이 전화 키패드에서 왼손과 오른손의 엄지손가락만을 이용해서 숫자만을 입력하려고 합니다.
맨 처음 왼손 엄지손가락은 * 키패드에 오른손 엄지손가락은 # 키패드 위치에서 시작하며, 엄지손가락을 사용하는 규칙은 다음과 같습니다.
- 엄지손가락은 상하좌우 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 해주세요.
입출력 예시
입출력 예시 대한 설명
풀이 과정
left의 처음 시작위치는 키패드 ' * '로 초기값 '10'을 주고, right의 처음 시작위치는 키패드 ' # '로 초기값 '12'를 준다.
[선택 번호가 1, 4, 7 또는 3, 6, 9 일 경우]
1. 번호가 키패드 왼쪽의 1, 4, 7과 오른쪽의 3, 6 ,9는 단순 비교문으로 "L"또는 "R"를 구하여 StringBuffer에 붙여준다.
[선택 번호가 2, 5, 8, 0 일 경우] - left번호, right번호, 선택번호 구분을 잘 해야 한다.
** 우선 그림속 키패드에서 규칙을 찾아서 해답을 찾아간다.
* 키패드의 좌표는 키패드 모양 기준으로 4x3배열이다. 1 = (0, 0) 부터 시작하여 #(12) = (3,2)가 된다.
* 해당 번호의 위치(좌표) 구하는 방식 = 현재번호-1 나누기 3을 하여 '몫'은 x좌표, '나머지'는 y좌표가 된다.
* 선택된 번호의 위치(좌표) 구하는 방식 = 현재번호 나누기 3을 하여 '몫'은 x좌표, y좌표는 가운데 고정이니 '1'이 된다
-> 좌표를 구하는 이부분은 다른 개발자분의 풀이를 보고 알게됬다. (현타 거하게 왔다ㅠ)
1. 가장 최근에 걸렸던 left번호와 right번호를 구해 해당 번호들의 위치(x, y 좌표)를 구한다.
2. 선택번호의 위치(x, y 좌표)를 구한다.
-> (left또는 right에서 선택번호까지의 거리를 구하기 위함이다.)
3. 1에서 구한 좌표 x값과 2에서 구한 좌표 x값을 마이너스 연산을 한 후 절대값으로 반환 받는다.
4. 1에서 구한 좌표 y값과 2에서 구한 좌표 y값을 마이너스 연산을 한 후 절대값으로 반환 받는다.
* 절대값 연산 시 Math.abs() 함수 사용
* 3과 4에서 반환받은 절대값들의 합이 left 또는 right 위치에서의 선택된 번호 까지의 거리가 된다.
6. left의 거리와 right의 거리 중 더 작은 숫자(거리)를 StringBuffer에 붙여준다.
7. 만약 같은 거리일 경우 현재 매개변수로 받은 String hand의 값을 기준으로 정한다.
마지막으로 완성된 StringBuffer를 answer에 넣고 반환해준다.
풀이
public class Solution {
public String solution(int[] numbers, String hand) {
String answer = "";
StringBuffer answerTemp = new StringBuffer();
int left = 10, right = 12; // 초기값 선언 후 로직에 따라 가장 최근 번호들이 들어갈 것.
int leftDis = 0, rightDis = 0; // 거리를 담을 변수
for(int num : numbers){
if(num==1||num==4||num==7){
left = num;
answerTemp.append("L");
}else if(num==3||num==6||num==9){
right = num;
answerTemp.append("R");
}else{ // 키패드 가운데 라인일 경우
leftDis = Distance(left, num, hand);
rightDis = Distance(right, num, hand);
if(leftDis>rightDis){
right = num;
answerTemp.append("R");
}else if(leftDis<rightDis){
left = num;
answerTemp.append("L");
}else{
if(hand.equals("left")){
left = num;
answerTemp.append("L");
}else{
right = num;
answerTemp.append("R");
}
}
}
}
answer = answerTemp.toString();
return answer;
}
// 거리 구하는 함수
static int Distance(int val, int num, String hand){
// 키패드의 0번은 보이는 규칙에 따라 '10'을 준다.
if(val == 0) val = 11;
if(num == 0) num = 11;
// left 또는 right의 좌표를 구한다.
int x = (val-1) / 3;
int y = (val-1) % 3;
// 선택번호의 좌표를 구한다.
int numX = num / 3;
int numY = 1; // 가운데 라인 고정 '1'
// 각각의 x, y의 절대값을 더한 후 반환해준다.
return Math.abs(x-numX)+Math.abs(y-numY);
}
// 예시 2번 테스트
public static void main(String[] args) {
int [] numbers = {7, 0, 8, 2, 8, 3, 1, 5, 7, 6, 2};
String hand = "left";
Solution s = new Solution();
s.solution(numbers, hand);
}
}
'Algorithm' 카테고리의 다른 글
[Algorithm] 프로그래머스_완주하지 못한 선수(해시) (0) | 2021.08.12 |
---|---|
[Algorithm] 특정값 소수 판별하기 (0) | 2021.08.11 |
[Algorithm] 원더랜드_프림 알고리즘(최소스패닝트리) (0) | 2021.07.30 |
[Algorithm] 원더랜드_크루스칼 알고리즘(최소스패닝트리) (0) | 2021.07.26 |
[Algorithm] 친구인가? (Disjoint-Set : Union&Find) (0) | 2021.07.24 |