这个数字是秘密斐波那契吗?


23

背景

你们大多数人都知道斐波那契数是什么。根据Zeckendorf定理,有些人可能知道所有正整数都可以表示为一个或多个不同的斐波那契数之和。如果整数的最佳Zeckendorf表示形式中的项数n本身是斐波那契数,我们将其称为n“秘密”斐波那契数。

例如:

139 = 89 + 34 + 13 + 3
This is a total of 4 integers. Since 4 is not a Fibonacci number, 139 is not secretly Fibonacci

140 = 89 + 34 + 13 + 3 + 1
This is a total of 5 integers. Since 5 is a Fibonacci number, 140 is secretly Fibonacci

笔记

  • 可以使用贪心算法找到最佳的Zeckendorf表示形式。只需取最大的斐波那契数<= n并从n中减去它,直到达到0
  • 所有斐波那契数字都可以表示为1个斐波那契数字的总和(本身)。由于1是斐波那契数,因此所有斐波那契数也都秘密地称为斐波那契。

挑战

您面临的挑战是编写一个接受整数的程序或函数,并返回该整数是否为秘密斐波那契。

输入项

您可以采用任何合理的格式输入。您可以假设输入将是单个正整数。

输出量

输出两个不同结果之一,以确定输入是否为秘密斐波那契。示例包括True/ False1/ 0等。

计分

这是,因此最短答案以字节为单位!禁止出现标准漏洞。

测试用例

Truthy (secretly Fibonacci)
1
2
4
50
140
300099

Falsey (NOT secretly Fibonacci)
33
53
54
139
118808

6
这是否意味着他们好奇?
凯文

2
万一它对任何人都有用:最佳和是唯一的解决方案,它不使用两个连续的斐波那契数。
卡巴斯德'18

2
@kasperd您是正确的,如果您考虑一下,这是有道理的。如果解决方案具有两个连续的斐波那契数,则可以将它们加在一起以形成下一个。如果您的解决方案包含5和8,那将比拥有一个13更不理想
。– Cowabunghole

@Cowabunghole这是直觉。完整的证明要复杂得多。如果解决方案已经包含5、8和13,则将添加8 + 13而不是5 + 8。并且另一个方向也需要证明。
卡巴斯德(Kasperd),

Answers:



8

Python 2,77个字节

def f(n):z=[bin(x).count('1')for x in range(n*n+1)if x&2*x<1];print z[z[n]]<2

在线尝试!

这利用了定理,即OEIS A003714的两个描述是等效的:

斐波那契数:如果ñ=F一世1个+F一世2++F一世ķñ的Zeckendorf表示(即在斐波那契数系统中写ñ),则一种ñ=2一世1个+2一世2++2一世ķ也是二进制表示不包含两个相邻1个的。

我们生成足够的*这样的数字,然后将其z用作从非负整数到“ n的Zeckendorf表示中有多少项的映射”。ñ通过在二进制数中计算1。

然后剩下来检查是否z[n]是斐波那契数,即z[z[n]] == 1

*至少,ñ2+1个 感觉像足了,并在实验上似乎是不够的。稍后再证明。


您可以通过删除周围的反引号来削减两个字节bin(x)。您也可以通过更改range(n*n+1)为来删除一个range(n<<n)。(假设0无效)
nedla2004 '18 -10-30

我不知道我对周围的倒影在想什么bin(x),哈哈。而且,hm 1<<n已经足够了,但是我想让运行时保持非天文数字
Lynn

公平地说,我想能够运行代码可能是一个重要属性。:)
nedla2004 '18

6

果冻,15 字节

‘ÆḞ€fRṪạµƬL’Ɗ⁺Ị

接受非负整数的单子链接,1如果产生“ Secretly Fibonacci”,0否则产生。

在线尝试! (对于较大的测试用例而言效率太低)

怎么样?

‘ÆḞ€fRṪạµƬL’Ɗ⁺Ị - Link: integer, I
        µƬ      - perform the monadic link to the left as a function of the current I,
                - collecting up all the inputs until the results are no longer unique:
‘               -   increment I -> I+1
 ÆḞ€            -   nth Fibonacci number for €ach n in [1,I+1]
     R          -   range from 1 to I
    f           -   filter discard (discard Fibonacci numbers not in the range, i.e. > I)
      Ṫ         -   tail (get the largest)
       ạ        -   absolute difference with I
                - This gives us a list from I decreasing by Fibonacci numbers to 0
                - e.g. for 88 we get [88,33,12,4,1,0]
                -      because (88-33)+(33-12)+(12-4)+(4-1)+(1-0)=55+21+8+3+1=88 
          L     - length (the number of Fibonacci numbers required plus one)
           ’    - decrement (the number of Fibonacci numbers required)
            Ɗ   - treat the last three links (which is everything to the left) as a monad:
             ⁺  - ...and repeat it
                - i.e. get the number of Fibonacci numbers required for the number of
                -      Fibonacci numbers required to represent I.
                -      This is 1 if I is Secretly Fibonacci, and greater if not)
              Ị - insignificant? (is the absolute value of that <= 1?)


5

C#(.NET核心)124 115 98个字节

a=>{int n=0,b,c;for(;a>0;a-=b,n++)for(b=c=1;c<=a;b=c-b)c+=b;for(b=c=1;c<n;c+=b)b=c-b;return c==n;}

在线尝试!

-3个字节:在for循环时更改(感谢OlivierGrégoire
-6个字节:切换回使用变量,并在循环外初始化b和c(感谢Kevin Cruijssen
-17个字节:在第二个循环中更改条件以移动循环外并与返回结合,在最后一个循环中重用了b和c变量(感谢raznagul

取消高尔夫:

a => {
    int n = 0, b, c;                        // initialize variables

    for(; a > 0; a -= b, n++)               // increase n until a is 0
        for(b = c = 1; c <= a; b = c - b)   // set b and c to 1 for each a; set second largest Fibonacci number until largest Fibonacci number reaches a
            c += b;                         // set largest Fibonacci number of current sequence

    for(b = c = 1; c < n; c += b)           // while e is less than or equal to n, continue incrementing largest (e) Fibonacci number in the sequence
        b = c - b;                          // increment second-largest (d) Fibonacci number

    return c == n;                          // if c equals n, a is a secret Fibonacci number
}

1
for(;c<=a;b=c-b)c+=b;将为您节省3个字节。
奥利维尔·格雷戈尔

1
115个字节。我删除了{}循环的所有for括号,并将所有内容放入循环。另外,我添加了一个变量r,该变量设置为1您的变量,if(e==n)最后返回,因此您只有一个return
凯文·克鲁伊森

双方都很好。我曾尝试将while循环更改为for,但以某种方式错过了执行此操作的简单方法。拥有一个单独的返回变量绝对更好。
猫鼬

1
通过在第二循环中不断变化的条件e<n,你可以移动if到循环后consequentlly与它结合return101个字节
raznagul

1
您可以通过重复使用bc在最后一个循环中删除d和来节省另外3个字节e
raznagul

4

Perl 6、58字节

{(1,&[+]...*>$_)∋($_,{$^n-(1,&[+]...^*>$n).tail}...0)-1}

在线尝试!

1, &[+] ... * > $_ 只是斐波那契数列,停在方便的非无限位置(输入数字)。

$_, { $^n - (1, &[+] ...^ * > $n).tail } ... 0是一个数字序列,从输入数字开始,每个后续元素都是通过从前一个元素中减去小于或等于前一个元素的最大斐波那契数而获得的。0到达时序列终止。例如,如果$_140,则此序列为140, 51, 17, 4, 1, 0

从该序列中减去一个就将其视为一个数字,即其长度,而差是斐波纳契数的数量,这些数字加在一起便得出输入数。然后检查该数字是否符合第一个斐波那契数列。


我以前没看过这个把戏&[+]!很好,不必定义两个初始术语
乔·金

1
通过将斐波那契数列分配给一个函数和其他一些更改来获得51个字节
Jo King

l4m2的JavaScript响应端口,50个字节
nwellnhof,

@nwellnhof哈,除了几乎没有区别
Jo King

3

Perl 6,48个字节

{4>($_,{$_,{$_-(1,&[+]...*>$_)[*-2]}...^0}...1)}

在线尝试!

重复将输入转换为Zeckendorf表示形式的列表,直到达到单个数字,然后检查序列的长度是否小于4。

中间的Zenckendorf函数主要来自Sean的答案,并进行了一些改进。

说明:

{4>($_,{$_,{$_-(1,&[+]...*>$_)[*-2]}...^0}...1)}
{                                              } # Anonymous code block
                                          ...     # Define a sequence:
    $_  # That starts at the input
      ,{                                 }  # Each element is defined by:
                                   ... # Another sequence that:
        $_,   # Starts at the previous element
            $_-   # The previous element minus
                1,&[+]...*     # The Fibonacci sequence
                          >$_  # Ending when it is larger than the previous element
               (             )[*-2]  # The second from last element
          {                        }...^0  # Run until 0, discarding the last element
         # This returns the length of the Zeckendorf Representation
                                         ...1  # Run this until it is length 1
 4>(                                         )  # Return true if the length of the sequence is smaller than 4

例如,对于该序列2就是2 1因为2已经是一个Fibonacci数。的顺序140140 5 1,并且由于5是斐波那契数,因此返回true。用于序列3333 4 2 1,由于4不是Fibonacci数序列是长度为4的。


3

05AB1E,14 个字节

ΔDÅFθ-¼}¾ÅF¾<å

在线尝试。没有针对所有测试用例的测试套件,因为counter_variable不能将其重置为0。尽管我手动验证了所有内容,但它们都是正确的。

说明:

Δ      }          # Loop until the top of the stack no longer changes
 D                #  Duplicate the top of the stack
                  #  (implicitly the input in the first iteration)
  ÅF              #  Get a list of all Fibonacci numbers lower than this number
    θ             #  Get the last item (largest one)
     -            #  Subtract it from the number
      ¼           #  Increase the counter_variable by 1 every iteration
        ¾         # After the loop, push the counter_variable
         ÅF       # Get all Fibonacci numbers below this counter_variable
           ¾<     # Push the counter_variable again, and subtract 1
             å    # Check if this value is in the list of Fibonacci numbers
                  # (and output implicitly)

注意:该命令counter_variable5用于input 1396input 140,因为为了使Δ-loop检查堆栈保持不变,它当然会进行额外的迭代。



2

视网膜0.8.2,61字节

.+
$*
M`((?>\2?)(\1|\G.))*..|.
.+
$*
^(((?>\3?)(\2|^.))*.)?.$

在线尝试!链接包括测试用例。说明:

.+
$*

转换为一元。

M`((?>\2?)(\1|\G.))*..|.

计算所需的斐波那契数。

第一个替换处理的斐波那契数至少为2。在第一次通过时,\2尚不存在,但幸运的是它是可选的,因此我们不必匹配它。\1也不存在,但幸运的是,我们可以选择在\G.比赛开始时匹配单个字符。两者\2\1因此采取对值1。

在后续通过中,\2存在,因此我们尝试对其进行匹配。这次如果失败了,那么\1也会失败(因为它大于\2),但是如果成功了,则(?>)可以防止回溯,因此如果\2匹配但\1不匹配,我们就不要尝试\1。(\G1因为我们已经超过了补丁程序的开头,所以总是会失败。)最后,\2它采用\1while 的前一个值,而while \1是两个值之和。

因此,我们将尽可能多地匹配斐波纳契数,并不断添加。由于该序列的部分和1, 2, 3, 5...0, 1, 3, 6, 11...即2小于我们在最后完成由匹配2所述斐波那契数。

显然,这本身无法匹配1,因此交替处理该情况。

.+
$*

转换为一元。

^(((?>\3?)(\2|^.))*.)?.$

测试这是否是斐波那契数。这使用与第一个测试相同的想法,但是使用^代替\G而且我们还需要精确匹配,因此它使用可选的捕获方式,而不是交替的方式,因为这更容易打高尔夫(但捕获次数会增加1)。

视网膜,35字节

.+
*
2}C`((?>\2?)(\1|\G.))*..|.
^1$

在线尝试!链接包括测试用例。说明:

.+
*

转换为一元。

C`((?>\2?)(\1|\G.))*..|.

计算所需的斐波那契数。(首先将转换和计数都循环一遍,这样就节省了一个完整的字节。)

2}

总共执行两次上述步骤。这需要将斐波纳契数的总和与斐波那契数的总和相加。

^1$

如果该数字是秘密斐波那契,则结果为1。


1

Python 2中146个 137字节

lambda a:len(g(len(g(a))))<2
f=lambda n:n<3or f(n-2)+f(n-1)
def g(a,n=1):j=f(n-1);return[j]if a-j<1else[j]+g(a-j)if a-f(n)<0else g(a,n+1)

在线尝试!

f()是一个递归函数,它返回第n个斐波那契数的值。取自这个答案

g()是一个递归函数,它以整数列表形式返回给定数字的Zeckendorf表示形式。

由于所有斐波那契数都将具有从g()返回的一项长度,因此h()检查g(n)的g()的长度是否== 1。

编辑:感谢nedla2004保存了9个字节。我一直忘记lambda并不总是最好的解决方案...


1
138个字节。我主要只是做g一个函数,以便可以定义f(n-1)一个变量。将其他更改从耦合==<相同的位置。
nedla2004 '18
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.