数字总和斐波那契


30

我们都熟悉斐波那契数列

0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144, 233, 377, 610, 987, 1597, 2584, 4181, 6765

但是,相反,f(n) = f(n-1) + f(n-2)我们将对前2个条目进行数字求和


序列应仍以开头0, 1,之后差异会迅速显现。此列表的索引为0,也可以使用索引为1的状态。

f(0)  = 0
f(1)  = 1
f(2)  = 1   # 0 + 1
f(3)  = 2   # 1 + 1
f(4)  = 3   # 1 + 2
f(5)  = 5   # 2 + 3
f(6)  = 8   # 3 + 5
f(7)  = 13  # 8 + 5
f(8)  = 12  # 8 + 1 + 3
f(9)  = 7   # 1 + 3 + 1 + 2
f(10) = 10  # 1 + 2 + 7
f(11) = 8   # 7 + 1 + 0
f(12) = 9   # 1 + 0 + 8
f(13) = 17  # 8 + 9
f(14) = 17  # 9 + 1 + 7
f(15) = 16  # 1 + 7 + 1 + 7
f(16) = 15  # 1 + 7 + 1 + 6
f(17) = 13  # 1 + 6 + 1 + 5
f(18) = 10  # 1 + 5 + 1 + 3
f(19) = 5   # 1 + 3 + 1 + 0
f(20) = 6   # 1 + 0 + 5
f(21) = 11  # 5 + 6
f(22) = 8   # 6 + 1 + 1
f(23) = 10  # 1 + 1 + 8
f(24) = 9   # 8 + 1 + 0
f(25) = 10  # 1 + 0 + 9
f(26) = 10  # 9 + 1 + 0
f(27) = 2   # 1 + 0 + 1 + 0
(After this point it repeats at the 3rd term, 0-indexed)

注意:在发布挑战之前,我没有注意到重复的发生,在这里我想写另一本新颖的斐波那契挑战是不可能的。


给您的任务一个数字n,输出此序列的第n个数字。

前3位数字:[0,1,1]

24位重复模式: [2,3,5,8,13,12,7,10,8,9,17,17,16,15,13,10,5,6,11,8,10,9,10,10]

提示:您也许可以利用此重复方法来获得好处。


这是,最低字节数是获胜者。


奖励如果您在答案中使用重复,我将奖励利用顺序中重复的最低字节数答案,赏金为100分。该答案应在原始答案之后作为原始答案的一部分提交。看到这篇文章作为我正在谈论的例子:https : //codegolf.stackexchange.com/a/108972/59376

要获得此奖金,您的代码必须在固定时间(O(1))内运行并附带说明。

奖金获胜者:丹尼斯https://codegolf.stackexchange.com/a/108967/59376 <丹尼斯赢得了。

最独特的实现:https : //codegolf.stackexchange.com/a/108970/59376
(也将获得100分,在选择正确答案后最终确定)


2
我们可以使用基于1的索引还是必须基于0?
Business Cat

1
@BusinessCat是的,可以,将其拧紧。
魔术章鱼缸

1
您如何定义利用重复的优势?是否必须对其进行硬编码,或者我只是将其添加%24到“常规”解决方案中?
丹尼斯

1
@Dennis我定义了利用重复的意思是O(1)。如果您的代码确实在利用重复,那么它应该在恒定的时间内运行。
魔术章鱼缸

1
@Dennis从技术上讲,输入上的%24将使其在27次迭代时达到上限;虽然没有意思,但绝对重要。
魔术章鱼缸

Answers:



28

JavaScript(ES6),45个字节

f=(n,x=0,y=1)=>n?f(n-1,y,(x%9||x)+(y%9||y)):x
<input type=number min=0 oninput=o.textContent=f(this.value)><pre id=o>

x并且y不能两者都是9,因为那要求以前的数字是0,所以他们的数字和不能超过17。这意味着大于的数字的数字根9与余数模相同9


6
这样,这也将获得等同于重复领导者的奖励……这是一个很棒的数学见解。
魔术章鱼缸

13

Python 2,53个字节

f=lambda n:n>1and sum(map(int,`f(n-1)`+`f(n-2)`))or n

递归函数。的基的情况下n=0n=1产率n,较大的数字通过调用计算值f(n-1)f(n-2)每个转换为字符串,串联两个串,使用每个字符转换为整数mapint函数,然后求和所得的列表。


使用模24信息,我目前可以获得一个56字节的非递归未命名函数:

lambda n:int(('011'+'2358dc7a89hhgfda56b8a9aa'*n)[n],18)

1
是! +1了!一个重复的答案:)。我在您的荣誉先生中添加了奖金部分,您现在是100分悬赏竞赛的领军人物!
魔术八爪鱼缸

11

JavaScript(ES6),34个字节

f=n=>n<2?n:~-f(--n)%9+~-f(--n)%9+2

可能会冻结浏览器的输入值在27以上,但它确实适用于所有输入值。可以使用简单的缓存进行验证:

c=[];f=n=>n<2?n:c[n]=c[n]||~-f(--n)%9+~-f(--n)%9+2
<input type=number value=0 min=0 step=1 oninput="O.value=f(this.value)"> <input id=O value=0 disabled>

正如尼尔的绝妙答案所指出的那样,输出永远不能超过17,因此任何高于9的输出的数字总和等于n%9。这也适用于9以下的输出;我们也可以通过~-在模数之前减去1 ,然后在1之后再添加1,使它也适用于9 。


我用硬编码可以做到的最好是50个字节:

n=>"0x"+"7880136ba5867ffedb834968"[n%24]-(n<3)*9+2

6

果冻,8字节

;DFS
ç¡1

在线尝试!

怎么运行的

ç¡1   Main link. No arguments. Implicit left argument: 0

  1   Set the right argument to 1.
ç¡    Repeatedly execute the helper link n times – where n is an integer read from
      STDIN – updating the left argument with the return value and the right
      argument with the previous value of the left argument. Yield the last result.


;DFS  Helper link. Arguments: a, b

;     Concatenate; yield [a, b].
 D    Decimal; convert both a and b to their base-10 digit arrays.
  F   Flatten the result.
   S  Compute the sum of the digits.

替代解决方案,19个字节,恒定时间

;DFS
9⁵ç23С⁸ịµṠ>?2

在线尝试!

怎么运行的

9⁵ç23С⁸ịµṠ>?2  Main link. Argument: n

9               Set the return value to 9
 ⁵              Yield 10.
  ç23С         Execute the helper link 23 times, with initial left argument 10
                and initial right argument 9, updating the arguments as before.
                Yield all intermediate results, returning
                [10,10,2,3,5,8,13,12,7,10,8,9,17,17,16,15,13,10,5,6,11,8,10,9].
   ⁸ị           Extract the element at index n. Indexing is 1-based and modular.
     µ          Combine all links to the left into a chain.
       >?2      If n > 2, execute the chain.
      Ṡ         Else, yield the sign if n.

1
+1为“让我们只计算在固定时间内整个重复节”的chuzpe:d
菲利克斯Dombek

4

JavaScript(ES6),52 46 45字节

_=$=>$<2?$:eval([..._(--$)+[_(--$)]].join`+`)

用法

_=$=>$<2?$:eval([..._(--$)+[_(--$)]].join`+`)
_(7)

输出量

13

说明

此函数检查输入是否小于2,如果小于2,则返回输入。否则,它将创建两个值的数组,这些值作为字符串彼此附加。这两个值是使用input - 1和调用函数的结果input - 2

...操作者拆分此字符串变换成字符,然后再次转换成一个字符串数组,但现在具有+值之间ES。然后将此字符串解释为代码,因此计算总和,然后将其返回。

这是一种双递归算法,因此效率很低。它需要2个n-2函数调用才能输入n。因此,这是一个更长但更快的解决方案。感谢ETHproductions提出了它。

f=($,p=1,c=0)=>$?f($-1,c,eval([...p+[c]].join`+`)):c

这不适用于27之类的大值,它会冻结浏览器(至少对我
有用

这需要一些时间,但最终会到达那里。我会仔细研究,但是性能对于这一挑战并不重要...
路加福音

好吧,耶稣,并不是计算量很大,您的程序应该可以处理27以上的值...但是,如果它适用于1-28,则从技术上证明它可以用于更高的值。
魔术八达通Ur

1
@KritixiLithos这是递归的问题。计算序列中的第n个数字大约需要2 ^(n-2)个函数调用,这会迅速建立。
ETHproductions '02

您可以保存一个字节用[..._(--$)+[_(--$)]]:-)
ETHproductions

4

05AB1E,8个字节

XÎF‚¤sSO

在线尝试!

说明

XÎ        # push 1,0,input
  F       # input_no times do:
   ‚      # pair the top 2 elements of the stack
    ¤     # push a copy of the 2nd element to the stack
     s    # swap the pair to the top of the stack
      S   # convert to list of digits
       O  # sum

3

CJam,22个 20字节

感谢Martin Ender,节省了2个字节

ri2,{(_(jAb\jAb+:+}j

简单的递归算法,没什么花哨的。0索引。

在线尝试!测试0-50(实际上运行速度非常快)。

说明

ri                    Read an integer from input
  2,                  Push the array [0 1]
    {             }j  Recursive block, let's call it j(n), using the input as n and [0 1] as base cases
     (                 Decrement (n-1)
      _(               Duplicate and decrement again (n-2)
        jAb            Get the list digits of j(n-2)
           \           Swap the top two elements
            jAb        Get the list of digits of j(n-1)
               +       Concatenate the lists of digits
                :+     Sum the digits

CJam,42个字节

使用重复的解决方案。与乔纳森·艾伦的解决方案相似的算法。

ri_2,1+"[2358DC7A89HHGFDA56B8A9AA]"S*~@*+=

在线尝试!


3

Perl 6的 41  37个字节

{(0,1,{[+] |$^a.comb,|$^b.comb}...*)[$_]}

试试吧

{(0,1,*.comb.sum+*.comb.sum...*)[$_]}

试试吧

{ # bare block lambda with implicit parameter 「$_」
  (

    0, 1,           # first two values

    # WhateverCode lambda with two parameters ( the two 「*」 )
    *.comb.sum      # digital sum of first parameter
    +
    *.comb.sum      # digital sum of second parameter

    ...            # keep using that code object to generate new values until:

    *              # never stop

  )[ $_ ]          # index into the sequence
}

1
您可以将内部lambda编写为*.comb.sum+*.comb.sum
smls

2

MATL,15字节

lOi:"yyhFYAss]&

在线尝试!

lO       % Push 1, then 0. So the next generated terms will be 1, 1, 2,... 
i        % Input n
:"       % Repeat that many times
  yy     %   Duplicate top two elements in the stack
  h      %   Concatenate into length-2 horizontal vector
  FYA    %   Convert to decimal digits. Gives a 2-row matrix
  ss     %   Sum of all matrix entries
]        % End
&        % Specify that next function (display) will take only 1 input
         % Implicit display


2

C,96字节

或61个字节,将转义码各计为1个字节

0索引。与其他一些答案类似,我正在为值的查找表建立索引,但已将其压缩为4个字节的块。我没有去研究mod 24版本,因为我认为它没有那么有趣,因为其他人已经这样做了,但让我们面对现实吧,C还是不会赢。

#define a(n) n<3?!!n:2+(15&"\x1\x36\xba\x58\x67\xff\xed\xb8\x34\x96\x87\x88"[(n-3)/2%12]>>n%2*4)

说明:

#define a(n)                                                                                     // using a preprocessor macro is shorter than defining a function
             n<3?!!n:                                                                            // when n is less than 3 !!n will give the series 0,1,1,1..., otherwise..
                                                                             (n-3)/2%12          // condition the input to correctly index the string...
                           "\x1\x36\xba\x58\x67\xff\xed\xb8\x34\x96\x87\x88"                     // which has the repeating part of the series encoded into 4 bits each number
                                                                                                 // these are encoded 2 less than what we want as all numbers in the series after the third are 2 <= a(n>2) <= 17 which conforms to 0 <= a(n>2) - 2 <= 15
                                                                                        >>n%2*4  // ensure the data is in the lower 4 bits by shifting it down, n%2 will give either 0 or 1, which is then multiplied by 4
                        15&                                                                      // mask those bits off
                     2+                                                                          // finally, add 2 to correct the numbers pulled from the string

在线尝试!


我确实将转义代码算作每个1字节!出色的工作
Albert Renshaw



2

Mathematica,49个字节

If[#<2,#,Tr[Join@@IntegerDigits[#0/@{#-1,#-2}]]]&

简单的递归定义。一段时间后变得很慢。

Mathematica,79 71字节

If[#<3,Sign@#,(9@@LetterNumber@"JJBCEHMLGJHIQQPOMJEFKHJ")[[#~Mod~24]]]&

对周期性模式进行硬编码。快速,令人满意地滥用Mathematica :) 感谢JungHwan Min节省了8个字节!


您的第二个代码LetterNumber@"JJBCEHMLGJHIQQPOMJEFKHJ"比短8个字节43626804920391712116157158790~IntegerDigits~18
JungHwan Min

你是对的!这些日子之一,我会想起LetterNumber....
格雷格·马丁

1

Python 2,56个字节

简单的迭代解决方案。

a,b=0,1
exec'a,b=b,(a%9or a)+(b%9or b);'*input()
print a

在线尝试!

(a%9or a)+(b%9or b)实际使用起来要短于sum(map(int(`a`+`b`)))


我认为您的意思是sum(map(int,a+b))(无法弄清楚如何在评论中使用`)

1

PowerShell,79字节

$b,$c=0,1;for($a=$args[0];$a;$a--){$z=[char[]]"$b$c"-join'+'|iex;$b=$c;$c=$z}$b

在线尝试!

冗长而乏味的迭代解决方案,可以在每个for循环中直接进行数字和计算。在循环的最后,我们想要的数字在中$b,因此留在管道上,输出是隐式的。请注意,如果输入为0,则由于条件为假,因此不会进入循环,因此$b保持0


1

批处理,85字节

@set/ax=0,y=1
@for /l %%i in (1,1,%1)do @set/az=x-x/10*9+y-y/10*9,x=y,y=z
@echo %x%

我想知道如何将我的JavaScript答案移植到批处理中,但是线索来自@Dennis的Python解决方案。



1

Ruby,58个字节

->n{n<3?n<=>0:"9aa2358dc7a89hhgfda56b8a"[n%24].to_i(18)}

简单的硬编码解决方案。



1

八度,148字节

function f = fib(n)
  if (n <= 1)
    f = n;
  else
    f = sum(int2str((fib(n - 1)))-48) + sum(int2str((fib(n - 2)))-48);
  endif
endfunction

欢迎来到ppcg!不错的第一篇文章!
Rɪᴋᴇʀ

1

Haskell,151个字节

import Numeric
import Data.Char
s i=foldr(\c i->i+digitToInt c)0$showInt i""
d a b=a:d b(s a+s b)
f 0=0
f 1=1
f 2=1
f i=d 2 3!!fromIntegral(mod(i-3)24)

f 123456789012345678901234567890123456789012345678例如,使用调用功能。

该代码还适用于非常大的索引。由于实现了模24功能,因此速度非常快。

未压缩的代码:

-- FibonacciDigital
-- Gerhard
-- 13 February 2017

module FibonacciDigital () where

import Numeric
import Data.Char

-- sum of digits
digitSum :: Int -> Int 
digitSum i = foldr (\c i -> i + digitToInt c) 0 $ showInt i ""

-- fibonacci digital sequence function with arbitrary starting values
fibonacciDigitals :: Int -> Int -> [Int]
fibonacciDigitals a b = a : fibonacciDigitals b (digitSum a + digitSum b)

-- index -> fibonacci digital value
f :: Integer -> Int 
f 0 = 0 
f 1 = 1 
f 2 = 1 
f i = fibonacciDigitals 2 3 !! fromIntegral (mod (i-3) 24) 

-- End

0

R,90个字节

一个非常长的解决方案,但是比我最初的108更好。我怀疑有更好的方法来执行此操作,但目前无法看到它。

function(n,x=0:1){repeat`if`(n,{x=c(x,sum(scan(t=gsub('',' ',x))))[-1];n=n-1},break);x[1]}

这是一个未命名的函数,该函数使用gsub并将scan(t=向量中的数字拆分为数字。将这些总和添加到向量中,而删除第一项。 repeat用于逐步计算序列n时间,结果是向量的第一项。



0

Mathematica,67个字节

r=IntegerDigits;f@0=0;f@1=1;f[x_]:=f@x=Tr@r@f[x-1]+Tr@r@f[x-2];f@#&
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.