Nomad Engineer

[일일코테 Day9] 3진법 뒤집기 본문

개발/코딩테스트

[일일코테 Day9] 3진법 뒤집기

universehan 2021. 3. 3. 18:42

문제

programmers.co.kr/learn/courses/30/lessons/68935?language=javascript#

 

코딩테스트 연습 - 3진법 뒤집기

자연수 n이 매개변수로 주어집니다. n을 3진법 상에서 앞뒤로 뒤집은 후, 이를 다시 10진법으로 표현한 수를 return 하도록 solution 함수를 완성해주세요. 제한사항 n은 1 이상 100,000,000 이하인 자연수

programmers.co.kr

문제는 간단했다. 

접근법

구현하는 방법은 두가지 정도 생각해 봤다.

  • 내장함수를 사용하기
  • 직접 구현해보기

아무래도 이런 문제는 직접 구현해보는걸 의도한것 같아서 직접 구현해 보았다.

문제를 새부사항으로 쪼개보면

  • 3진수 문자열 얻기
  • 뒤집기
  • 뒤집은 문자열로 다시 10진수로 만들기

3진수 문자열 얻기

10준수의 수를 3으로 계속 나누면서 나머지를 문자열로 추가해 나간다. 중학교때 배웠던것 같은데 대략 그림을 퍼오자면

2진 법으로 변환

문자열 뒤집기

기본적으로 제공하는 내장함수를 사용하면 되지만 나 같은 경우는 낮은 자리부터 하나씩 앞에다 푸시하면서 넣었다. 어차피 뒤집어야 하기 때문에, 예를들어. 9 라면. 110 => [1, 1, 0] 문자열로 표현하려면 배열의 낮은 인덱스 부터 큰 숫자가 들어가야 한다.

 

뒤집은 문자열로 다시 10진수로 만들기

어차피 큰 숫자를 1의 자리로 볼것이기 때문에 그냥 단순히 앞에서 부터 빼나가면서 더하면 된다.

result = digit[i] * pow(3, i)

실수

- 경계값을 잘못 정했다.

 

테스트 케이스

실수를 하고 나니. 다음의 경우는 꼭  테스트 케이스를 넣어야 겠다.

- 0

- 딱 나누어 떨어지는 수 - 이 경우는 3의 배수들

- 최대값 - 최대값

- 경계값을 결정하는 - 반복문의 완료 조건에 해당하는 숫자.

특별히 진수 변환하고 역으로 다시 변환하는 함수가 잘 동작하는지 검증하는 방법이 필요했는데 이 방법에는 다음의 두가지 방법을 사용했다.

  • 임의의 3진수 숫자를 정하고 그에 해당하는 10진수를 계산해서 테스트 케이스로 사용
  • 임의의 숫자를 3진수로 변환하고 다시 10진수로 변환하는 코드를 반복문으로 검증
for(let i = 0; i < 1000; ++i) {
  ternary = convert(i);
  decimal = convertToDec(tenary);
  assert(ternary == decimal);
}

구현

사용하는 내장 함수.

  • Math.pow
  • Array.prototype.reverse
  • Array.reduce
function decimalFromReversedOf(digits) {
    return digits.reduce((answer, digit, i) => answer + digit * Math.pow(3, i), 0);
}

function ternaryDigitsOf(n) {
    const digits = [];
    for(let share = n; share > 0; share = Math.floor(share/3)) {
        digits.unshift(share % 3);
    }
    return digits;
}

function solution(n) {
    const digits = ternaryDigitsOf(n);
    return decimalFromReversedOf(digits);
}

 

결론

  • 반복문의 완료 조건을 잘 생각하자. 
  • 경계값 테스트를 고민해보자.
  • 쉽게 검증하는데 로직을 재사용할 수 있도록 가능하면 기능단위로 함수를 분리해 두는게 편하다.

언제나 짧은시간에 글을 쓰는건 힘들고. 항상 내용이 부실해진다. 

References

반응형