-
[알고리즘/자바스크립트] 트리보나치 수열 구하기 (Tribonacci Sequence)Algorithm 2019. 2. 20. 22:02
-해당 문제는 codewars사이트의 level6 문제입니다. (1~8단계 중 8단계가 가장 쉬운 레벨)-
[문제] Well met with Fibonacci bigger brother, AKA Tribonacci.
As the name may already reveal, it works basically like a Fibonacci, but summing the last 3 (instead of 2) numbers of the sequence to generate the next. And, worse part of it, regrettably I won't get to hear non-native Italian speakers trying to pronounce it :(
So, if we are to start our Tribonacci sequence with [1, 1, 1] as a starting input (AKA signature), we have this sequence:
[1, 1 ,1, 3, 5, 9, 17, 31, ...]
But what if we started with [0, 0, 1] as a signature? As starting with [0, 1] instead of [1, 1] basically shifts the common Fibonacci sequence by once place, you may be tempted to think that we would get the same sequence shifted by 2 places, but that is not the case and we would get:
[0, 0, 1, 1, 2, 4, 7, 13, 24, ...]
Well, you may have guessed it by now, but to be clear: you need to create a fibonacci function that given a signature array/list, returns the first n elements - signature included of the so seeded sequence.
Signature will always contain 3 numbers; n will always be a non-negative number; if n == 0, then return an empty array and be ready for anything else which is not clearly specified ;)
If you enjoyed this kata more advanced and generalized version of it can be found in the Xbonacci kata
[Personal thanks to Professor Jim Fowler on Coursera for his awesome classes that I really recommend to any math enthusiast and for showing me this mathematical curiosity too with his usual contagious passion :)]
[해석] 말그대로 트리보나치 수열을 구하는 문제! 피보나치 수열은 첫째 및 둘째 항이 1이며 그 뒤의 모든 항은 바로 앞 두 항의 합인 수열이다. 트리보나치는 피보나치 수열과 거의 같은데 대신 두 항의 합이 아닌 세 항의 합을 구한다.
함수에 초기 숫자 배열인 signature와 n을 넣는데 트리보나치 수열을 n개로 만들어 return시키면 된다.
예를 들어 tribonacci ([1,1,1],10) 함수는 [ 1, 1, 1, 3, 5, 9, 17, 31, 57, 105 ]을 return한다.
tribonacci ([0, 0, 1], 0) => []
tribonacci ([1, 1, 1], 1) => [1]
tribonacci ([0, 1, 1], 5) => [0, 1, 1, 2, 4]
이 문제는 푸는 데 시간이 꽤 걸렸다ㅜㅜ
사실 코드도 그렇게 간단하게 짠 것 같지가 않다.
다른 사람 풀이 보니까 간단한게 짠게 많던데 아직 부족한게 많은듯.
어쨌든 이 문제는 한칸씩 밀어서 계속 3개씩 합하고 그 숫자를 계속 배열 마지막에 추가해야한다는게 핵심이다.
처음에 짠 코드는 아래와 같다.
function tribonacci (signature, n) { var num = 0; if(n <= 3) { return signature.splice(0, n) } while (num < n-3) { var sum=0 for(var i=num; i<num+3; i++) { sum += signature[i] } signature.push(sum) num++; } return signature }
일단 num이라는 초기값을 0으로 두었다.
그리고 n이 3보다 작거나 같으면 signature배열을 0부터 그 n번까지 잘라서 return했다.
그래야 n이 3보다 작은 경우에도 불필요하게 for문을 도는 일이 없을테니까.
그리고 for문으로 배열에 있는 숫자를 3개씩 더하면서 반복을 하는데
그 더하는 과정을 n-3번해야한다.
왜 n-3이냐면 초기 배열 요소의 개수가 3이고 거기에 n-3개의 숫자를 추가해서 총 n개의 숫자가 든 배열을 만들어야하기 때문이다.
그리고 sum이란 변수를 주고 signature[i]를 3번 더한 값을 배열에 push()로 추가해준다.
추가되고 난 후 num을 하나씩 증가시켜줌으로서 이 과정을 n-3번 반복한다.
일단 이렇게 짠 코드는 제대로 잘 작동되어 테스트는 통과하였다.
그런데 문제는 코드가 너무 쓸데없이 길다는거!
항상 처음에 짠 코드를 여러 번 잘 읽어보면 불필요한 구석이 있다.
예를들면 while문 안에 for문을 돌린거. 반복을 2번이나 하는 셈인데
생각해보면 무조건 숫자는 3개만 더할거라 굳이 for문을 쓸 필요가 없는 느낌.
function tribonacci (signature, n) { if(n <= 3) { return signature.splice(0, n) } for(var i=0; i<n-3; i++) { signature.push(signature[i] + signature[i+1] + signature[i+2]) } return signature }
그렇게 줄이고 줄여서 다시 짠 코드.
for문을 n-3번만큼 돌리고
signature 배열에 signature[i] + signature[i+1] + signature[i+2]를 push해준다.
이렇게 일렬로 쭉 쓰면 될 것을 sum이란 변수를 만들어서 반복을 돌리고
while문을 써서 num이란 숫자를 ++시켜서 돌리고 할 필요가 없었던 것 같다.
while문은 주로 몇 번 반복할지 확실치 않은 경우에 쓰면 좋다고 배웠는데
이 경우에는 몇 번 반복하는지 확실하게 정해져있으니 for문이 맞는 것 같다.
다시 테스트해봤더니 확실히 아까의 코드보다 속도가 빨라졌다!
짝짝짝
반응형'Algorithm' 카테고리의 다른 글
[알고리즘/자바스크립트] 배열의 특정요소만 맨 뒤로 옮기기 (Moving Zeros To The End) (0) 2019.02.24 [알고리즘/자바스크립트] 어떤 값의 개수가 홀수인지 판별하기 (Find the odd int) (0) 2019.02.24 [알고리즘/자바스크립트] 홀수 짝수 판별하여 map()으로 배열 재구성하기 (WeIrD StRiNg CaSe) (0) 2019.02.19 [알고리즘/자바스크립트] 삼각형 판별문제 (Is this a triangle?) (0) 2019.02.18 [알고리즘/자바스크립트] 완벽한 제곱근 구하기 (Find the next perfect square!) (0) 2019.02.18 COMMENT