Q, 47 바이트
m:{*/1_-':|(0<){y-x x bin y}[*+60(|+\)\1 0]\x}
테스트
+(i;m'i:1 2 3 4 5 6 7 8 9 42 1000 12345)
쌍으로 읽습니다 (i, map (m, i)). 여기서 m은 계산 함수이고 i는 다른 인수입니다.
글을
1 1
2 2
3 3
4 3
5 5
6 5
7 10
8 8
9 8
42 272
1000 12831
12345 138481852236
설명
n funtion\arg
function (function (function (... function (args))) n 번 (내부적으로 tal recursion을 사용함)을 적용하고 결과 시퀀스를 반환합니다 *+60(|+\)\1 0
. | +) : 시퀀스에 적용된 + \는 부분합을 계산하고 (예 : + \ 1 2 3은 1 3 6), | sums reversed. 60(|+\)\1 0
시퀀스 1 0, 1 1, 2 1, 3 2, 5 3, 8 5, 13 8, 21 13을 생성합니다. ... *+
이 결과 플립에 적용되고 첫 번째 결과를 얻습니다. 1 2 3 5 8 13 21 34 55 ..
(cond)function\args
cond true 인 동안 function (function (.. function (args)))을 적용하고 부분 결과 시퀀스를 반환합니다.
function[arg]
둘 이상의 인수 함수에 적용하면 투영이 생성됩니다 (부분 적용)
인수에 이름을 지정할 수 있지만 내재적 이름은 x, y, z입니다.
{y-x x bin y}[*+60(|+\)\1 0]
부분 프로젝션을 사용하여 args x, y가있는 람다를 선언합니다 (arg x는 피보나치 계열이며 * + 60 (| +) \ 1 0으로 계산). x는 피보나치 값을 나타내고, y는 처리 할 숫자입니다. 이진 검색 (bin)은 더 큰 피보나치 수 <= y ( x bin y
) 의 인덱스를 찾아 해당 x 값을 뺍니다.
부분 resuls에서 제품을 계산하기 위해 우리는 그것들을 뒤집고 각 쌍의 차이를 계산하고 ( -':|
) 첫 번째를 버리고 ( 1_
0이기 때문에) 곱합니다 ( */
).
누적 합계에 관심이 있다면 코드는 동일하지만 +/
대신에 동일 */
합니다. + 또는 * 대신 다른 분음 연산자를 사용할 수도 있습니다
실행 효율에 대해
이 콘테스트에서 효율성은 문제가되지 않습니다. 그러나이 문제에서 우리는 직계 비용에서 지수 비용에 이르기까지 다양 할 수 있으므로 궁금합니다.
두 번째 버전 (주석을 제외한 길이 48 바이트)을 개발하고 두 버전에서 테스트 케이스 배터리를 1000 번 반복했습니다.
f:*+60(|+\)\1 0;m:{*/1_-':|(0<){x-f f bin x}\x} /new version
실행 시간은 원래 버전 0'212 seg, 새 버전 0'037 seg
원래 버전은 기능 적용마다 한 번씩 피보 나시 세리를 계산합니다. 새 버전은 피보나치를 하나만 계산합니다.
두 경우 모두 피보나치 시리즈 계산에는 꼬리 재귀가 사용됩니다.
2
를 들어로 분해 할 수 있습니다-1 + 3
. Zeckendorf의 정리에 대한 올바른 진술은 양의 피보나치 수는 양의 지수를 가진 비 연속적인 피보나치 수의 합으로 고유하게 분해 될 수 있다는 것입니다.