ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • Section4 Daily Coding 10_primePassword (optional)
    공부/데일리코딩 2022. 8. 3. 09:04
    반응형

    문제

    다음의 조건을 만족하면서 현재의 비밀번호('curPwd')를 새 비밀번호(newPwd)로 변경하는 데 필요한 최소 동작의 수를 리턴해야 합니다.

    • 한 번에 한 개의 숫자만 변경가능하다.
    • 4자리의 소수(prime)인 비밀번호로만 변경가능하다.

    정리하면, 비밀번호가 계속 소수를 유지하도록 숫자 한 개씩을 바꿔갈 때 현재 비밀번호에서 새 비밀번호로 바꾸는 데 최소 몇 개의 숫자를 변경해야 하는지를 리턴해야 합니다.

    입력

    인자 1 : curPwd

    • number 타입의 1,000 이상 9,999 이하의 자연수

    인자 2 : newPwd

    • number 타입의 1,000 이상 9,999 이하의 자연수

    출력

    • number 타입을 리턴해야 합니다.

    주의사항

    • 4자리인 소수는 1,000 이상의 소수를 말합니다.(0011, 0997 등은 제외)

    입출력 예시

    let output = primePassword(1033, 1033);
    console.log(output); // --> 0
    
    output = primePassword(3733, 8779);
    console.log(output); // --> 3 (3733 -> 3739 -> 3779 -> 8779)

    Reference Code

    const isPrime = (num) => {
      if (num % 2 === 0) return false;
      let sqrt = parseInt(Math.sqrt(num));
      for (let divider = 3; divider <= sqrt; divider += 2) {
        if (num % divider === 0) {
          return false;
        }
      }
      return true;
    };
    
    // 4자리 수를 받아서 각 자리수의 수들의 배열로 변환하는 함수
    //  let output = splitNum(3359);
    //  console.log(output); // --> [3, 3, 5, 9]
    const splitNum = (num) => {
      const digits = num.toString().split('');
      return digits.map((d) => Number(d));
    };
    
    // 길이의 4의 수 배열을 받아서, 4자리의 수로 변환하는 함수
    //  let output = splitNum([3, 3, 5, 9]);
    //  console.log(output); // --> 3359
    const joinDigits = (digits) => Number(digits.join(''));
    
    const primePassword = (curPwd, newPwd) => {
      if (curPwd === newPwd) return 0;
      // bfs를 위해 queue를 선언
      let front = 0;
      let rear = 0;
      const queue = [];
      const isEmpty = (queue) => front === rear;
      const enQueue = (queue, item) => {
        queue.push(item);
        rear++;
      };
      const deQueue = (queue) => {
        return queue[front++];
        // const item = queue[front];
        // front++;
        // return item;
      };
    
      // 각 4자리의 방문 여부를 저장하는 배열
      // 한 번 방문한 수(가장 최소의 동작으로 만든 수)는 다시 방문할 필요가 없다.
      const isVisited = Array(10000).fill(false);
      isVisited[curPwd] = true;
      // bfs를 위한 시작점
      // 큐에는 [필요한 동작 수, 비밀번호]가 저장된다.
      enQueue(queue, [0, curPwd]);
      // bfs는 큐가 빌(empty) 때까지 탐색한다.
      while (isEmpty(queue) === false) {
        const [step, num] = deQueue(queue);
        // 각 자리수 마다 변경이 가능하므로 4번의 반복이 필요하다.
        for (let i = 0; i < 4; i++) {
          const digits = splitNum(num);
          // 0부터 9까지 시도한다.
          for (let d = 0; d < 10; d++) {
            // 각 자리수마다 원래 있던 수(digits[i])는 피해야 한다.
            if (d !== digits[i]) {
              // 현재 자리수의 수를 변경하고,
              digits[i] = d;
              // 변경한 후 4자리 수를 구한다.
              const next = joinDigits(digits);
              // 만약 이 수가 새 비밀번호와 같다면 리턴한다.
              // next는 deQueue된 num으로부터 1단계 다음에 도달한 수이다.
              if (next === newPwd) return step + 1;
              // 1,000보다 큰 소수여야 하고, 방문된 적이 없어야 한다.
              if (next > 1000 && isPrime(next) && isVisited[next] === false) {
                // 방문 여부를 표시하고,
                isVisited[next] = true;
                // 큐에 넣는다.
                enQueue(queue, [step + 1, next]);
              }
            }
          }
        }
      }
    
      // 큐가 빌 때까지, 즉 모든 경우의 수를 탐색할 때까지 리턴되지 않은 경우
      // 현재 비밀번호에서 새 비밀번호를 만들 수 없다.
      return -1;
    };
    반응형

    '공부 > 데일리코딩' 카테고리의 다른 글

    Section4 Daily Coding 12_inequalityNumber  (0) 2022.08.05
    Section4 Daily Coding 11_LPS  (0) 2022.08.04
    Section4 Daily Coding 09_LCS  (0) 2022.08.02
    Section4 Daily Coding 08_LIS  (0) 2022.08.01
    Section4 Daily Coding 07_rangeMinimum  (0) 2022.07.29
Designed by Tistory.