斐波那契分解


21

斐波那契数

斐波那契数字的开头为f(1) = 1f(2) = 1(其中有些包括,f(0) = 0但这与挑战无关。然后,对于n > 2f(n) = f(n-1) + f(n-2)

挑战

您的任务是找到并输出n可以表示为斐波纳契数的乘积的第-个正数。您可以选择使其更适合0索引或1索引,但您必须在答案中指定它。

另外,您的答案必须在合理的时间内计算出第100个项。

测试用例

n   result corresponding product (for reference)
1   1      1
2   2      2
3   3      3
4   4      2*2
5   5      5
6   6      2*3
7   8      2*2*2 or 8
8   9      3*3
9   10     2*5
10  12     2*2*3
11  13     13
12  15     3*5
13  16     2*2*2*2 or 2*8
14  18     2*3*3
15  20     2*2*5
16  21     21
17  24     2*2*2*3 or 3*8
18  25     5*5
19  26     2*13
20  27     3*3*3
100 315    3*5*21

参考文献


在测试用例中,为什么为什么其中一些n =结果,而对于7及以上,它们不相等。也许我不明白这个问题。但是我只想查看一下
乔治

1
7不能表示为斐波那契数的乘积。因此,1st所需数字为12nd为2,...,6th为6,但7th为8
Leaky Nun

嗯,这当然是有道理的
乔治

您是否应该打印所有方式来制作号码。例如16有两种方式,还是可以只输出一种?
乔治

3
@george,我相信“ corresponding product”仅用于澄清。您的代码仅需要输出“ result”。
trichoplax

Answers:


6

果冻26 24 23 21 字节

ÆDf÷߀FðḊ¡
1ç#2+С1¤Ṫ

在线尝试!

怎么运行的

1ç#2+С1¤Ṫ  Main link. Argument: n (integer)

        ¤   Combine the three links to the left into a niladic chain.
   2          Set the left argument and the return value to 2 (third positive
              Fibonacci number).
       1      Yield 1 (second positive Fibonacci number).
    +С       Compute the sum of the return value and right argument, replacing the
              return value with the sum and the right argument with the previous
              return value.
              Do this n times, collecting all return values in a list.
              This returns A, the first n Fibonacci numbers greater than 1.
1             Set the return value to 1.
 ç#           Call the helper link with left argument k = 1, 2, 3... and right
              argument A = [2, 3, 5...] until n of them return a truthy value.
              Collect the matches in a list.
           Ṫ  Tail; extract the last (n-th) match.


ÆDf÷߀FðḊ¡    Helper link. Left argument: k. Right argument: A

        Ḋ     Dequeue; yield r := [2, ..., k].
       ð ¡    If r in non-empty, execute the chain to the left. Return k otherwise.
ÆD              Yield the positive divisors of k.
   ÷            Divide k by all Fibonacci numbers in A.
  f             Filter; keep divisors that belong to k÷A, i.e., all divisors
                d for which k÷d belongs to A.
    ߀          Recursively call the helper link for each kept divisor d, with left
                argument d and right argument A.
      F         Flatten the result, yielding a non-empty array iff any of the
                recursive calls yielded a non-empty array or a number.
                If the left argument is 1, the helper link returns 1, so the
                array will be non-empty if the consecutive divisions by Fibonacci
                numbers eventually produced a 1.

2
就输入而言,此算法的复杂性是多少?
Leaky Nun

无论如何,这都是非常快的!第100个学期不到2秒
路易斯·门多

@LeakyNun我不知道如何计算,但是看到输入400比输入100花32倍的时间,我会说它是指数的。虽然可以轻松处理100。
丹尼斯

1
好吧,只有您知道您的算法是什么...
Leaky Nun

通过不为每个测试数字重新计算斐波那契数列,我设法使它更快。打完高尔夫球后,我会加一个解释。
丹尼斯

5

朱莉娅79字节

!k=any(i->√(5i^2+[4,-4])%1k%i<!(k÷i),2:k)^~-k
<|(n,k=1)=n>0?n-!k<|-~k:~-k

在线尝试!

背景

在“ 高级问题和解答”中,H-187:斐波那契是一个正方形,建议者显示

斐波那契/卢卡斯身份

其中L n表示第n 卢卡斯数,反之,如果

逆斐波那契/卢卡斯身份

那么n是斐波那契数,m是卢卡斯数。

怎么运行的

我们<|为我们的目的定义了二进制运算符。它在Julia的最新版本中未定义,但仍被解析器识别为运算符。

当仅使用一个参数(n)调用时,<|k初始化为1。虽然Ñ是正的,它减去!k来1如果ķ是斐波那契数,的产品0如果不)从Ñ并递归调用自身,增量ķ1。一旦n达到0,就可以找到所需量的乘积,因此<|返回k的先前值,即〜-k = k-1

!重新定义为斐波纳契数产品检验的一元运算符完成了以下任务。

  • 如果k = 1,则k是斐波那契数的乘积。在这种情况下,我们将的返回值提高any(...)到幂〜-k = k-1 = 0,因此结果将为1

  • 如果K> 1,则结果将是的值any(....),这将返回当且仅当谓词√(5i^2+[4,-4])%1∋k%i<!(k÷i)返回对于某个整数使得2≤I≤ķ

    谓词中的链式条件if k%i属于√(5i^2+[4,-4])%1k%i小于!(k÷i)

    • √(5i^2+[4,-4])%1取的平方根5I 2 + 45I 2 - 4和计算它们的残基模1。如果对应的数字是一个理想的平方,则每个模数为0;否则,小于1的正数。

      由于k%i返回的整数,它只能属于模量的数组,如果ķ%I = 0(即,ķ是整除)和至少一个间5I 2 + 45I 2 - 4是一个完全平方(即,是斐波那契数)。

    • !(k÷i)以参数k÷i(整数除法)递归调用1,当且仅当k÷i是斐波那契数的乘积时,才大于0

通过归纳,具有所需的属性。


5

Python,90个字节

f=lambda n,a=2,b=3:n<2or n%a<f(n/a)or n-a>0<f(n,b,a+b)
g=lambda k,n=1:k and-~g(k-f(n),n+1)

主要功能g输出k第一个索引的斐波那契乘积。它计算g(100)315几乎瞬间。通用的递归公式就是如此,它计算数量以n寻找k满足功能的实例f。每个这样的实例都会降低所需的计数,k直到达到为止0

辅助功能f测试一个数字为斐波那契产品。它在其可选参数a和中递归生成斐波那契数b。如果满足以下任一条件,则输出“是”:

  • n<2。这意味着n==1,琐碎的产品)
  • n%a<f(n/a)。这需要n%a==0f(n/a)==True,即n斐波那契数的倍数a,并且除去该因子a仍会产生斐波那契乘积。
  • n-a>0<f(n,b,a+b),相当于n>a and f(n,b,a+b)。检查当前正在测试的斐波那契数是否至少不是n,并且更大的斐波那契数能工作。感谢Dennis使用不等式短路代替来节省2个字节and

该函数g可以短一个字节,例如

lambda k:filter(f,range(k*k+1))[k]

如果g(k)始终是if k*k,则我不确定它在渐近情况下是否正确。绑定的2**k就足够了,但随后g(100)的时间太长。也许g可以在中进行递归f


根据OEIS 上的此表g(k)超过和超过k*kk = 47000
isaacg

2

Perl 6的 95  93个字节

{(1..*).grep({$/=$_;map {->{$/%$_||($//=$_);$/}...*!%%$_;0},reverse 2,3,&[+]...*>$_;2>$/})[$_]}
{(1..*).grep({$/=$_;map {->{$/%$_||($//=$_);$/}...*%$_;0},reverse 2,3,&[+]...*>$_;2>$/})[$_]}

(基于0的索引)

测试:

my &fib-prod = {(1..*).grep({$/=$_;map {->{$/%$_||($//=$_);$/}...*%$_;0},reverse 2,3,&[+]...*>$_;2>$/})[$_]}

say fib-prod 0 ..^ 20;
# (1 2 3 4 5 6 8 9 10 12 13 15 16 18 20 21 24 25 26 27)
say time-this { say fib-prod 100 -1; };
# 315
# 1.05135779

sub time-this (&code) {
  my $start = now;
  code();
  now - $start;
}

说明:

{
  (1..*).grep(
    {
      $/ = $_; # copy the input ($_) to $/
      map { # map used just for side effect
        ->{
          $/ % $_    # if $/ is divisible by the current fib factor
        ||
          ($/ /= $_) # divide it out once
        ;
          # return the current value in $/
          $/
        }
        ... # repeat until that returns:
        * !%% $_ # something that is not divisible by the current fib factor
        ;0
      },
      # the possible fibonacci factors plus one, reversed
      # ( the extra is to save one byte )
      reverse 2,3,&[+] ... *>$_;

      # is the end result of factoring equal to 1
      # ( for the grep above )
      2 > $/
    }
  )[ $_ ] # get the value at 0-based index
}

2

Python 3中,175个 170 148字节的

感谢@Dennis提供-22个字节

j=x=int(input())
y=1,1
exec('y+=y[-2]+y[-1],;'*x)
i=c=0
while c<x:
    if j>=x:j=0;i+=1;t=i
    if t%y[~j]<1:t/=y[~j];j-=1
    if t<2:c+=1;j=x
    j+=1
print(i)

从STDIN接收输入并打印到STDOUT。这是一个索引。计算第100个项大约需要十分之一秒。

怎么运行的

j=x=int(input())                Get term number x from STDIN and set Fibonacci number index
                                j to x to force initialisation of j later 
y=1,1                           Initialise tuple y with start values for Fibonacci sequence
exec('y+=y[-2]+y[-1],;'*x)      Compute the Fibonacci sequence to x terms and store in y
i=c=0                           Initialise test number i and term counter c
while c<x:                      Loop until x th term is calculated
    if j>=x:j=0;i+=1;t=i        Initialise Fibonacci number index j, increment i and
                                initialise temp variable t for looping through all j for
                                some i. Executes during the first pass of the loop since
                                at this point, j=x
    if t%y[~j]<1:t/=y[~j];j-=1  Find t mod the j th largest Fibonacci number in y and if no
                                remainder, update t by dividing by this number.
                                Decrementing j means that after a later increment, no
                                change to j occurs, allowing for numbers that are 
                                divisible by the same Fibonacci number more than once by
                                testing again with the same j
    if t<2:c+=1;j=x             If repeated division by ever-smaller Fibonacci numbers
                                leaves 1, i must be a Fibonacci product and c is
                                incremented. Setting j equal to x causes j to be reset
                                to 0 during the next loop execution
    j+=1                        Increment j
print(i)                        i must now be the x th Fibonacci product. Print i to STDOUT

在Ideone上尝试


2

Python 2中,120个 107字节

g=lambda k:1/k+any(k%i==0<g(k/i)for i in F)
F=2,3;k=0;n=input()
while n:F+=F[k]+F[-1],;k+=1;n-=g(k)
print k

Ideone上进行测试

怎么运行的

我们将F初始化为元组(2,3)(前两个斐波那契数大于1),k初始化为0n初始化为从STDIN读取的整数。

n为正数时,我们执行以下操作:

  • 将计算为F [k] + F [-1]的下一个斐波那契数附加到元组F上,即F的最后两个元素之和。

  • 增量k

  • n减去g(k)

当且仅当k是斐波那契数的乘积时g才返回1,因此一旦n达到0,则k是第n 斐波那契数,我们将其打印到STDOUT。

g实现以下目的。

  • 如果k1,则它是斐波那契数的乘积,并1/k确保我们返回1

  • 如果ķ大于1,我们称之为g(k/i)递归所有斐波那契数˚F

    g(k/i)递归测试k / i是否为斐波那契数积。如果g(k/i)返回1并且i均等地划分k,则k%i = 0且条件k%i<g(k/i)成立,因此,且仅当存在斐波那契数,使得k是该斐波那契数与另一个斐波那契数的乘积时,g才返回1


1

JavaScript(ES6),136

用这种方式打高尔夫球相当慢,在我的PC上大约8秒钟就可以计算出100项。

(n,F=i=>i>1?F(i-1)+F(i-2):i+1,K=(n,i=1,d,x)=>eval('for(;(d=F(i++))<=n&&!(x=!(n%d)&&K(n/d)););x||n<2'))=>eval('for(a=0;n;)K(++a)&&--n;a')

少打高尔夫球,也更快(避免eval

n=>{
  F=i=> i>1 ? F(i-1)+F(i-2) : i+1; // recursive calc Fibonacci number
  K=(n,i=1,d,x)=>{ // recursive check divisibility
    for(; (d=F(i++))<=n && !(x=!(n%d)&&K(n/d)); );
    return x||n<2
  };
  for(a=0; n; )
    K(++a) && --n;
  return a
}

测试

X=(n,F=i=>i>1?F(i-1)+F(i-2):i+1,K=(n,i=1,d,x)=>eval('for(;(d=F(i++))<=n&&!(x=!(n%d)&&K(n/d)););x||n<2'))=>eval('for(a=0;n;)K(++a)&&--n;a')

function test() {
  var i=+I.value
  O.textContent=X(i)
}

test()
<input id=I value=100 >
<button onclick="test()">Go</button><pre id=O></pre>


1

Haskell,123个字节

f=2:scanl(+)3f
m((a:b):c)=a:m(b?(a#c))
v#((a:b):c)|v==a=b?(v#c)
_#l=l
y?(z:e)|y>z=z:y?e
a?b=a:b
l=1:m[[a*b|b<-l]|a<-f]
(l!!)

非常懒惰,无限!

可能不是短路的方法,但是我不得不尝试这种方法,这是一种非常知名的方法的通用性,用于计算汉明数列表。f是从2开始的斐波那契数字的列表。为简便起见,假设lol(列表列表)是有序无限列表的无限列表,按其第一个元素排序。m是合并大声笑,删除重复项的功能。它使用两个infix辅助函数。?将无限排序的列表插入大声笑。#从可能出现在第一个列表的开头的lol中删除一个值,并使用来重新插入其余列表?

最后,l是数字列表,它们是斐波那契数字的乘积,定义为1,然后合并通过l与斐波那契数字相乘而获得的所有列表。最后一行指出了所需的函数(通常不将其绑定到名称,因此请不要照原样复制),以使用!!索引到列表中,从而使该函数的索引为0。

计算第100或100,000个数字没有问题。


1

外壳,13个字节

请注意,Husk比此挑战要新。但是,它和本次高尔夫最有用的功能(Ξ)并不是在考虑这一挑战的情况下创建的。

S!!Ṡ¡ȯuΞIṪ*İf

在线尝试!

14字节的更有效版本:

在线尝试!


0

Python 2中,129个 128 125 123 121字节

g=lambda k:1/k|any(abs(round(5**.5*i)**2-5*i*i)==4>k%i<g(k/i)for i in range(k+1))
f=lambda n,k=1:n and f(n-g(k),k+1)or~-k

Ideone上进行测试

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.