키패드 각 숫자의 위치를 배열처럼 접근하는 것은 바로 떠올렸지만,
타겟 숫자가 어떤 위치에 있는지를 알아내는 방법을 어떻게 해야하는지 고민을 많이 했다.
처음엔 숫자의 몫과 나머지를 이용한 방식으로 할까 하다가 매번 계산하는 것도 좋지 않을 것 같았고
계산도 깔끔하게 떨어지지 않아 오히려 더 복잡해질 것 같아서 넘겼다.
그래서 생각한 다음 방식은 각 타겟 숫자의 위치를 저장한 배열을 만들고
타겟 숫자를 인덱스로 삼아 접근해야 겠다고 생각했다.
특수 문자인 *과 #은 각각 10번, 11번으로 삼고 구현하려고 했다.
그러다가 이 방식은 코드 파악도 쉽지 않고 (근데 코드 파악을 고려해야할 지는 잘 모르겠다)
이렇게 일일이 위치를 저장할 바에는 객체로 더 직관적으로 표현해도 되겠다 싶어서 객체를 선택했다.
처음에는 if와 else if, else로 주구장창 나열했더니 가독성이 너무 안 좋았다.
너무 잦은 if로 뎁스도 깊어지고, 내가 짠 코드임에도 복잡해서 파악이 힘들었다.
그래서 if ~ else를 각 단계별로만 묶고
3단계 이전의 경우로 해결하는 건 continue를 이용해 이후 로직을 실행하지 않도록 구현했다.
continue를 적절하게 사용하면 if ~ else를 2중, 3중으로 만들지 않아도 되기 때문에
훨씬 코드가 개선되는 것 같다고 느꼈다.
거리를 계산하는 건 타켓 숫자 위치와 현재 손의 위치의 0번 인덱스와 1번 인덱스의 차이를 더하는 방식으로 구현했다.
다만, 왼손 오른손을 둘다 구현해야 하고 계산하는 식이 너무 길어 따로 빼두는 게 더 좋을 것 같았다.
그래서 calDistance 함수를 만들었고, 함수 내부에서 키패드 숫자 위치를 알아야 하는 점 때문에 solution 내부에 함수를 위치시켰다.
function solution(numbers, hand) {
const leftLine = [1, 4, 7];
const rightLine = [3, 6, 9];
const keypad = {
1: [0, 0], 2: [0, 1], 3: [0, 2],
4: [1, 0], 5: [1, 1], 6: [1, 2],
7: [2, 0], 8: [2, 1], 9: [2, 2],
"*": [3, 0], 0: [3, 1], "#": [3, 2],
};
let left = "*";
let right = "#";
const result = [];
function calDistance(target, current) {
return (
Math.abs(keypad[target][0] - keypad[current][0]) +
Math.abs(keypad[target][1] - keypad[current][1])
);
}
for (const target of numbers) {
// 1단계
if (leftLine.includes(target)) {
result.push("L");
left = target;
continue;
} else if (rightLine.includes(target)) {
result.push("R");
right = target;
continue;
}
// 2단계
const leftDistance = calDistance(target, left);
const rightDistance = calDistance(target, right);
if (leftDistance < rightDistance) {
result.push("L");
left = target;
continue;
} else if (leftDistance > rightDistance) {
result.push("R");
right = target;
continue;
}
// 3단계
if (hand === "right") {
result.push("R");
right = target;
} else {
result.push("L");
left = target;
}
}
return result.join("");
}