https://school.programmers.co.kr/learn/courses/30/lessons/12899#
모든 숫자를 1, 2, 4로 나타내는 나라가 있을 때, 이 나라에서 나타내는 숫자는 다음과 같이 변환된다.
자연수 n이 매개변수로 주어질 때, n을 124 나라에서 사용하는 숫자로 바꾼 값을 return 하도록 코드를 작성하라.
이 나라의 숫자는 모두 1, 2, 4로 구성된다. 여기서 생각할 수 있는 것은 10진법의 수를 3진법으로 나타내서 구하면 되는게 아닌가 싶지만, 0이라는 숫자를 사용하지 않기 때문에 일반적인 3진법과는 조금 다른 부분이 생긴다. 따라서 숫자를 3진법으로 변환한 뒤에 추가 작업을 거치면 답을 구할 수 있다.
예를 들어 9라는 숫자가 있을 때 3진법으로 나타내면 100이라는 값을 가진다. 하지만 124나라에서는 24라는 값을 가진다.
생각해야하는 로직은 간단하다.
- 0보다 작은 숫자가 온다면 바로 앞의 값에서 -1을 진행하고 자신에서 3을 가져온다.
- 3이라는 숫자에 대해서 4로 치환한다.
1번은 쉽게 말해 우리가 뺄셈을 진행할 때 자릿 수 별로 뺄셈이 진행될 텐데 두 수를 비교해서 뒤의 수가 크면 바로 앞 자리에 -1을 진행하고 10을 가져와서 뺄셈을 진행하는 방법처럼 생각을 하면 된다. 이 방식을 값을 비교하는 곳에서 0이 온다면 진행을 해주면 된다.
2번은 124 나라에서는 3을 사용하지 않기 때문에 그저 3에 대해서 4로 치환해주면 된다.
문제를 풀 때는 해당 값을 우선 배열로 바꿔주고 푸는 것이 좀 더 쉽게 풀 수 있다. 따라서 9를 3진법으로 바꾸고 배열로 다시 구성해주면 [1, 0, 0]이다.
계산 자체는 배열의 가장 마지막부터 진행을 한다. 가장 마지막 값이 0이므로 바로 앞에서 -1을 해주고 3진법이므로 3을 가져와 더해주면 [1, -1, 3]이 된다.
그 다음을 보면 0보다 작으므로 마찬가지로 앞의 수에 -1을 하고 자신에게 3을 더해주면 [0, 2, 3]이 된다.
그 다음을 보면 0이지만 가장 앞에 위치하고 있기 때문에 더 이상 -1을 진행해서 숫자를 끌어올 수가 없기 때문에 배열의 가장 앞에서는 예외를 적용해 작업을 진행하지 않는다.
하지만 0이라는 수를 그대로 남겨놓을 수는 없기 때문에 0이 온다면 shift 함수를 사용해서 제거하는 과정을 거쳐 [2, 3]을 만들어낸다.
마지막으로 배열에서 3을 4로 치환하고([2, 4]) 다시 숫자들을 합쳐주면 124 나라에서 사용하는 숫자들을 만들어낼 수 있다.
function solution(n) {
let arr = n.toString(3).split('')
for(let i = arr.length - 1; i > 0; i--) {
if(arr[i] <= 0) {
arr[i-1] = (parseInt(arr[i-1]) - 1).toString()
arr[i] = (parseInt(arr[i]) + 3).toString()
}
}
if(arr[0] === '0') {
arr.shift()
}
arr.map((el, index) => {
if(el === '3') {
arr[index] = '4'
}
})
return arr.join('')
}
for(let i = arr.length - 1; i > 0; i--) {
if(arr[i] <= 0) {
arr[i-1] = (parseInt(arr[i-1]) - 1).toString()
arr[i] = (parseInt(arr[i]) + 3).toString()
}
}
3진법으로 만든 배열의 가장 마지막으로 앞으로 오면서 작업을 진행한다. 작업은 해당 위치의 수가 0보다 작거나 같으면 바로 앞자리의 수에서 -1을 진행하고 자신에게 3을 더하는 과정을 진행한다. 이 반복은 가장 앞자리에서는 진행을 하지 않는다.
if(arr[0] === '0') {
arr.shift()
}
이론 상 배열의 가장 앞에는 0이 가장 작은 숫자이므로 (-1이 올 수 없다.) 0일 경우에 shift 함수를 실행해서 없애준다.
마지막으로 배열의 3에 대해서 4로 치환하는 과정을 거치고 배열을 합쳐서 반환해준다.