[프로그래머스] 3진법 뒤집기
2021.11.05에 푼 문제입니다.
이 문제는 어려운 건 아닌데 검색하면 금방 풀 수 있어서 쉽게 풀 수 있었던 것 같아요.
해결방안
function solution(n) {
return parseInt(n.toString(3).split('').reverse().join(''), 3);
}
이렇게 보면 간단해 보이지만 이해가 안 될 수 있으니 풀어쓴다면
// 정답 코드 풀어쓴 코드
function solution(n) {
// 10진법을 3진법으로
let ternary = n.toString(3).split('');
// 3진법을 역순으로
let reverse = ternary.reverse().join('');
// 역순 3진법을 10진법으로
return parseInt(reverse, 3);
}
이렇게 됩니다.
먼저 밑에 정답 코드 풀어쓴 코드의 해결방안 순서로 설명하고 마지막에 합쳐서 정답 코드에 대해 설명하겠습니다.
해결방안 순서
- 10진법을 3진법으로
- 3진법을 역순으로
- 역순 3진법을 10진법으로
1단계. 10진법을 3진법으로
// 1단계. 10진법을 3진법으로
let ternary = n.toString(3).split('');
- n.toString(3) : 10진수를 3진수로 바꿈
- split('') : 3진수를 쪼개어 배열로 만듬
?진법 -> ?진법으로 바꾸려면 다양한 방법이 있는데
- toString() : 10진법을 2~36사이의 진법으로 바꿀 때 사용
- parseInt() : 2~36사이의 진법을 10진법으로 바꿀 때 사용
이번에는 10진법 -> ?진법으로 바꾸는 방법 중에서 가장 쉬운 toString을 사용해보겠습니다.
기본적인 toString()
MDN Web Docs
toString()은 문자열을 반환하는 object의 대표적인 방법입니다.
구문 : obj.toString()
여기서 쓰는 toString()
MDN Web Docs
toString() 메서드는 특정한 Number 객체를 나타내는 문자열을 반환합니다.
구문 : numObj.toString([radix])
- radix Optional : 수의 값을 나타내기 위해 사용되기 위한 기준을 정하는 2와 36사이의 정수. (진수를 나타내는 기수의 값.)
- 만약 toString()에 2와 36의 사이 값이 아닌 radix가 주어지면, RangeError 에러가 발생합니다.
//10진수 -> 2진수
let baseTenInt = 10;
console.log(baseTenInt.toString(2));
// "1010"이 출력됩니다
10진수를 3진수를 만든 뒤 .split()를 넣는 것이 중요한데요.
split()를 쓰는 이유는 "2단계에서 3진법으로 바꾼 값을 역순으로" 바꾸는데
마음 같아서는 1200을 바로 0021로 바꾸고 싶지만 아쉽게도 안되더라고요.😅
(이게 숫자로 인식돼서 그른가 00이 계속 사라지더라고요.)
그래서 reverse()를 사용해서 역순으로 바꾸어 주어야 되는데 reverse()은 배열에서만 쓸 수 있어
split()을 사용해서 3진법을 하나하나 쪼개어 배열로 만든 후 reverse()를 써서 역순으로 바꾸는 겁니다.
MDN Web Docs
split() 메서드는 String 객체를 지정한 구분자를 이용하여 여러 개의 문자열로 나눕니다.
구문 : str.split([separator[, limit]])
- separator Optional
원본 문자열을 끊어야 할 부분을 나타내는 문자열을 나타냅니다. 실제 문자열이나 정규표현식을 받을 수 있습니다. 문자열 유형의 separator가 두 글자 이상일 경우 그 부분 문자열 전체가 일치해야 끊어집니다. separator가 생략되거나 str에 등장하지 않을 경우, 반환되는 배열은 원본 문자열을 유일한 원소로 가집니다. separator가 빈 문자열일 경우 str의 각각의 문자가 배열의 원소 하나씩으로 변환됩니다. - limit Optional
끊어진 문자열의 최대 개수를 나타내는 정수입니다. 이 매개변수를 전달하면 split() 메서드는 주어진 separator가 등장할 때마다 문자열을 끊지만 배열의 원소가 limit개가 되면 멈춥니다. 지정된 한계에 도달하기 전에 문자열의 끝까지 탐색했을 경우 limit개 미만의 원소가 있을 수도 있습니다. 남은 문자열은 새로운 배열에 포함되지 않습니다.
// split 예제
var myString = 'Hello World. How are you doing?';
var splits = myString.split(' ', 3);
console.log(splits); //["Hello", "World.", "How"]
// limit를 안 쓸 경우
let mystring = 'Hello';
console.log(mystring.split('')); // [ 'H', 'e', 'l', 'l', 'o' ]
여기서 제가 구하고 싶은 값은 테스트 1번으로 예시로 들자면(n=45)
1200 -> [1, 2, 0, 0]으로 바꾸고 싶은 거니까
limit를 안 쓰고 ''만 넣어서 사용하겠습니다.
테스트 1 : n=45
n.toString(3) -> 1200
let ternary = n.toString(3).split(''); -> ['1', '2', '0', '0']
테스트 2 : n=125
n.toString(3) -> 11122
let ternary = n.toString(3).split(''); -> [ '1', '1', '1', '2', '2' ]
2단계. 3진법을 역순으로
// 2단계. 3진법을 역순으로
let reverse = ternary.reverse().join('');
- reverse() : 1단계에서 만든 배열을 역순으로
- join('') : 역순으로 바꾼 배열을 다시 합치기
앞에서 설명했지만 배열을 역순으로 바꾸기 위해서는 reverse()가 필요한데요.
MDN Web Docs
reverse() 메서드는 배열의 순서를 반전합니다. 첫 번째 요소는 마지막 요소가 되며 마지막 요소는 첫 번째 요소가 됩니다.
구문 : a.reverse()
// reverse 예제
const a = [1, 2, 3];
console.log(a); // [1, 2, 3]
a.reverse();
console.log(a); // [3, 2, 1]
그다음 join()을 해줘서 배열을 다시 합쳐주어야 됩니다.
join()을 해주는 이유는 3진법을 앞뒤 반전시킨걸 다시 10진법으로 바꾸기 위해서는 배열의 원소 문자열로 합쳐야 되기 때문입니다.
MDN Web Docs
join() 메서드는 배열의 모든 요소를 연결해 하나의 문자열로 만듭니다.
구문 : arr.join([separator])
- separator Optional
- 배열의 각 요소를 구분할 문자열을 지정합니다.
- 이 구분자는 필요한 경우 문자열로 변환됩니다.
- 생략하면 배열의 요소들이 쉼표로 구분됩니다.
- separator가 빈 문자열이면 모든 요소들이 사이에 아무 문자도 없이 연결됩니다.
// join예제
var a = ['바람', '비', '불'];
var myVar1 = a.join(); // myVar1에 '바람,비,불'을 대입
var myVar2 = a.join(', '); // myVar2에 '바람, 비, 불'을 대입
var myVar3 = a.join(' + '); // myVar3에 '바람 + 비 + 불'을 대입
var myVar4 = a.join(''); // myVar4에 '바람비불'을 대입
제가 원하는 답은 [ '0', '0', '2', '1' ] -> 0021으로 변환하니까
위에 예제 마지막 줄처럼 join('');을 써주고 reverse 변수에 담아주었습니다.
3단계. 역순 3진법을 10진법으로
// 3단계. 역순 3진법을 10진법으로
return parseInt(reverse, 3);
- parseInt(reverse, 3) : 3진법을 10진법으로
역순한 3진법을 다시 10진법으로 바꾸어 주어야 되는데 이때 parselInt()를 사용했습니다.
- toString() : 10진법을 2~36사이의 진법으로 바꿀 때 사용
- parseInt() : 2~36사이의 진법을 10진법으로 바꿀 때 사용
MDN Web Docs
parseInt() 함수는 문자열 인자를 파싱하여 특정 진수(수의 진법 체계에서 기준이 되는 값)의 정수를 반환합니다.
구문 : parseInt(string)
구문 : parseInt(string, radix)
- string : 파싱할 값입니다. 문자열이 아닐 경우 ToString 추상 연산을 사용해 문자열로 변환합니다. 문자열의 선행 공백은 무시합니다.
- radix Optional : string의 진수를 나타내는 2부터 36까지의 정수입니다. 주의하세요. 기본 값이 10이 아닙니다! Number 자료형이 아닌 경우 Number로 변환합니다.
//parseInt 예제
parseInt('0e0') // 0
parseInt('08') // 8
// 15를 반환
parseInt('0xF', 16)
parseInt('F', 16)
parseInt('17', 8)
parseInt(021, 8)
parseInt('015', 10) // parseInt('015', 8)이었다면 13을 반환
parseInt(15.99, 10)
parseInt('15,123', 10)
parseInt('FXX123', 16)
parseInt('1111', 2)
parseInt('15 * 3', 10)
parseInt('15e2', 10)
parseInt('15px', 10)
parseInt('12', 13)
?진번 -> ?진법에 대해 예제를 한눈에 알고 싶다면 아래에 있는 블로그 참고하시면 좋을 것 같아요.👇
https://unikys.tistory.com/334
[자바스크립트] 16진수와 10진수, 8진수, 2진수 변환하기
* 자바스크립트의 간단한 함수들을 이용하면 진수변환을 아주 쉽게할 수 있다. 10진수 16진수 2진수 8진수 * 10진수 -> 16진수 var dec = 123; var hex = dec.toString(16); // === "7b" * 10진수 -> 2진수 va..
unikys.tistory.com
마지막으로 위에 나온 설명을 다 협쳐 쓰면
return parseInt(n.toString(3).split('').reverse().join(''), 3);
- 주황색 : 10진법을 3진법으로
- 초록색 : 3진법을 역순으로
- 파란색 : 3진법을 10진법으로
여기까지 프로그래머스 3진법 뒤집기 해결방안에 대해 설명해보았습니다.