이 문제는 그림이 나와서 그런지 푸는데 아기자기하고 즐거웠다
(즐거웠다는 의미가 절대 쉬웠다는 의미는 아닙니다만)
코딩테스트 연습 - 키패드 누르기
[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"
programmers.co.kr
내가 생각했을 때 이 문제를 풀면서 중요한 건 두가지였는데
1. 양 손가락의 마지막 위치가 어디인지
2. 키패드 간의 거리를 어떤 공식으로 구할 것인지
1번같은 경우는 map을 사용해서 양 손의 마지막 클릭 버튼을 업데이트 해주었다
let handsLocation = new Map([
["R","#"],
["L","*"]
]);
문제는 2번이었는데. 거리를 구한다는 말에 유클리드 거리 구하는 공식으로 계산했는데(대각선 구할 때 써야함)
문제에 손가락은 상하좌우로 이동한다고 나와있었기 때문에 유클리드가 아니라 맨해튼 거리를 사용해
거리를 구해야했던 것
const absDis = Math.floor(Math.sqrt(Math.pow(Math.abs(a1-b1),2) + Math.pow(Math.abs(a2-b2),2)))
이렇게 유클리드로 열심히 구했는데 계속 실패 떠서 다 콘솔 찍었는데 허망했다.
const absDis = Math.floor( Math.abs(a1 - b1) + Math.abs(a2 - b2))
이렇게 구하는 것이 맞았다.
이 밖에는 따로 어려움은 없었던 것같다.
우선 무조건 오른손/왼손을 사용하는 경우와 각 숫자 패드의 좌표를 선언해준다
const left = [1,4,7];
const right = [3,6,9];
const keys = {
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]
}
입력받은 numbers를 for문을 돌려 차례대로 어떤 손을 써야하는지 확인하여
마지막 손가락의 위치를 업데이트해주고 answer 배열에 추가해준다.
const setValues = (hand,num) => {
handsLocation.set(hand,num);
answer.push(hand)
}
for (let number of numbers) {
if (left.includes(number)) {
setValues("L",number);
} else if (right.includes(number)) {
setValues("R",number);
} else {
selHand(number)
}
}
왼손에도 오른손에도 속하지 않는 번호는 else 문에서 처리하는데
코드 길어지는게 싫어서 따로 selHand로 뺐다
const selHand = (num) => {
const fromL = calDistance(handsLocation.get("L"),num);
const fromR = calDistance(handsLocation.get("R"),num);
const handChar = hand === "right" ? "R" :"L"
if (fromL == fromR) {
return setValues(handChar,num);
}
return fromL < fromR ? setValues("L",num) : setValues("R",num);
}
fromL과 fromR로 직전위치 - 숫자까지의 거리를 각각 계산하여 비교한다.
const calDistance =(k1,k2) => {
const a = keys[k1];
const b = keys[k2];
const a1 = a[0];
const a2 = a[1];
const b1 = b[0];
const b2 = b[1];
const absDis = Math.floor( Math.abs(a1 - b1) + Math.abs(a2 - b2))
return absDis
}
calDistanse에서 두 숫자를 받아 각각의 좌표를 구하고 절대 거리를 리턴한다.
function solution(numbers, hand) {
const answer = [];
const left = [1,4,7];
const right = [3,6,9]
let handsLocation = new Map([
["R","#"],
["L","*"]
]);
const keys = {
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]
}
const setValues = (hand,num) => {
handsLocation.set(hand,num);
answer.push(hand)
}
const calDistance =(k1,k2) => {
const a = keys[k1];
const b = keys[k2];
const a1 = a[0];
const a2 = a[1];
const b1 = b[0];
const b2 = b[1];
const absDis = Math.floor( Math.abs(a1 - b1) + Math.abs(a2 - b2))
return absDis
}
const selHand = (num) => {
const fromL = calDistance(handsLocation.get("L"),num);
const fromR = calDistance(handsLocation.get("R"),num);
const handChar = hand === "right" ? "R" :"L"
if (fromL == fromR) {
return setValues(handChar,num);
}
return fromL < fromR ? setValues("L",num) : setValues("R",num);
}
for (let number of numbers) {
if (left.includes(number)) {
setValues("L",number);
} else if (right.includes(number)) {
setValues("R",number);
} else {
selHand(number)
}
}
return answer.join('')
}
마지막에 ['R','L','R','R'] 형태로 저장된 배열을 string으로 바꿔줘야 해서 join('')을 사용했다
'Algorithm' 카테고리의 다른 글
[HackerRank/js] Mini-Max Sum (배열의 합을 구해 비교하기) (0) | 2022.07.04 |
---|---|
[Hackerrank/js] Plus Minus (0) | 2022.07.04 |
[프로그래머스/js] 신규 아이디 추천 (0) | 2022.06.29 |
[프로그래머스/js] 신고 결과 받기 (0) | 2022.06.29 |
[ORACLE] 월/요일별 태어난 사람 통계 (DECODE, SUM, HAVING COUNT사용하기) (0) | 2022.01.18 |