1. 문제
스마트폰 전화 키패드의 각 칸에 다음과 같이 숫자들이 적혀 있습니다.
이 전화 키패드에서 왼손과 오른손의 엄지손가락만을 이용해서 숫자만을 입력하려고 합니다.
맨 처음 왼손 엄지손가락은 * 키패드에 오른손 엄지손가락은 # 키패드 위치에서 시작하며, 엄지손가락을 사용하는 규칙은 다음과 같습니다.
- 엄지손가락은 상하좌우 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 해주세요.
입출력 예
numbers | hand | result |
[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" |
2. 나의 풀이
function solution(numbers, hand) {
// 핸드폰 좌표
const coordinate = {
1: [0, 3], 2: [1, 3], 3: [2, 3],
4: [0, 2], 5: [1, 2], 6: [2, 2],
7: [0, 1], 8: [1, 1], 9: [2, 1],
"*": [0,0], 0: [1, 0], "#": [2, 0],
};
let answer = "";
// 왼쪽 엄지 위치
let left_thumb = "*";
// 오른쪽 엄지 위치
let right_thumb = "#";
for (let i = 0; i < numbers.length; i ++) {
// 1, 4, 7은 나머지가 1
if (numbers[i] % 3 === 1) {
answer += "L";
left_thumb = numbers[i];
// 0을 제외한, 3, 6, 9는 나머지가 0
} else if (numbers[i] !== 0 && numbers[i] % 3 === 0) {
answer += "R";
right_thumb = numbers[i];
} else {
// 거리 비교
// 왼쪽 엄지의 좌표
const left_coordinate = coordinate[left_thumb];
// 오른쪽 엄지의 좌표
const right_coordinate = coordinate[right_thumb];
// 현재 눌러야 하는 숫자의 좌표
const target_coordinate = coordinate[numbers[i]]
// 왼쪽 엄지와 타겟 좌표의 거리
const left_target_distance = Math.abs(left_coordinate[0] - target_coordinate[0])
+ Math.abs(left_coordinate[1] - target_coordinate[1])
// 오른쪽 엄지와 타겟 좌표의 거리
const right_target_distance = Math.abs(right_coordinate[0] - target_coordinate[0])
+ Math.abs(right_coordinate[1] - target_coordinate[1])
// 오른쪽 엄지가 긴 경우(왼쪽 엄지가 타겟번호와 가까움)에 왼쪽 엄지가 타겟 번호를 눌러야 한다.
if(left_target_distance < right_target_distance) {
answer += "L";
left_thumb = numbers[i];
// 반대로 왼쪽 엄지가 긴 경우(오른쪽 엄지가 타겟번호와 가까움)에 오른쪽 엄지가 타겟 번호를 눌러야 한다.
} else if (left_target_distance > right_target_distance) {
answer += "R";
right_thumb = numbers[i];
} else {
// 왼쪽, 오른쪽 엄지가 타겟과의 거리가 같은 경우
// 왼손잡이면 왼쪽 엄지로 누른다.
if (hand === "left") {
answer += "L";
left_thumb = numbers[i];
// 오른손 잡이면 오른쪽 엄지로 누른다.
} else {
answer += "R";
right_thumb = numbers[i];
}
}
}
}
return answer;
}
- 핸드폰 숫자를 x축과 y축이 있는 좌표로 만들어야 겠다는 생각이 들었다. (coordinate 객체)
- *이 (0,0)을 기준으로 좌표 값을 채워 넣었다.
- 문제의 조건중에서 왼쪽, 오른쪽 엄지 중에서 가까운 쪽 손가락이 번호를 누르기 때문에, 각 엄지의 위치를 저장해야 했다. (left_thumb, right_thumb)
- 숫자 배열을 순회하면서 숫자가 1, 4, 7인 경우에는 왼쪽 엄지로 누른다. (answer += "L")
- 반대로 0을 제외한 3, 6, 9인 경우에는 오른쪽 엄지로 누른다. (answer += "R")
- 나머지 숫자의 경우에는 현재 왼쪽 엄지의 위치와 오른쪽 엄지 위치중에 가까운 손가락이 누른다.
- 거리를 계산하기 위해서, 각각의 좌표를 가져온다.
- 좌표를 가지고와서 현재 눌러야 하는 번호의 좌표와 거리를 계산한다. 이 때 거리를 계산하기 위해 음수가 나오지 않도록 Math.abs를 사용해서 절대값으로 구한다.
- 거리계산 예시
- 왼쪽 엄지가 7([0, 1])에 있고, 오른쪽 엄지가 3([2, 3])에 있다고 가정하고, 현재 눌러야 하는 번호가 2([1, 3])라면
const left_target_distance = Math.abs(left_coordinate[0] - target_coordinate[0])
+ Math.abs(left_coordinate[1] - target_coordinate[1])
const right_target_distance = Math.abs(right_coordinate[0] - target_coordinate[0])
+ Math.abs(right_coordinate[1] - target_coordinate[1])
// left_target_distance = Math.abs(0 - 1) + Math.abs(1 - 3) ===> 3
// right_target_distance = Math.abs(2 - 1) + Math.abs(3 - 3) ===> 1
- 오른쪽 엄지가 2에 더 가깝기 때문에 오른손 엄지로 누른다.
- 거리를 비교했을 때, 왼쪽이 가까우면 왼쪽 엄지로 누르고 반대라면 오른쪽 엄지가 누른다.
- 거리가 같은 경우 왼손잡이는 왼쪽 엄지로, 오른손 잡이는 오른쪽 엄지로 누른다.
처음에 좌표까지는 좋았지만, 이 좌표를 어떻게 활용해야 할지 막막했다. 그리고 거리를 구할 때도, 처음에는 자꾸 음수값들이 나와서 꼬이고 했을 때, 많이 해맸지만 필요한 메서드를 찾아보니 잘 풀렸던것 같다. 마지막으로 상세하게 알고리즘을 나열하다 보니 힘들었지만... 그래도.. 했으니....
공부 공부..
'리코딩 : 알고리즘' 카테고리의 다른 글
프로그래머스 - 해시 - 위장 (0) | 2021.10.08 |
---|---|
프로그래머스 - 직업군 추천하기 (0) | 2021.10.07 |
14. 프로그래머스 - 다트게임 (0) | 2021.10.05 |
13. 프로그래머스 - 2019 KAKAO BLIND RECRUITMENT 오픈채팅방 (0) | 2021.10.04 |
12. 프로그래머스 - 숫자 문자열과 영단어 (0) | 2021.10.02 |