ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • [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
    }
    1. ans는 반환할 정답이자, 점프한 횟수이다.
    2. while 반복문을 n이 0이 될 때까지 순회한다. 만약, 현재 n을 2로 나눈 나머지가 1인 경우, 점프에 해당하므로 ans에 1을 더한다.
    3. 그리고, n을 계속해서 Math.floor() 를 통해 2로 나눈 몫으로 최신화해준다.
    4. 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)]
      }
    }
    1. wrongIdx는 이전에 말한 글자의 맨 뒷 문자와 현재 말한 글자의 첫 문자가 불일치하는 경우의 인덱스이다. (+1)
    2. word[0] 와 words[idx-1][words[idx-1].length-1] 을 비교하되, 첫 문자는 이전 문자가 없어 오류가 생기므로 words[idx-1] 존재의 조건을 추가해준다.
    3. doubleIdx는 현재 말한 글자가 이전에 이미 말해진 중복의 경우의 인덱스이다. (+1)
    4. words를 현재 인덱스까지 slice 한 배열이, 현재 문자인 word를 포함한다면 우리가 찾는 인덱스인 것이다.
    5. findIndex는 불일치의 경우 -1을 반환한다. 우리는, JS 인덱싱이 아닌 실제 사람수와 카운트 계산을 위해 각각에 1을 더했다.
    6. 고로, wrongIdx, doubleIdx 모두 0인 경우 탈락자가 없는 케이스가 되는 것이다. 이 때는, [0,0]을 반환한다.
    7. 만약, 0보다 큰 값이 존재한다면 이것은 탈락자 발생순서이다. 먼저 탈락한 사람을 찾아야 하므로, 작은 값으로 failIdx를 설정한다.
    8. 정답의 첫 인자는 몇 번째 사람이 탈락했는지 이다. 이는, failIdx를 n으로 나눈 나머지고, 0인 경우는 마지막 사람이므로 n이 된다.
    9. 정답의 두번째 인자는 탈락발생이 몇 번째 사이클에 발생했는지다. 이는, 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])로 최신화하고 있다.

     

    * 출처 : 프로그래머스 정답자의 풀이

     

    반응형
Designed by Tistory.