-
[CodeKata] 프로그래머스 : 3.20(토), 점프와 순간이동 & 영어 끝말잇기Algorithm 2021. 3. 20. 15:15반응형
🥋 Ooooth!! (Level 2) : 점프와 순간이동
이동할 거리 N까지 최대한 순간이동으로 가는 것이 이득이다.
역발상으로, N을 0이 될 때까지 2로 나누고 (이는 모두 순간이동에 해당), 나머지가 1인 경우에만 점프로 이동한다는 개념으로 접근했다.
🧮 풀이
function solution(n) { let ans = 0; while (n > 0) { if (n%2 === 1) ans++; n = Math.floor(n/2) } return ans }
- ans는 반환할 정답이자, 점프한 횟수이다.
- while 반복문을 n이 0이 될 때까지 순회한다. 만약, 현재 n을 2로 나눈 나머지가 1인 경우, 점프에 해당하므로 ans에 1을 더한다.
- 그리고, n을 계속해서 Math.floor() 를 통해 2로 나눈 몫으로 최신화해준다.
- n이 1인 경우, ans에 1이 더해지고 n은 0이 될 것이다. 이 시점이, 처음 0에서 점프를 통해 1까지 이동하는 첫 스타트인 것이다.
🥋 Ooooth!! (Level 2) : 영어 끝말잇기
🧮 풀이
function solution(n, words) { const wrongIdx = words.findIndex((word, idx) => words[idx-1] && word[0] !== words[idx-1][words[idx-1].length-1])+1 const doubleIdx = words.findIndex((word, idx) => words.slice(0, idx).includes(word))+1 if (wrongIdx === 0 && doubleIdx === 0) { return [0,0]; } else { const failIdx = [wrongIdx, doubleIdx].filter(e => e > 0).reduce((a,b) => a < b ? a : b); return [failIdx % n === 0 ? n : failIdx % n, Math.ceil(failIdx/n)] } }
- wrongIdx는 이전에 말한 글자의 맨 뒷 문자와 현재 말한 글자의 첫 문자가 불일치하는 경우의 인덱스이다. (+1)
- word[0] 와 words[idx-1][words[idx-1].length-1] 을 비교하되, 첫 문자는 이전 문자가 없어 오류가 생기므로 words[idx-1] 존재의 조건을 추가해준다.
- doubleIdx는 현재 말한 글자가 이전에 이미 말해진 중복의 경우의 인덱스이다. (+1)
- words를 현재 인덱스까지 slice 한 배열이, 현재 문자인 word를 포함한다면 우리가 찾는 인덱스인 것이다.
- findIndex는 불일치의 경우 -1을 반환한다. 우리는, JS 인덱싱이 아닌 실제 사람수와 카운트 계산을 위해 각각에 1을 더했다.
- 고로, wrongIdx, doubleIdx 모두 0인 경우 탈락자가 없는 케이스가 되는 것이다. 이 때는, [0,0]을 반환한다.
- 만약, 0보다 큰 값이 존재한다면 이것은 탈락자 발생순서이다. 먼저 탈락한 사람을 찾아야 하므로, 작은 값으로 failIdx를 설정한다.
- 정답의 첫 인자는 몇 번째 사람이 탈락했는지 이다. 이는, failIdx를 n으로 나눈 나머지고, 0인 경우는 마지막 사람이므로 n이 된다.
- 정답의 두번째 인자는 탈락발생이 몇 번째 사이클에 발생했는지다. 이는, failIdx를 n으로 나눈 값을 올림하면 된다. (Math.ceil())
🖇 리뷰
사실 위 풀이보다는, words 순회 과정에서 2가지 탈락조건을 동시에 체크하는 것이 효율적이다.
나는 reduce() 를 단순히 배열을 하나의 값으로 축약한다고만 생각했는데, 아래는 콜백함수를 통해 1) reduce 축약값을 현재의 끝글자로 관리하면서, 2) 동시에 answer 탈락자 인덱스를 탐색하는 로직을 동시에 실행하고 있다.
function solution(n, words) { let answer = 0; words.reduce((prev, now, idx) => { answer = answer || ((words.slice(0, idx).indexOf(now) !== -1 || prev !== now[0]) ? idx : answer); return now[now.length-1]; }, "") return answer ? [answer%n+1, Math.floor(answer/n)+1] : [0,0]; }
정말 좋은 풀이이다. prev(흔히 acc) 값을 누적이 아닌, 이전 글자의 마지막 글자(now[now.length-1])로 최신화하고 있다.
* 출처 : 프로그래머스 정답자의 풀이
반응형'Algorithm' 카테고리의 다른 글
[CodeKata] 프로그래머스 : 3.24(수), 뉴스 클러스터링 (0) 2021.03.25 [CodeKata] 프로그래머스 : 3.22(월), 예상 대진표 (0) 2021.03.23 [CodeKata] 프로그래머스 : 3.18(목), 배달 / [이론] Dijkstra Algorithm (0) 2021.03.18 [CodeKata] 프로그래머스 : 3.17(수), 짝지어 제거하기 (0) 2021.03.17 [CodeKata] 프로그래머스 : 3.13(토), 피보나치 수 & 행렬의 곱셈 (0) 2021.03.13