본문 바로가기
코테연습

47-2. 3진법 뒤집기(2)

by hxunz 2022. 5. 18.

3진법 뒤집기 코테를 진짜 진수로 바꾸는 방법으로도 풀어봤다.

 

⛑ 계획

1. 10진법 숫자를 2진법으로 바꾼다. (간단한 구현부터 해보려고 2진법으로 해봤다.)

2. 2진법을 뒤집는다.

3. 10진법으로 만든다.

4. 이를 3진법에 적용시킨다.

 


⛑ 실행

1. 10진법 숫자를 2진법으로 바꾼다.

const solution = (number, result = '') => {
  if (number < 2) {
    return number.toString() + result;
  }

  return solution(
    Math.floor(number / 2),
    (number % 2) + result
  )
}

 

예를 들어서 설명을 적어봐야겠다.

number가 5인 경우

첫번재 리턴 말고 그 다음 두번째 리턴으로 넘어간다 (number < 2 이 예외처리에 걸리니까)

5 / 2 -> 2.xx인데 Math.floor()를 해줬으니까 -> 2

5 % 2 -> 1 -> result 처음 값이 '' 이니까 1 + '' -> '1'

=> return solution(2, 1)이 되었다.

 

number가 2가 되었다. 

그럼 다시 두번째 리턴으로 넘어가서 

2 / 2 -> 1

2%2 -> '0' + '1'(위에서 result값에 '1'이 들어갔음) -> '01'

=> return solution(1,   '01')이 되었다.

 

number가 1이 되었다.

이때 if문에 걸리기때문에 첫번째 리턴을 실행해준다.

number.toString() + result;

=> '1' + '01'

=> '101'

 

 


2. 2진법을 뒤집는다.

const solution = (number, result = '') => {
  if (number < 2) {
    return result.split('').reverse().concat(number.toString()).join('');
  }

  return solution(
    Math.floor(number / 2),
    (number % 2) + result
  )
}

문자열을 뒤집고 싶어서 reverse()함수를 사용하고싶었다. 

그런데 reverse()는 배열에 적용되는 함수이기 때문에 result 값을 배열로 만들어야했다.

그래서 result.split('')을 한 다음에 reverse()를 해줬다. 

그리고 concat()을 사용해서 number.toString()과 합쳐줬다. 

그리고 join('')을 사용해서 문자열로 나타내줬다.

 

 


3. 10 진법으로 만든다

 

function binaryToDecimal(binary) {
  let result = 0;
  const reverseNum = [...binary].reverse();
  
  for (i = 0; i < reverseNum.length; i++) {
  	if (reverseNum[i] === '1') {
    	result += Math.pow(2, i);
     }
   }
   
   return result;
}

const solution = (number, result = '') => {
  if (number < 2) {
    const binary = result.split('').reverse().concat(number.toString()).join('');
    return binaryToDecimal(binary);
  }

  return solution(
    Math.floor(number / 2),
    (number % 2) + result
  )
}

2진수 숫자를 10진수로 변환하기 위해서 따로 함수를 만들어줬다. 

문자열 binary를 배열로 만든다음에 reverse()를 사용해서 뒤집어줬다.

const reverseNum = [...binary].reverse();

2진수라서 0,1로만 이루어져있기 때문에 배열 reverseNum에서 1인 숫자만 제곱을 해줬고

이를 result에 더해줬다. 

for (i = 0; i < reverseNum.length; i++) {
if (reverseNum[i] === '1') {
result += Math.pow(2, i);
}
}
 
 
 
위의 코드를 리팩토링 해서 for 반복문을 사용하는 대신 reduce를 사용해줬다.
function binaryToDecimal(binary) {
  const reverseNum = [...binary].reverse();
  
  return reverseNum.reduce((acc, curr, i) => (curr === '1') ? acc + Math.pow(2, i) : acc, 0);
}

 

 


4. 이를 3진법에 적용시킨다.

function ternaryToDecimal(ternary) {
  let result = 0;
  const reverseNum = [...ternary].reverse();
  
  for (i = 0; i < reverseNum.length; i++) {
  	if (reverseNum[i] === '2') {
    	result += Math.pow(3, i) * 2;
    } else if (reverseNum[i] === '1') {
      result += Math.pow(3, i);
     }
   }
   
   return result;
}

const solution = (number, result = '') => {
  if (number < 3) {
    const ternary = result.split('').reverse().concat(number.toString()).join('');
    return ternaryToDecimal(binary);
  }

  return solution(
    Math.floor(number / 3),
    (number % 3) + result
  )
}

간단하게 solution 함수에 숫자 2는 3으로 바꿔주고

ternaryToDecimal 함수는 reverseNum[i]가 2일때랑 1일때 예외처리를 해주었다. 

 

 

 

for 안쓰고 reduce 쓴거

function binaryToDecimal(binary) {
  const reverseNum = [...binary].reverse();
  
  return reverseNum.reduce((acc, curr, i) =>
    (curr === '2') ? acc + Math.pow(3, i) * 2
      : (curr === '1') ? acc + Math.pow(3, i)
        : acc,0);
}

const solution = (number, result = '') => {
  if (number < 3) {
    const binary = result.split('').reverse().concat(number.toString()).join('');
    return binaryToDecimal(binary);
  }

  return solution(
    Math.floor(number / 3),
    (number % 3) + result
  )
}

 

 


+ N진법 뒤집기

function toDecimal(notation, newNumber) {
  const reverseNum = [...newNumber].reverse();
  
  return reverseNum.reduce((acc, curr, i) => acc + Math.pow(notation, i) * curr, 0);
}

const solution = (notation, number, result = '') => {
  if (number < notation) {
    const newNumber = result.split('').reverse().concat(number.toString()).join('');
    return toDecimal(notation, newNumber);
  }

  return solution(
    notation,
    Math.floor(number / notation),
    (number % notation) + result
  )
}

의미가 불분명했던 숫자인 매직넘버를 상수로 선언을 해줬다. 

그래서 기존에 3진법 뒤집기만 가능했던 부분을

이제는 N진법 뒤집기가 가능하도록 해주었다. 

 

3진법 뒤집기를 할 때에 3이라고 적었던 부분을 바꿨다.

notation을 파라미터로 넣어주고 넘겨주면서 사용할 수 있도록 해주었다. 

 

'코테연습' 카테고리의 다른 글

49. 완주하지 못한 선수  (0) 2022.05.24
48. 내적  (0) 2022.05.19
47-1. 3진법 뒤집기  (0) 2022.05.17
46. 음양더하기  (0) 2022.05.17
45. 키패드 누르기  (0) 2022.05.17

댓글