본문 바로가기
문제풀이/프로그래머스

콜라츠 추측

by dev_kong 2021. 11. 21.
728x90
728x90

문제 설명

1937년 Collatz란 사람에 의해 제기된 이 추측은, 주어진 수가 1이 될때까지 다음 작업을 반복하면, 모든 수를 1로 만들 수 있다는 추측입니다. 작업은 다음과 같습니다.

1-1. 입력된 수가 짝수라면 2로 나눕니다. 
1-2. 입력된 수가 홀수라면 3을 곱하고 1을 더합니다.
2. 결과로 나온 수에 같은 작업을 1이 될 때까지 반복합니다.

예를 들어, 입력된 수가 6이라면 6→3→10→5→16→8→4→2→1 이 되어 총 8번 만에 1이 됩니다. 위 작업을 몇 번이나 반복해야하는지 반환하는 함수, solution을 완성해 주세요. 단, 작업을 500번을 반복해도 1이 되지 않는다면 –1을 반환해 주세요.

 

풀이방법

오늘 rest 파라미터 배웠다. 써보고 싶었다.

그래서 num에다가 rest 먹여서 array로 만들고

for문 돌려서 숫자 하나씩 push로 집어 넣은뒤에

num.length -1 리턴해주면 될 거 같았다.

죵나 똑똑한 방법이라고 생각했다.

 

function solution(...num) {
  let answer = 0;
  for (let i = 0; i < num.length; i++) {
    if (num[i] !== 1 && num[i] % 2 && num.length < 500) {
      num.push(num[i] * 3 + 1);
    } else if (num[i] !== 1 && !(num[i] % 2) && num.length < 500) {
      num.push(num[i] / 2);
    } else if (num.length === 500) {
      answer = -1;
    } else if (num[i] === 1) {
      answer = num.length - 1;
    }
  }
  return answer;
}

이따구로 했다. 빡대가리인 듯 하다..

그래도 풀긴 품 ㅎ

우리집 시니어 개발자가 코드리뷰 해줘땅

참신하단다. 

 

1. for문의 조건이 계속 변경 되면 추측이 힘들다.

   for문의 조건 i<num.length 가 push로 인해 계속 변경이 되기 때문에,

   코드를 딱 보면 이해하기가 힘들다. 사실 나도 설명하는데 힘들었다.

2. early_return

   횟수가 500이 넘거나, 변수가 1일 경우 먼저 return 해주면 if - else if 문이 간결해지고

   결국 가독성이 좋아진다.

3. 매개변수 자체를 변경하지 마라

   매개변수를 변경하는건 anti_pattern 중 하나다 앵간하면 하지마라.

4. rest parameter는 용도에 맞게 써라.

   rest parameter는 함수의 인자가 몇개 들어올지 모를 때 쓰는거지,

   매개변수를 배열로 변경하려고 쓰는게 아니다.

   만들어진 목적대로 써라

5. 코드 짤때는 시간복잡도도 중요하지만 공간 복잡도도 신경써라.

   설명은 못하겠지만 머리로는 이해함...ㅇㅇ

 

 

function solution(...num) {
  let answer = 0;
  for (let i = 0; i < num.length; i++) {
    if (num.length === 500) {
      return -1;
    }
    if (num[i] === 1) {
      return num.length - 1;
    }
    num.push(num[i] % 2 ? num[i] * 3 + 1 : num[i] / 2);
  }
  return answer;
}

 

 

 

그렇게 해서 수정한 코드.

훨씬 보기 좋아졌다. 

그런데 이런 조건(반복문이 몇번 돌아야 하는지 명확하지 않은경우)에는

for 반복문 보다 while 반복문을 쓰는게 좋단다.

이제껏 들었던 강의들에선 for 반복문은 열심히 설명해주던데

while 반복문은 스을-쩍 넘어가서

나도 까먹고 있었다.

코테할때 가끔 쓰인다니 잘 기억하도록 하자

 

 

function solution_while(num) {
  let temp = num;
  let count = 0;

  while (temp !== 1) {
    if (count > 500) return -1;

    temp = temp % 2 ? temp * 3 + 1 : temp / 2;
    count += 1;
  }

  return count;
}

 

 

최종수정

매개변수 변경안함

for 대신에 while 로 변경

카운트가 500이 넘어가거나 매개변수가 1인경우 early-return

ternary operator로 가독성 좋은 깔끔한 코드

count에다가 1씩 올려주고 최종리턴 한다

 

후기

풀었다고 좋아했는데,

푼게 푼게 아니다.

그래도 한문제로 많은걸 배울 수 있었다.

그리고 사실 어떻게든 풀었다는 사실에 기분이 좋긴했음... ㅎ

 

 

https://programmers.co.kr/learn/courses/30/lessons/12943

728x90
728x90

댓글