프로그래머스 - [카카오 인턴] 키패드 누르기

문제


풀이
카카오 인턴쉽 문제답게 상당히 어려운 문제였다. 풀고자 했던 의도는 키패드를 먼저 2차원 평면 좌표로 구현하기 위해 2차원 배열로 좌표들을 지정해 주었고, 현재 왼손 시작 좌표, 오른손 시작 좌표를 지정해 준 다음 numbers 배열들을 좌표에 매칭시켰다.

먼저 1번, 4번, 7번에 해당되는 (1, 0), (2, 0), (3, 0)일 때 "L"을 추가하고
3번, 6번, 9번에 해당되는 (1, 2), (2, 2), (3, 2)일 때 "R"을 추가시킨다.
남은 0번, 2번, 5번, 8번을 처리할 때가 관건인데 이는 예시를 통해 이해해보자
왼손 위치가 키패드4번, 오른손 위치가 키패드9번에 있을 때 다음으로 5번 키를 눌러야 하는 상황

9번에서 5번을 가기위해 걸리는 거리는 (1,2)와 (2,1)사이의 거리를 구하기 위해서 유클리드 거리를 계산하기 위해
Math.sqrt(Math.pow(1-2, 2) + Math.pow(2-1, 2)) 의 연산을 했더니 계속 풀리지 않아 의문을 가졌다.
그리고 문제의 예제 설명을 자세히 보니 9번에서 5번으로 가는 거리가 루트2가 아닌 2라고 표기된 것을 발견했다

그제서야 문제 조건에서 손의 위치는 상하좌우로만 이동할 수 있다는 것을 발견했다.... (문제 조건을 확실하게 읽자ㅠ)
즉, 피타고라스 공식을 사용하는 유클리드 거리가 아닌 맨하탄 거리를 이용해서 구해야 한다는 것이었다.

따라서, x좌표간의 차이 + y좌표간의 차이를 구하면 되기에 Math.abs((1-2) + (2-1)) 로 구현해 주니 해결되었다.
그리고 왼손위치에서 계산한 맨하탄 거리와 오른손위치에서 계산한 맨하탄 거리가 같을 때 왼손잡이이면 "L", 오른손잡이이면 "R"을 추가한다.
function solution(numbers, hand) {
answer = '';
leftHandPosition = [0, 0]; // 왼손 시작 좌표
rightHandPosition = [0, 2]; // 오른손 시작 좌표
// numbers 배열을 좌표에 매칭하기 위한 인덱스화
numbers.map((num, idx) => {
if(num === 0) return numbers[idx] = 10
else return numbers[idx]--
});
// 키패드를 좌표를 그린다 생각하고 2차원 배열로 표현
let keyCoordinate = [
[3, 0], [3, 1], [3, 2], // 1 2 3
[2, 0], [2, 1], [2, 2], // 4 5 6
[1, 0], [1, 1], [1, 2], // 7 8 9
[0, 0], [0, 1], [0, 2] // * 0 #
];
numbers.map((_, idx) => numbers[idx] = keyCoordinate[numbers[idx]]);
for(let i = 0; i < numbers.length; i++) {
// numbers[i]가 1, 4, 7 일때, 왼손위치 numbers[i]로 변경, answer에 L 글자 추가
if(JSON.stringify(numbers[i]) === JSON.stringify([3, 0])
|| JSON.stringify(numbers[i]) === JSON.stringify([2, 0])
|| JSON.stringify(numbers[i]) === JSON.stringify([1, 0])
) {
leftHandPosition = numbers[i];
answer += 'L';
}
// numbers[i]가 3, 6, 9 일때, 오른손위치 numbers[i]로 변경, answer에 R 글자 추가
else if(JSON.stringify(numbers[i]) === JSON.stringify([3, 2])
|| JSON.stringify(numbers[i]) === JSON.stringify([2, 2])
|| JSON.stringify(numbers[i]) === JSON.stringify([1, 2])
) {
rightHandPosition = numbers[i];
answer += 'R';
}
// numbers[i]가 0, 2, 5, 8 일때
else {
// 왼손위치와 numbers[i]의 거리가 오른손위치와 numbers[i]의 거리보다 짧을 때
if(Math.abs(leftHandPosition[0] - numbers[i][0]) + Math.abs(leftHandPosition[1] - numbers[i][1])
< Math.abs(rightHandPosition[0] - numbers[i][0]) + Math.abs(rightHandPosition[1] - numbers[i][1])
) {
leftHandPosition = numbers[i];
answer += 'L';
}
// 오른손위치와 numbers[i]의 거리가 왼손위치와 numbers[i]의 거리보다 짧을 때
else if(Math.abs(leftHandPosition[0] - numbers[i][0]) + Math.abs(leftHandPosition[1] - numbers[i][1])
> Math.abs(rightHandPosition[0] - numbers[i][0]) + Math.abs(rightHandPosition[1] - numbers[i][1])
) {
rightHandPosition = numbers[i];
answer += 'R';
}
// 왼손위치와 numbers[i]의 거리와 오른손위치와 numbers[i]의 거리가 같을 때
else {
if(hand === 'left') {
leftHandPosition = numbers[i];
answer += 'L'
}
else {
rightHandPosition = numbers[i];
answer += 'R';
}
}
}
}
return answer;
}