Write a function, persistence
, that takes in a positive parameter num
and returns its multiplicative persistence, which is the number of times you must multiply the digits in num
until you reach a single digit.
For example:
persistence(39) === 3 // because 3*9 = 27, 2*7 = 14, 1*4=4
// and 4 has only one digit
persistence(999) === 4 // because 9*9*9 = 729, 7*2*9 = 126,
// 1*2*6 = 12, and finally 1*2 = 2
persistence(4) === 0 // because 4 is already a one-digit number
🚩 문제해석
주어진 숫자(parameter)를 한자리씩 곱해서 나온 수가 한자리 수가 될 때까지 몇 번을 반복해야 하는지를 구해서 그 반복횟수를 결과값으로 리턴하시오. 이미 주어진 수가 한자리 수라면 반복 횟수가 없기때문에 결과값은 0이 된다.(example)
첫번째 생각
/ 와 %를 이용하여 숫자로 접근해서 풀어볼까?
첫번째 풀이
```javascript
function persistence(num) {
let cnt = 0;
while(num >= 10){
let mul = 1;
let tmp = num;
while(tmp > 0){
mul *= tmp % 10;
tmp = Math.floor(tmp / 10);
}
num = mul; cnt++;
}
return cnt;
}
```
while문을 사용한 이유는 주어진 수가 몇자리 수가 될지 알 수가 없기 때문이다. 또한 몇 번을 반복하면 되는지도 알 수가 없다. 결국 2번의 while문을 사용할 수 밖에 없었다.
두번째 생각
각 자리수를 배열에 넣으면 자리수로 접근하기가 수월하니까 우선 배열로 바꿔서 풀어볼까?
두번째 풀이
```javascript
function persistence(num) {
let cnt = 0;
while(num >= 10){
num = String(num).split('').reduce((a,v)=>Number(a)*Number(v),1);
cnt++;
}
return cnt;
}
```
const persistence = num => {
return `${num}`.length > 1
? 1 + persistence(`${num}`.split('').reduce((a, b) => a * +b))
: 0;
}
재귀적 풀이. 항상 반복하는 경우에 재귀적 풀이가 가능하다. 하지만 재귀적인 접근을 안하게된다, 대신 반복문을 주로 사용한다. 아마도 익숙해서 그런것같다. 또 재귀적 접근은 항상 stack overflow 의 이슈를 갖고 있다. 그럼에도 이 코드는 적재적소에 ES6 문법을 잘 사용하였다. 어떤 식으로 ES6를 사용했는지 알아보자.
첫번째는 Number타입을 String타입으로 바꾸는 방법이다. 이 부분을 template literals이라는 문법을 사용하였다.
두번째는 reduce() 메소드이다. 지금까지 문제를 풀어올 때마다 많이 사용한 메소드로 다시 한 번 설명하면, 배열에서 하나의 (누적된) 결과값을 보여주고 싶을 때 사용한다. ( 참고. MDN reduce() )
세번째는 화살표함수(arrow function) 이다. 내가 잘 사용하지않는 구문이긴하다. 알고는 있는데 잘 사용이 안된다. 😥
기본 구문
```javascript
(param1, param2, …, _paramN) => expression
// 다음과 동일함: => { return expression }
// 매개변수가 하나뿐인 경우 괄호는 선택사항
(singleParam) => { statements }
singleParam => { statements }
// 매개변수가 없는 함수는 괄호가 필요
() => { statements }
//리턴값 표시
(...params) => 'return' 이라는 말 생략가능 : 바로 나온 코드가 리턴값이 된다.
(...params) => {
code here
'return' 이라는 말 생략을 못하고 명시적으로 적어줘야한다.
}
```
arrow function을 사용하는 이유는 무엇일까? 이것도 코드가 직관적이고 간결해지기 때문에 사용한다. 하지만 아직 모든 곳에서 이 구문을 사용할수있는 것은 아니라고 한다. 작업환경(브라우저환경)에 따라서 적용이 안되는 곳도 있다고 한다.(특히 IE....) React를 처음 사용할 때 화살표함수를 정확히 사용할 줄 몰라서 애먹은적이 있었다. 보기에는 쉬워보여도 구문이 길어지면 어떻게 매개변수를 써야할지 혹은 리턴값은 어떻게 나타내는지 헷갈릴 수 있다. 익숙해져야 할 구문이다.
네번째는 ES6 문법은 아니지만 재치있는 코드인 +b 이다. 처음엔 왜 +를 넣은거지라는 의문이 들었다. 여러가지 실험을 해보니, +b는 b라는 문자(열)을 정수화시켜주기 위한 코드였다. 보통 정수화시킬 때는 Number()나 parseInt()를 많이 사용하는데 이렇게도 사용할 수 있다는 것을 처음 알게 되었다. 마치 문자열을 만들어주기 위해서 5+'' 와 같은 용도로 사용하였다.
점차적으로 문제풀이를 함수형으로 풀어나가는데 익숙해지는 것 같다. 하지만 항상 생각해봐야 할 것은 한 줄로 간단하게 푼다고 해서 그것이 좋은 풀이는 아니라는 점이다. 항상 내 생각하는 바를 명확하고 간결하게 코드로서 나타내려고 노력하는 연습을 해야겠다. 어렵지않은 문제였지만 내가 의도한바를 코드로 표현하였다면, 그것만으로도 목표 달성이라고 생각한다.
MDN Template literals
arrow_function의 장점은?
MDN 화살표 함수
🚀 문제를 풀어나갈 때 생각의 흐름을 정리합니다. 또한 새로운 풀이에 대한 코드를 분석하고 모르는 부분에 대해서 정리합니다. 생각이 다른 부분에 대한 피드백은 언제나 환영합니다. 틀린 내용에 대한 피드백 또한 항상 감사합니다.