斐波那契产品


13

您可以将大于0的数字分解为正Fibonacci数字的唯一和。在这个问题中,我们通过重复减去最大可能的正斐波那契数来做到这一点。例如:

1 = 1
2 = 2
3 = 3
4 = 3 + 1
12 = 8 + 3 + 1
13 = 13
100 = 89 + 8 + 3

现在,我将斐波那契乘积称为与上面相同的列表,但加法运算被乘积代替。例如,f(100) = 89 * 8 * 3 = 2136

编写一个给定正整数n的程序或函数,该函数将返回该数字的斐波那契乘积。


测试用例:

1: 1
2: 2
3: 3
4: 3
5: 5
6: 5
7: 10
8: 8
9: 8
42: 272
1000: 12831
12345: 138481852236

6
该说法不太正确。例如2可以分解为-1 + 3。Zeckendorf定理的正确说法是,正斐波那契数可以唯一分解为具有正指数的非连续斐波那契数之和。
彼得·泰勒

1
@PeterTaylor对于这个问题,我不认为负斐波那契数是该系列的一部分。连续或仅在需要索引时才重要,我们不在乎此问题的索引。
orlp

1
我并不是说您应该更改问题以支持负斐波那契数:我是说您应该对其进行编辑,以明确表明您所做的假设。
彼得·泰勒

1
@orlp是连续的还是无关紧要的,因为两种不同的形式将给出两种不同的乘积。但是,您已经以一种已经隐式排除了连续的斐波那契项的方式说明了问题,因此不必担心。
霍布斯(Hobbs)

2
(特别是:F(n)和F(n + 1)都不会出现在输出中,因为算法保证在考虑它们之前,余数已经小于F(n + 2)= F(n)+ F(n + 1))
霍布斯(Hobbs

Answers:


5

果冻16 15 字节

Rf1+С¤ṪạµÐĿIAP

并不是特别快或对内存不友好,但是对于所有测试用例都足够有效。在线尝试!

怎么运行的

Rf1+С¤ṪạµÐĿIAP  Main link. Argument: n (integer)

         µ       Combine the chain to the left into a link.
          ÐĿ     Apply that link until the results are no longer unique.
                 Return the list of unique results.
      ¤            Combine the two links to the left into a niladic chain.
  1                  Set the left (and right) argument to 1.
   +D¡               Apply + to the left and right argument, updating the left
                     argument with the sum, and the right argument with the
                     previous value of the left one. Return the list of results.
                     Repeat this process n times.
                   This yields n + 1 Fibonacci numbers, starting with 1, 2.
R                  Range; map k to [1, ..., k].
 f                 Filter; keep the items in the range that are Fibonacci numbers.
       Ṫ           Tail; yield the last one or 0 if the list is empty.
        ạ          Absolute difference with k.
                   This is the argument of the next iteration.
            I    Compute the increments of the arguments to the loop, yielding
                 the selected Fibonacci numbers (with changed sign).
             A   Apply absolute value to each.
              P  Compute their product.  

6
丹尼斯,这似乎很大。
orlp

9

Python,54个字节

f=lambda n,a=1,b=1:n<1or b>n and a*f(n-a)or f(n,b,a+b)

只是一些不错的旧递归。


5

Perl,69 63 + 4(-pl61标志)= 67字节

#!perl -pl61
while($_){$n=$m=1;($n,$m)=($m,$n+$m)until$m>$_;$_-=$n;$\*=$n}}{

使用:

> echo 42 | perl -pl61e 'while($_){$n=$m=1;($n,$m)=($m,$n+$m)until$m>$_;$_-=$n;$\*=$n}}{'

取消高尔夫:

while (<>) {
# code above added by -p
    # $_ has input value
    # $\ = 1 by -l61
    while ($_ != 0) {
        my $n = 1;
        my $m = 1;
        while ($m <= $_) {
            ($n, $m) = ($m, $n + $m);
        }
        $_ -= $n;
        $\ *= $n;
    }
} {
# code below added by -p
    print;  # prints $_ (undef here) and $\
}

伊迪恩


解释应该提到八进制061是字符的ASCII编码'1'。不错的技巧,$\可用于几乎免费打印。
彼得·科德斯

2

JavaScript(ES6),78个 42个字节

f=(n,a=1,b=1)=>n?b>n?a*f(n-a):f(n,b,a+b):1

@ Sp3000的答案的端口。原始的78字节版本:

f=(n,a=[2,1])=>n>a[0]?f(n,[a[0]+a[1],...a]):a.map(e=>e>n?0:(r*=e,n-=e),r=1)&&r

2

> <>,57字节

111\ ;n{/
:@+>:{:})?\$:@@
~{*}:0=?\}>:0${:})?$~:{$-$:1@?$

期望输入号在程序启动时出现在堆栈上。

f0, f1, f2, ..., fn在堆栈上建立斐波那契数列(),直到达到大于输入(i)的数字为止。然后,将产品(p)初始化为1...

while (i != 0)
   if (fn <= i)
      i = i - fn
      p = p * fn
   else
      i = i - 0
      p = p * 1
   discard fn
output p

在线试用!


真好!我建议您发布使用链接在线编译器
路易斯Mendo


1

Pyth,24个字节

W=-QeaYh.WgQeH,eZsZ1;*FY

在线尝试:演示测试套件

说明:

Q 被分配了输入编号。

该部分h.WgQeH,eZsZ1计算最大斐波那契数,该数小于或等于Q

h.WgQeH,eZsZ1
            1   start with H=Z=1
 .WgQeH         while Q >= end(H):
       ,eZsZ       H=Z=(end(Z), sum(Z))
h               first

因此,如果Q = 10,它将生成数字/对:

1 -> (1,1) -> (1,2) -> (2,3) -> (3,5) -> (5,8) -> (8,13) -> 8

其余代码计算分区并将数字相乘:

W=-QeaY...;*FY    implicit: Y = empty list
     aY...        add the calculated Fibonacci number to the empty list
    e             take the last element of Y (yes the number we just added)
 =-Q              and update Q with the difference of Q and ^
W         ;       continue until Q == 0
           *FY    multiply all number in Y and print

显然有很多更短的解决方案(尽管运行时确实很差),例如*FhfqQsTyeM.u,eNsNQ1


1

Haskell,44个字节

可以互相递归:

(a&b)c|c<1=1|b>c=a*f(c-a)|d<-a+b=b&d$c
f=0&1
  • a 是以前的斐波那契数
  • b 是当前的斐波那契数
  • c 是输入
  • f 是所需的功能

少打高尔夫球:

(a & b) c | c == 0    = 1
          | c <  b    = a * f (c-a)
          | otherwise = b & (a + b) $ c
f x = (0 & 1) x

1

其实22个位元组

W;╗uR♂F;`╜≥`M░M;╜-WXkπ

在线尝试!

说明:

W;╗uR♂F;`╜≥`M░M;╜-WXkπ
                        (implicit input)
W                 W     while top of stack is truthy:
 ;╗                       push a copy of n to reg0
   uR♂F;                  push 2 copies of [Fib(a) for a in range(1, n+2)]
        `╜≥`M░            filter: take values where n <= Fib(a)
              M;          two copies of maximum (call it m)
                ╜-        subtract from n (this leaves n-m on top of the stack to be the new n next iteration, with a copy of m below it)
                   X    discard the 0 left over after the loop ends
                    kπ  product of all stack values

实际有自己的编码吗?我在22个字符中计算了35个字节。mothereff.in/…–

1
@cat就像认真地一样,它使用CP437。
Mego

1

使用Javascript(ES6)134个 106 92字节

感谢@cat发现空间。

n=>{for(c=[a=b=s=1,1];a+b<=n;)a+=b,c.unshift(b+=a,a);c.map(i=>i<=n&&(n-=i)&(s*=i));alert(s)}

刚回到家时,我会在手机上制作未经优化的版本。欢迎提出想法。


一个多余的空格。:P

1

返回,44字节

[a:[a;][1$[¤¤+$a;->~][]#%$␌a;\-a:]#␁[¤][×]#]

Try it here.

令人惊讶的是效率低下的匿名lambda导致结果在Stack2上。用法:

12345[a:[a;][1$[¤¤+$a;->~][]#%$␌a;\-a:]#␁[¤][×]#]!

注:␌和␁是为各自的非打印字符的占位符:进纸标题开始

说明

[                                           ]  lambda
 a:                                            store input to a
   [  ][                         ]#            while loop
    a;                                           check if a is truthy
        1$[¤¤+$a;->~][]#%                        if so, generate all fibonacci numbers less than a 
                         $␌                      push copy of TOS to stack2
                           a;\-a:                a-=TOS
                                   ␁[¤][×]#   get product of stack2

我在42个字符中计数46个字节。如果RETURN使用了一些有点特殊编码,它应该是跨越42个字符42个字节,但它似乎是unicode的,所以它的46

实际上,我只是意识到我忘记放入一些无法打印的东西。
Mama Fun Roll

我需要一个显微镜来告诉它们是什么,所以我为您链接了它们。:d(我不知道,如果它是SOH或BOM)

0

PHP,119字节

代码(为了便于阅读,包装在两行中):

for($o=$c=1;$c<=$n=$argv[1];$f[++$k]=$c,$a=$b,$b=$c,$c+=$a);
for($i=$k;$i;$i--)for(;$n>=$d=$f[$i];$n-=$d,$o*=$d);echo$o;

第一行计算$f的斐波那契数小于$n(命令行中提供的参数)。第二行(通过减法)计算斐波那契因子并将其乘以计算的乘积$o

在代码前面加上<?php(技术上不是程序的一部分),将其放在文件(fibonacci-factors.php)中,然后按以下方式运行:

$ php -d error_reporting=0 fibonacci-factors.php 100
# The output:
2136

或使用来运行它php -d error_reporting=0 -r '... code here ...' 100

可以在Github上找到未发布的代码和测试套件。


0

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是不同的args

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 n次应用function(function(function(...(function(args))))(内部使用tal递归),并返回结果序列。我们将fibonnaci系列的60个第一项计算为*+60(|+\)\1 0。在这种情况下,函数为( | +):加在序列上的+ \会计算部分和(ex + \ 1 2 3为1 3 6),|反转seq。因此,每次“迭代”时,我们都会计算前两个斐波那契数的部分和,并返回部分求和后求和,60(|+\)\1 0生成序列1 0,1 1,2 1,3 *+2,5 3,8 5,13 8,21 13,... 应用于结果翻转(置位)并取第一个,结果为序列1 1 2 3 5 8 13 21 34 55 ..

(cond)function\args 在cond true时应用function(function(.. function(args))),并返回部分结果的序列

function[arg] 在一个以上参数的函数上应用会创建一个投影(部分应用)

我们可以给args命名,但是隐式名称是x,y,z

{y-x x bin y}[*+60(|+\)\1 0]声明带有部分投影的args x,y的lambda(arg x是斐波那契数列,计算为* + 60(| +)\ 1 0)。x代表斐波那契值,y代表要处理的数字。二进制搜索(bin)用于定位更大的斐波那契数<= y(x bin y)的索引,并减去x的对应值。

要从部分结果计算乘积,我们将它们反转并计算每对(-':|)的差,删除第一个(1_因为是0)并乘以(*/)。

如果我们对累计和感兴趣,则代码是相同的,但是用+/代替*/。我们还可以使用任何其他双向运算符代替+或*

关于执行效率

我知道在这场比赛中效率不是问题。但是在这个问题上,我们可以从线性成本到指数成本不等,所以我对此感到很好奇。

我开发了第二个版本(不包括注释,长度为48字节),并在两个版本上重复测试了1000次电池。

f:*+60(|+\)\1 0;m:{*/1_-':|(0<){x-f f bin x}\x}    /new version

执行时间是:原始版本0'212段,新版本0'037段

原始版本每个功能应用程序一次计算fibbonaci序列;新版本只计算斐波那契。

在这两种情况下,斐波那契数列的计算均使用尾递归

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.