斐波那契反转!


42

介绍

我们都知道并喜欢我们的斐波那契数列,并且已经在这里看到了无数挑战。但是,我们仍然缺少一个非常简单的案例,该答案将提供:反斐波那契!因此,鉴于F_n您的工作就是寻找n

规格

输入项

您的输入将是一个非负整数,保证是斐波那契数列的一部分。

输出量

输出也必须是非负整数。

该怎么办?

引言已经说过:给定斐波那契数,输出其索引。斐波那契编号在此定义为F(0)=0, F(1)=1, F(n)=F(n-1)+F(n-2),您将获得F(n)且必须返回n

潜在的极端案例

0是有效的输入和输出。
如果给定“ 1”作为输入,则可以根据需要输出“ 1”或“ 2”。
您可能总是假设您的输入实际上是斐波那契数。
您可以假定输入可表示为32位带符号整数。

谁赢?

这是代码高尔夫球,因此最短的答案以字节为单位!
标准规则当然适用。

测试用例

0 -> 0
2 -> 3
3 -> 4
5 -> 5
8 -> 6
13 -> 7
1836311903 -> 46

39
轻微的挑剔:不应该将其视为斐波
Michael

19
那么,iccanobiF?

6
@Michael这不是斐波纳契函数的反函数,因为斐波那契函数没有反函数,因为它不是单射的(因为“ 1”出现两次)。反向最初来自“反向表查找”的想法,这是我希望人们在这里所做的事情(例如,我希望他们这样做是为了解决问题)。
SEJPM

9
从非负整数到斐波那契数集,此处的函数可以视为“斐波那契函数” 的右逆。右逆的存在并不意味着单射性。
丹尼斯

1
@SEJPM:不过,我确实期望完成一个任务,例如“编写一个向后拼写斐波那契序列的程序”。
Bergi '16

Answers:


58

实际上是1个字节

f

是的,自2015年11月16日起,有一个内置函数。

在线尝试


有趣的是,没有内置字节,它是9个字节:

╗1`F╜=`╓i

在线尝试!

说明:

╗1`F╜=`╓i
╗          push input to register 0
 1`F╜=`╓   push list containing first value x (starting with x = 0) where:
   F         fib(x)
    ╜=       is equal to the input
        i  flatten the list

15
我有一个思想,一个是只想,当我看到这一点:ಠ_ಠ
艾迪克伦普

37
我真的不明白为什么您会为了如此荒谬的特定目的而“浪费”一个符号
致命一击

19
@Fatalize Fibonacci和反Fibonacci函数是我添加的第一个函数。即使到现在,仍然有39个完全未使用的单字节命令(谁知道可以利用多少个重载)。256个符号,加上实际上有5种类型(整数,实数,字符串,可迭代,函数)的事实,意味着最多有1280个可能的一元函数和6400个可能的二进制函数。对于看似无用的命令,还有很多空间。
Mego

23
@Mego您是否只是想与Mathematica竞争最强大的功能?
gcampbell '16

13
实际上,它只是一个字节……大声笑,喜欢这个语言名称。
nicael


31

Python,36 34 32字节

lambda n:len(str(66*n**6))//1.24

之前的版本:

f=lambda n:len(str(66*n**6))//1.24
f=lambda n:(n*n*7).bit_length()//1.4

说明

核心思想是颠倒公式

fibonacci(n) ~ ( (1 + sqrt(5)) / 2)**n / sqrt(5)

告诉我们

log fibonacci(n) ~ n log((1 + sqrt(5)) / 2) - log(sqrt(5))

要得到

f(n) ~ (log(n) + log(sqrt(5))) / log((1 + sqrt(5))/2)

高尔夫优化是:

  • 用于len(str(n))在不导入的情况下计算日志库10 log(用于.bit_length()计算日志库2的旧版本)
  • 提高n到幂,以便对数的近似值可以区分连续的斐波那契数
  • 乘以一个常数会放大这些值,以使它们在正确的范围内

然后,除数被舍弃到我所能控制的最小精度,并且选择乘数来为所有32位斐波纳契数提供正确的结果。


它应该是32个字节,因为f=不计算在内。
Leaky Nun

2
如上面的评论所述,默认情况下允许使用匿名函数/未命名的lambda。另外,如果您将答案限制在Python 2上并且需要一个参数,则lambda n:~-len(`66*n**6`)//1.24应该可以。
丹尼斯


10

果冻,14 11个字节

5½×lØp+.Ḟ»0

在线尝试!

这是我第一个果冻答案!这使用了来自MATL答案的算法。感谢Dennis削减了3个字节!

说明:

   lØp      # Log Base phi
5½          # Of the square root of 5
  ×         # Times the input
      +     # Plus
       .    # 0.5
        Ḟ   # Floored

这得到了正确的答案,现在我们只需要处理特殊情况'0'。以'0'作为arg,我们得到-infinity,所以我们返回

»      # The maximum of 
 0     # Zero
       # And the previous calculated value.

7
+1是因为对说明的评论是打油诗的结尾。
丹尼尔(Daniel)

10

朱莉娅27 26 18字节

!n=log(3n+.7)÷.48

它使用Binet公式的反函数,其精度足以满足32位整数的要求;它实际上可以达到F(153)= 42,230,279,526,998,466,217,810,220,532,898> 2 105

在线尝试!

这个怎么运作

Binet的公式规定如下。

比内公式

限制˚F到设定斐波纳契,地图的Ñ→˚F Ñ具有逆右 ˚F→Ñ ˚F

我们有

Binet公式的右逆

而剩下要做的就是处理边缘情况0

由于输入限制为32位整数,因此我们可以使用短十进制文字代替公式中的常量。

  • logφ= 0.481211825059603447…≈0.48

    不幸的是,0.5不够精确。

  • √5= 2.2360679774997896964…≈3

    乍一看,这似乎是一个可怕的近似值,但是我们采用对数,因为log 3-log√5= 0.29389333245105…,所以四舍五入前的结果将有一个小的常数因子。

  • 0.5≈0.7

    由于前一个近似值有余,因此我们实际上可以完全省略此项,并且对于F> 0仍然可以获得正确的结果。但是,如果F = 0,对数将是不确定的。0.7是使公式扩展为F = 0的最短值。


8

JavaScript,54 50 69 50 42字节

b=>(j=>{for(i=c=0;b-i;c++)i=j+(j=i)})(1)|c

当然,它不会赢,只是为了好玩:)

确定,检查零消耗19个字节。WTF?愚蠢的我。


演示!要查看最后一个测试用例,您必须稍微滚动控制台。

a=b=>(j=>{for(i=c=0;b-i;c++)i=j+(j=i)})(1)|c;
console.log('0: '+a(0));
console.log('2: '+a(2));
console.log('3: '+a(3));
console.log('5: '+a(5));
console.log('8: '+a(8));
console.log('13: '+a(13));
console.log('1836311903: '+a(1836311903));

感谢@edc缩短了8个字节。


简单b=>{for(j=1,i=c=0;b-i;c++)i=j+(j=i);return c}45,golfed b=>(j=>{for(i=c=0;b-i;c++)i=j+(j=i)})(1)|c42
edc65

1
@edc哇,这很聪明,谢谢<3
nicael '16

8

Perl 6  33 30  27字节

{first *==$_,:k,(0,1,*+*...*>$_)}
{first *==$_,:k,(0,1,*+*...*)}
{first $_,:k,(0,1,*+*...*)}

试试吧

说明:

# lambda with implicit 「$_」 parameter
{
  first           # find the first element
    $_,           # where something is equal to the block's argument
    :k,           # return the key rather than the value

    # of the Fibonacci sequence
    ( 0, 1, * + * ... * )
    # ^--^ first two values
    #       ^---^ lambda used to generate the next in the series
    #             ^-^ generate until
    #                 ^ Whatever
}

测试:

#! /usr/bin/env perl6
use v6.c;
use Test;

# using the safer version that stops generating
# values bigger than the input
my &fib-index = {first $_,:k,(0,1,*+*...*>$_)}

my @tests = (
  0 => 0,
  2 => 3,
  3 => 4,
  5 => 5,
  8 => 6,
  13 => 7,
  1836311903 => 46,
  1836311904 => Nil, # this is why the safe version is used here
  12200160415121876738 => 93,
  19740274219868223167 => 94,
  354224848179261915075 => 100,
);

plan +@tests + 1;

for @tests -> $_ ( :key($input), :value($expected) ) {
  cmp-ok fib-index($input), &[eqv], $expected, .gist
}

cmp-ok fib-index((0,1,*+*...*)[1000]), &[eqv], 1000, 'works up to 1000th element of Fibonacci sequence'
1..13
ok 1 - 0 => 0
ok 2 - 2 => 3
ok 3 - 3 => 4
ok 4 - 5 => 5
ok 5 - 8 => 6
ok 6 - 13 => 7
ok 7 - 1836311903 => 46
ok 8 - 1836311904 => Nil
ok 9 - 12200160415121876738 => 93
ok 10 - 19740274219868223167 => 94
ok 11 - 354224848179261915075 => 100
ok 12 - works up to 1000th element of Fibonacci sequence

1
您可以first *==$_用just 代替first $_,因为数字是有效的智能匹配器。
smls

使用...运算符而不是first
Jo King

7

果冻,8 字节

1+С0
¢i

在线尝试!请注意,对于最后一个测试用例,这种方法效率太低。

这个怎么运作

¢i     Main link. Argument: n

¢      Call the helper link niladically (i.e., without arguments).
       This yields the sequence of the first n positive Fibonacci numbers, i.e.,
       [1, 1, 2, 3, 5, ...].
 i     Find the first index of n (1-based, 0 if not found).


1+С0  Helper link. No arguments.

1      Set the left argument to 1.
    0  Yield 0.
 +С   Add both arguments, replacing the left argument with the sum and the right
       argument with the previous value of the left argument.
       Yield the array of all intermediate values of the left argument.


5

Python,29个字节

g=lambda n:n>.7and-~g(n/1.61)

将输入除以黄金分割率近似值1.61,直到其低于0.7,然后输出除法数。

对于0,代码输出False在Python中等于0。可以避免2个字节

g=lambda n:n//.7and 1+g(n/1.61)

4

JavaScript(ES6),39 33字节

f=(n,j=0,k=1)=>n>j?f(n,k,j+k)+1:0

即使使用ES7,反向Binet公式也占用47个字节:

x=>Math.log(x*5**.5)/Math.log(.5+1.25**.5)+.5|0
x=>Math.log(x*5**.5)/Math.log((1+5**.5)/2)+.5|0
x=>Math.log(x*(p=5**.5))/Math.log((1+p)/2)+.5|0

只需分配log并预先计算所有常量...
查理

恕我直言,如果您按名称递归调用lambda f(n,k,j+k),则应包括分配f=并将其计为+2个字节。未命名的lambda规则不适用于此处。
查理

@charlie对不起,我总是忘记了这一点。固定。
尼尔

4

Sage,49个字节

lambda x,s=sqrt(5):x and int(log(x*s,(1+s)/2)+.5)

由于TuukkaX关于节约的建议sqrt(5)作为s剃掉几个字节。

在线尝试

这种与Binet公式相反的方法比以前的方法有一些改进:更快(恒定时间与二次时间),实际上适用于较大的输入,并且更短!

Python用户可能想知道为什么要使用我的sqrt(5)而不是简称的5**.5-这是因为它5**.5是使用C pow函数计算的,并且由于浮点问题而失去了精度。Sage中重载了许多数学函数(包括sqrtlog),以返回精确的符号值,而这不会失去精度。


我完全不了解Sage,但是您可以通过将sqrt(5)in 保留在变量中并使用两次而不是键入sqrt(5)两次来保存字节吗?
Yttsi '16

4

MATL,14个字节

t?5X^*17L&YlYo

在线尝试!

这使用了Binet公式的逆,因此非常快。

F表示第n个斐波那契数,而φ表示黄金分割率。然后

在此处输入图片说明

该代码对此公式进行了两个修改:

  • 该代码没有加1/2而是四舍五入,而是简单地四舍五入为最接近的整数,该整数占用更少的字节。
  • 输入F = 0需要作为特殊情况处理。

怎么做

t         % Take input F implicitly. Make a copy
?         % If (copy of) F is positive
  5X^     %   Push sqrt(5)
  *       %   Multiply by F
  17L     %   Push phi (predefined literal)
  &Yl     %   Two-input logarithm: first input is argument, second is base
  Yo      %   Round towards nearest integer
          % Else the input, which is 0, is left on the stack
          % End if implicitly
          % Display implicitly

1
替代方法:O1G:"yy+]vGmfq
DJMcMayhem

1
11个字节:t?17L&YlXkQ
jimmy23013

@ jimmy23013不错的方法!您应该明确地将其发布为一个单独的答案
Luis Mendo

我认为这不值得另一个答案,因为这只是删除的一种方法5X^*。(我之前已经做过。)而且我对MATL的了解还不足以继续改进它。
jimmy23013


3

JavaScript,22个字节

n=>Math.log(n)/.48+2|0

当我看到它时,我认为这不会起作用,但显然-Infinity|00在JavaScript中。去搞清楚。
丹尼斯

@Dennis:在JS中,按位运算符仅占用最后32位和-Infinity = FFF00000 00000000。我很高兴发现它,因为不必像那样预先设置一个明确的零测试,所以节省了3个字节n&&。除此之外,的主要目的|0是替代它Math.trunc()(例如÷Julia)。
查理

3

C,62 58字节

g(c,a,b){return c-a?g(c,b,a+b)+1:0;}f(c){return g(c,0,1);}

详细

int g(int c, int a, int b)
{
    if (c == a)
    {
        return 0;
    }
    else
    {
        return g(c, b, a+b) + 1;
    }
}

int f(c)
{
    return g(c, 0, 1);
}

3

Java 7,70个字节

int c(int n){int a=0,b=1,c=0,t;while(a<n){c++;t=b;b+=a;a=t;}return c;}

https://ideone.com/I4rUC5


2
欢迎使用PPCG,不错的第一答案!
Leaky Nun

int c(int n){int a=0,b=1,c=0,t;for(;a<n;t=b,b+=a,a=t)c++;return c;}(未经测试)
Leaky Nun

int c(int n){int a=0,b=1,c=0;while(a<n){c++;b+=a;a=b-a;}return c;}(未经测试)
Leaky Nun

2
int c(int n){int a=0,b=1,c=0;for(;a<n;b+=a,a=b-a)c++;return c;}(未测试)
Leaky Nun

2

TSQL,143字节

输入进去@n,如DECLARE @n INT = 1836311903;

DECLARE @O BIGINT=0;WITH F(R,P,N)AS(SELECT @O,@O,@O+1 UNION ALL SELECT R+1,N,P+N FROM F WHERE N<=@n)SELECT MAX(R)FROM F OPTION(MAXRECURSION 0);

2

Haskell,45个字节

f x=round$log(sqrt 5*x+0.9)/log((sqrt 5+1)/2)

2

Sesos,28个字节

十六进制转储:

0000000: 16f8be 766ef7 ae6d80 f90bde b563f0 7ded18 3ceffa  ...vn..m.....c.}..<..
0000015: b1c1bb af9f3f ff                                  .....?.

在线尝试!

(指数时间,因为在Sesos中复制数字需要指数时间。)

用于生成二进制文件的程序集:

set numin
set numout
get
jmp
sub 1
fwd 1
add 1
fwd 1
add 1
rwd 2
jnz    ;input input
fwd 4
add 1  ;input input 0 1
fwd 2
add 1  ;input input 0 1 0 1
rwd 4
jmp
jmp    ;input input-curr curr next iterations
sub 1
jnz    ;input 0 curr next iterations
fwd 3
add 1
jmp
sub 1
fwd 2
add 1
rwd 2
jnz    ;input 0 curr next 0 0 iterations+1
rwd 1
jmp
sub 1
fwd 1
add 1
fwd 1
add 1
rwd 2
jnz    ;input 0 curr 0 next next iterations+1
rwd 1
jmp
sub 1
fwd 1
sub 1
fwd 2
add 1
rwd 3
jnz    ;input 0 0 -curr next curr+next iterations+1
rwd 2
jmp
sub 1
fwd 2
add 1
fwd 1
add 1
rwd 3
jnz    ;0 0 input input-curr next curr+next iterations+1
fwd 3
jnz
fwd 3
put

2

Java 8 61字节

与@dainichi答案相同,只是使用Java 8 lambda使其更短。答案是有效的右值表达式。

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

取消高尔夫:

interface F
{
    int c(int n);
}

public class Main
{

    public static void main(String[] args)
    {
        F f = n->{int a=0,b=1,c=0,t;while(a<n){c++;t=b;b+=a;a=t;}return c;};
    }
}

1

Pyth,13个字节

J1tf>=Z+~JZZQ

测试套件。

Python 2中的近似值:

Z=0;J=1;T=1;Q=input()
while not J+Z>Q:
    temp=J
    J=Z
    Z=temp+J
    T += 1
print(T-1)

替代方法,18字节

L?<b2bsyMtBtbs.IyG

测试套件。

.I用于逆。


1

Java 7,89个字节

int c(int n){int i=-1;while(f(++i)<n);return i;}int f(int n){return n<2?n:f(n-1)+f(n-2);}

受到@Adnan 05AB1E答案的解释的启发。

非高尔夫球和测试用例:

在这里尝试。(超过了最后一个测试用例的时间限制,但是在我的PC上大约需要30-45秒。)

class Main{
  static int c(int n){
    int i = -1;
    while(f(++i) < n);
    return i;
  }

  static int f(int n){
    return n < 2
             ? n
             : f(n - 1) + f(n - 2);
  }

  public static void main(String[] a){
    System.out.println(c(0));
    System.out.println(c(2));
    System.out.println(c(3));
    System.out.println(c(5));
    System.out.println(c(8));
    System.out.println(c(1836311903));
  }
}

输出:

0
3
4
5
6
46


1

J,32 27 17字节

i.~0,+/@(!|.)\@i.

计算前n个斐波那契数,然后在该列表中找到n的索引。

用法

额外的命令用于格式化多个输入/输出。省略了最后一个测试用例,因为它将需要更多的时间来进行计算。

   f =: i.~0,+/@(!|.)\@i.
   (,.f"0) 0 1 2 3 5 8 13
 0 0
 1 1
 2 3
 3 4
 5 5
 8 6
13 7

说明

i.~0,+/@(!|.)\@i.  Input: n
               i.  Get the range [0, 1, ..., n-1]
             \@    For each prefix of that range
          |.         Reverse the prefix
         !           Find the binomial coefficient between each value in the original
                     prefix and the reversed prefix
     +/@             Sum those binomial coefficients
                   This will create the Fibonacci numbers from 1 to n
   0,              Prepend a 0 to the list of Fibonacci numbers
i.~                Find the index of n in that list and return

1

Mathematica,30个字节

Round@Log[5^.5/2+.5,.8+5^.5#]&

纯功能;如果输入为1,则返回2。

没有击败其他Mathematica条目,但展示了一种不寻常的方法:一个(非常酷的事实)第N个斐波那契数是最接近的整数,它是[1 / sqrt(5)乘以黄金分割率的N次方]( Binet的公式”)。

因此,反函数将是[sqrt(5)乘以所讨论的斐波那契数]的基数[黄金比例]对数。这.8+是确保我们不采用对数0而不破坏其他值的技巧。


1

Japt,10字节

Lo æ@U¥MgX

在线尝试!

说明

Lo æ@U¥MgX
Lo           // Creates a range from 0 to 99
   æ@        // Iterates through the range. Returns the first item X where:
     U¥      //   Input ==
       MgX   //   Xth Fibonacci number

1

Brachylog,14个字节

≜∧0;1⟨t≡+⟩ⁱ↖?h

在线尝试!

通过输出变量获取输入,并通过输入变量输出。

≜                 Label the input variable, trying 0, 1, -1, 2...,
  0               then starting with 0
 ∧                (which is not necessarily the input variable)
   ;1             paired with 1,
     ⟨t≡ ⟩        replace the first element of the pair with the last element
     ⟨ ≡+⟩        and the last element of the pair with the sum of the elements
          ⁱ↖?     a number of times equal to the input variable,
             h    such that the first element of the pair is the output variable.

我不确定为什么要这么做


0

Javascript(使用外部库)(84字节)

n=>_.Until((i,a)=>{l=a.length;if(a[l-1]!=n){return i<=1?i:a[l-1]+a[l-2]}}).Count()-1

链接到lib:https : //github.com/mvegh1/Enumerable

代码说明:库具有静态方法,该方法创建序列直到谓词具有未定义的返回值。该谓词具有签名(“ i” ndex,当前内部生成的“ a” ray)。在每次迭代中,我们检查内部数组的最后一个元素是否等于输入n。如果不是,则返回fib序列中的下一个值。否则,谓词具有不确定的结果,从而终止序列的生成。然后,我们返回序列的长度(并减去1以符合OP中看到的0为基数)

在此处输入图片说明


通过使用此处的 代码获得53个字节n=>{a=c=t=0,b=1;while(a<n){c++;t=b;b+=a;a=t}return c} 在线尝试!
pixma140
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.