Problem
스마트폰 전화 키패드의 각 칸에 다음과 같이 숫자들이 적혀 있습니다.
이 전화 키패드에서 왼손과 오른손의 엄지손가락만을 이용해서 숫자만을 입력하려고 합니다.
맨 처음 왼손 엄지손가락은 * 키패드에 오른손 엄지손가락은 # 키패드 위치에서 시작하며, 엄지손가락을 사용하는 규칙은 다음과 같습니다.
1. 엄지손가락은 상하좌우 4가지 방향으로만 이동할 수 있으며 키패드 이동 한 칸은 거리로 1에 해당합니다.
2. 왼쪽 열의 3개의 숫자 1, 4, 7을 입력할 때는 왼손 엄지손가락을 사용합니다.
3. 오른쪽 열의 3개의 숫자 3, 6, 9를 입력할 때는 오른손 엄지손가락을 사용합니다.
4. 가운데 열의 4개의 숫자 2, 5, 8, 0을 입력할 때는 두 엄지손가락의 현재 키패드의 위치에서 더 가까운 엄지손가락을 사용합니다.
4-1. 만약 두 엄지손가락의 거리가 같다면, 오른손잡이는 오른손 엄지손가락, 왼손잡이는 왼손 엄지손가락을 사용합니다.
순서대로 누를 번호가 담긴 배열 numbers, 왼손잡이인지 오른손잡이인 지를 나타내는 문자열 hand가 매개변수로 주어질 때, 각 번호를 누른 엄지손가락이 왼손인 지 오른손인 지를 나타내는 연속된 문자열 형태로 return 하도록 solution 함수를 완성해주세요.
Solution
문제분석
L = 왼쪽 엄지, R = 오른쪽 엄지
처음에는 L은 * 자리에, R은 #자리에 있음
손가락은 상하좌우로만 움직임
1, 4, 7 = L만 누를 수 있음
3, 6, 9 = R만 누를 수 있음
2, 5, 8, 0 = L, R 중 더 가까운 손이 누름. L R의 거리가 같다면 hand로 판단함(오른손잡이라면 R로 누름)
numbers = 누를 번호 순서
hand = 왼손잡이인지 오른손잡이인지 구별
return 각 번호 누른 엄지 LorR 나타내는 문자열
문제풀이
1. 2차원 배열로 풀어야겠다고 생각이 들었다.
2. L, R 각각의 위치 저장 ([X좌표, Y좌표])
3. L, R의 거리가 같다면 hand로 판단하기 때문에 numbers까지의 각 L R의 거리를 구해줘야한다.
구하는 방법은 Math.abs(L, R 각각의 [X] - numbers[X] ) + Math.abs(L R 각각의 [Y] - numvers[Y]) 로 numbers까지 거리가 얼마나 걸리는지 구해주고 더 작은 값을 지닌 손으로 클릭한다. 거리의 차를 구하는데 음수가 나올 수 있으므로 절대값으로 계산해준다
function solution(numbers, hand) {
let phone = [[1,2,3], [4,5,6], [7,8,9], ['*', 0, '#']];
let left = [3, 0];
let right = [3, 2];
let result = "";
for (let i of numbers){
let num = [];
if (i === 0 ) num.push(3, phone[3].indexOf(i));
else if(1 <= i && i < 4) num.push(0, phone[0].indexOf(i));
else if(i < 7) num.push(1, phone[1].indexOf(i));
else num.push(2, phone[2].indexOf(i));
if([1, 4, 7].includes(i)){
result += 'L';
left = num;
}
else if([3, 6, 9].includes(i)){
result += 'R';
right = num;
}
else {
let ln = Math.abs(left[0] - num[0]) + Math.abs(left[1] - num[1]);
let rn = Math.abs(right[0] - num[0]) + Math.abs(right[1] - num[1]);
if(ln === rn){
if(hand === 'right') {
result += 'R';
right = num;
}
else {
result += 'L';
left = num;
}
} else if(ln > rn) {
result += 'R';
right = num;
} else {
result += 'L';
left = num;
}
}
}
return result;
}
비록 시간은 걸렸지만 한번에 통과했다!
코드가 길고 if-else문이 난잡하게 있어서 가독성이 떨어지고 비효율적일까봐 리팩토링이 필요할 거 같았는데 다른 풀이 코드들과 비교해봤는데 아직 내 수준에서는 내 코드의 어느 부분을 리팩토링해야할지 안 보인다ㅜ
코드 분석
let phone = [[1,2,3], [4,5,6], [7,8,9], ['*', 0, '#']];
let left = [3, 0];
let right = [3, 2];
let result = "";
2차원 배열로 풀기 위해 phone변수에 4 * 3의 2차원 배열로 만들어놨다.
left와 rigth 손가락의 위치는 각각 *, #에 있으므로 각 x, y좌표를 배열로 넣어준다
result는 각 번호 누른 엄지가 L 인지 R인지 넣어줄 문자열이다.
for (let i of numbers){
let num = [];
if (i === 0 ) num.push(3, phone[3].indexOf(i));
else if(1 <= i && i < 4) num.push(0, phone[0].indexOf(i));
else if(i < 7) num.push(1, phone[1].indexOf(i));
else num.push(2, phone[2].indexOf(i));
누르는 번호 배열이 끝날 때까지 for문이 돌아가도록 만들어줬고
phone[0] = [1,2,3]
phone[1] = [4,5,6]
phone[2] = [7,8,9]
phone[3] = ['*',0.'#']
으로 이루어져있기 때문에 if문으로 i 숫자 범위를 따지면서 num에 현재 누르는 번호의 위치(x, y)를 넣어준다
if([1, 4, 7].includes(i)){
result += 'L';
left = num;
}
else if([3, 6, 9].includes(i)){
result += 'R';
right = num;
}
문제에서 조건 중 하나가
1, 4, 7이면 L로 눌러야하고
3, 6, 9이면 R로 눌러야한다
이 조건을 코드로 나타낸 것이 위의 코드이다.
예를 들어 1,4,7에 i가 속한다면 result에 L을 넣어주고 L의 좌표값을 나타내는 left에는 현재 num의 위치를 넣어준다
else {
let ln = Math.abs(left[0] - num[0]) + Math.abs(left[1] - num[1]);
let rn = Math.abs(right[0] - num[0]) + Math.abs(right[1] - num[1]);
i가 2, 5, 8, 0에 해당한다면 numbers에 더 가까운 손가락으로 터치해야하므로 각각의 numbers까지의 거리를 구해준다
x 좌표는 x 좌표끼리 빼주고 y좌표는 y좌표끼리 빼준다음 더해준다.
여기서 뺄 때 음수가 나올 수 있으므로 Math.abs메서드를 이용하여 절대값으로 만들어준다.
ln은 left -> numbers 거리
rn은 right -> numbers 거리를 의미한다
if(ln === rn){
if(hand === 'right') {
result += 'R';
right = num;
}
else {
result += 'L';
left = num;
}
}
ln과 rn이 같다면 오른손잡이, 왼손잡이 여부에 따라 달라진다는 조건이 있었다. 만약 왼손잡이라면 왼손이 움직여야한다.
그러므로 hand가 right라면 오른손잡이이므로 result에 R을 추가하고 right의 위치를 num으로 바꿔준다.
else if(ln > rn) {
result += 'R';
right = num;
} else {
result += 'L';
left = num;
}
}
}
return result;
}
ln이 rn보다 크다면 left가 rigth보다 numbers의 위치에서 멀리 있다는 의미이므로 오른손으로 해당 mumbers를 터치해준다.
'프로그래머스 (JS) > Lv. 1' 카테고리의 다른 글
[Programmers / JS] 160586번 - 대충 만든 자판 (0) | 2023.04.03 |
---|---|
[Programmers / JS] 72410번 - 신규 아이디 추천 (0) | 2023.03.31 |
[Programmers / JS] 92334번 - 신고 결과 받기 (0) | 2023.03.29 |
[Programmers / JS] 133502번 - 햄버거 만들기 (0) | 2023.03.29 |
[Programmers / JS] 42576번 - 완주하지 못한 선수 (0) | 2023.03.29 |