重复的斐波那契数字是什么?


30

您可能知道,斐波那契数是一个,它是该序列中前两个数的和。

斐波那契Digit™是前两个数字的总和。

例如,对于系列开始1,1,该系列将是1,1,2,3,5,8,13,4,7,11,2...。更改发生在之后,您可以13在其中添加而不是8+13添加1+3。系列在末尾循环,其中4+7=11和和1+1=2系列开始相同。

再例如,系列开始于2,22,2,4,6,10,1,1,2,3,5,8,13,4,7,11,2,3...。这个开始是唯一的,但是一旦数字总和到10,您最终得到1+0=1, 0+1=1,然后该系列继续进行-并循环-与该1,1系列相同。


挑战

给定一个整数输入0≤n≤99,请从这两个数字开始计算斐波那契数字系列中的循环。(当然可以允许您考虑超出此范围的整数,但这不是必需的。)如果输入的是一位数字,则您的代码应将其解释为表示序列的开头0,n

循环中所有两位数字都必须输出为两位数字。因此,例如,for的循环1,1将包含13,而不是1,3

输出从循环中的第一个数字开始。因此,基于上述限制,for的循环以1,1开头2,因为1,111分别计数。

只要是一致的,输出的每个数字都可以用您想要的分隔。在我所有的示例中,我都使用逗号,但是只要您始终使用相同的分隔符,都允许使用空格,换行符,随机字母等。所以2g3g5g8g13g4g7g11是一个合法的输出1,但2j3g5i8s13m4g7sk11并非如此。您可以使用字符串,列表,数组等任何东西,只要您具有以一致的分隔符分隔的正确顺序的正确数字。也可以用括号括住整个输出(例如(5,9,14)[5,9,14]等)。

测试用例:

1 -> 2,3,5,8,13,4,7,11
2 -> 2,3,5,8,13,4,7,11
3 -> 11,2,3,5,8,13,4,7
4 -> 3,5,8,13,4,7,11,2
5 -> 2,3,5,8,13,4,7,11
6 -> 3,5,8,13,4,7,11,2
7 -> 14,5,9
8 -> 13,4,7,11,2,3,5,8
9 -> 11,2,3,5,8,13,4,7
0 -> 0
14 -> 5,9,14
59 -> 5,9,14

这是,因此赢得的字节数最少。


1
我们可以接受2位数字而不是吗?0n99
Arnauld

1
像这样,采用两个输入而不是一个分开的输入?号
DonielF

我仍然不明白为什么,1459给出相同的结果。如果59将其解释为开始5,9并允许其作为循环的一部分,那么肯定14是其循环的开始吗?
尼尔

1
@williamporter序列的开头是0,1,1,2,3,5,8,13,4,7,11,2,3。循环的第一次重复是在第二次2
DonielF

2
@Neil各个序列的开头是1,4,5,9,14,55,9,14,5,9。他们都从第二个开始重复5。就像我之前说的,只有输入是分开的。后面的数字按顺序将它们的数字保持在一起。
DonielF

Answers:


10

果冻,15字节

DFṫ-SṭḊ
d⁵ÇÐḶZḢ

在线尝试!

怎么运行的

d⁵ÇÐḶZḢ  Main link. Argument: n (integer)

d⁵       Divmod 10; yield [n:10, n%10].
  ÇÐḶ    Call the helper link until a loop is reached. Return the loop.
     Z   Zip/transpose the resulting array of pairs.
      Ḣ  Head; extract the first row.


DFṫ-SṭḊ  Helper link. Argument: [a, b] (integer pair)

D        Decimal; replace a and b with the digits in base 10.
 F       Flatten the resulting array of digit arrays.
  ṫ-     Tail -1; take the last two digits.
    S    Compute their sum.
      Ḋ  Dequeue; yield [b].
     ṭ   Append the sum to [b].

6

Perl 6的96 78 75个字节

-3字节归功于nwellnhof

{0,|.comb,((*~*)%100).comb.sum...{my$a=.tail(2);m/(\s$a.*)$a/}o{@_};$_&&$0}

在线尝试!

0返回0,其他数字返回Match对象,该对象将字符串化为以空格开头并带有尾随空格的数字。

说明:

{                                                                         }   # Anonymous code block
 0,|.comb,                    ...   # Start a sequence with 0,input
                                    # Where each element is
                          .sum      # The sum of
          (     %100).comb          # The last two digits
           (*~*)                    # Of the previous two elements joined together
                                                                         # Until
                                 {                           }o{@_}   # Pass the list into another function
                                  my$a=.tail(2); # Save the last two elements
                                                m/(\s$a.*)$a/  # The list contains these elements twice?
                                                                     # And return
                                                                   ;$_     # Input if input is 0
                                                                      &&   # Else
                                                                        $0 # The looping part, as matched

5

的JavaScript(ES6), 111个104  103字节

f=(n,o=[p=n/10|0,n%10])=>n^o[i=o.lastIndexOf(n=(q=p+[p=n])/10%10+q%10|0)-1]?f(n,[...o,n]):o.slice(i,-1)

在线尝试!

已评论

f = (                       // f = recursive function taking:
  n,                        //    n = last term, initialized to the input
  o = [                     //    o = sequence, initially containing:
    p = n / 10 | 0,         //      p = previous term, initialized to floor(n / 10)
    n % 10 ]                //      n mod 10
) =>                        //
  n ^                       // we compare n against
  o[                        // the element in o[] located at
    i = o.lastIndexOf(      //   the index i defined as the last position of
      n =                   //     the next term:
        (q = p + [p = n])   //       q = concatenation of p and n; update p to n
        / 10 % 10           //       compute the sum of the last two digits
        + q % 10            //       of the resulting string
        | 0                 //       and coerce it back to an integer
      ) - 1                 //   minus 1
  ] ?                       // if o[i] is not equal to n:
    f(n, [...o, n])         //   append n to o[] and do a recursive call
  :                         // else:
    o.slice(i, -1)          //   we've found the cycle: return it

5

Python 3中187 176 158 139 138 129 121 120 112个 96 95 120 116字节

f=lambda n,m=0,z=[]:(n,m)in zip(z,z[1:])and z[z.index(m)::-1]or f((z and n//10or m%10)+n%10,z and n or n//10,(m,*z))

在线尝试!

编辑:如@ Jules所述,较短的解决方案适用于Python 3.6+。不再是Python 3 / 3.6+的独特解决方案

编辑:的索引z太冗长。没有它,现在使用毫无用处eval

编辑:简化查找是否在序列中已经出现了最后两个元素。

编辑:将输出格式从列表更改为元组+替换lambdadef

编辑:返回,lambda但嵌入t到中f

编辑:输入n实际上可以解释为增长集合的头z,它将代表递归方法的尾巴。也再次击败@ Arbo的解决方案。

编辑:实际上,您可以从头部解压缩两个项目,这又削减了16个字节。

编辑:实际上是17个字节。

编辑:正如@ Arbo所指出的那样,解决方案给出的答案1459案例与最初的测试案例相同,后来被证明是错误的。现在还不算短,但至少可以正常工作。


f-strings和的滥用eval。原始的非高尔夫代码,尽管我怀疑它可以通过某种方式更轻松地完成:

def is_subsequence(l1, l2):
    N, n = len(l1), len(l2)
    for i in range(N-n):
        if l1[i:i+n]==l2:
            return True
    return False

def generate_sequence(r):
    if is_subsequence(r,r[-2:]):
        return r
    last_two_digits = "".join(map(str,r))[-2:]
    new_item = sum(int(digit) for digit in last_two_digits)
    return generate_sequence(r + [new_item])

def f(n):
    seq = generate_sequence([n,n])[::-1]
    second_to_last = seq[1]
    first_occurence = seq.index(second_to_last)
    second_occurence = seq.index(second_to_last, first_occurence + 1)
    return seq[first_occurence + 1 : second_occurence + 1][::-1]

1
小修正:这是Python 3.6+。在3.5或更早版本中,这显然不起作用。
0xdd

1
您的测试代码似乎无效。59收益的输入(14, 5, 9)
ArBo

自从开始挑战以来,我发现测试用例已经改变,这就是为什么输出错误的原因。我已经更改了解决方案,使其可以正常工作,但现在还不算太短。不过,感谢您指出这一点。
西冈

4

C(GCC) 114个 112 109字节

f(n,s){int i[19]={};for(s=n/10,n%=10;i[s]-n;n+=n>9?-9:s%10,s=i[s])i[s]=n;for(;printf("%d ",s),i[s=i[s]]-n;);}

在线尝试!

-3从吊顶猫

包含尾随空格。

f(n,s){
    int i[19]={};                               //re-initialize edges for each call
    for(s=n/10,n%=10;                           //initialize from input
        i[s]-n;                                 //detect loop when an edge s->n repeats
        n+=n>9?-9:s%10,s=i[s])i[s]=n;           //step
    for(;printf("%d ",s),i[s=i[s]]-n;);         //output loop
}

1
呵呵,do...while如果它是单个语句,则不需要大括号O_o
仅支持ASCII的



2

Haskell,100字节

d!p@(s,t)|(_,i:h)<-span(/=p)d=fst<$>i:h|q<-d++[p]=q!(t,last$mod s 10+t:[t-9|t>9])
h x=[]!divMod x 10

在线尝试!

d!p@(s,t)                -- function '!' recursively calculates the sequence
                         -- input parameter:
                         -- 'p': pair (s,t) of the last two numbers of the sequence
                         -- 'd': a list of all such pairs 'p' seen before
  |       <-span(/=p)d   -- split list 'd' into two lists, just before the first
                         -- element that is equal to 'p'
   (_,i:h)               -- if the 2nd part is not empty, i.e. 'p' has been seen
                         -- before
          =fst<$>i:h     -- return all first elements of that 2nd part. This is
                         -- the result.
  |q<-d++[p]             -- else (p has not been seen) bind 'q' to 'd' followed by 'p'
   =q!                   -- and make a recursive call to '!' with 'q' and
     (t,    )            -- make the last element 't' the second to last element
                         -- the new last element is
          [t-9|t>9]      -- 't'-9 (digit sum of 't'), if 't'>9
       mod s 10+t        -- last digit of 's' plus 't', otherwise

h x=                     -- main function
     []!divMod x 10      -- call '!' with and empty list for 'd' and
                         -- (x/10,x%10) as the pair of last numbers

2

Python 2中123个 114 113字节

n=input()
p=b=l=n/10,n%10
while~-(b in p):p+=b,;l+=(b[1]/10or b[0]%10)+b[1]%10,;b=l[-2:]
print l[p.index(b)-2:-2]

在线尝试!

该程序将p在序列中出现的所有2值对中建立一个元组,并使用垃圾进行初始化以节省一些字节。序列本身内置在元组中l,该元组的最后两个元素存储在其中,b以方便(且简短)引用。一旦发现重复,我们就可以查找bin 的索引p来知道循环从哪里开始。

编辑:清理了一下,并减少了一个字节...我的方法似乎确实接近其字节数限制,我真的应该停止对此工作。


1

木炭,46字节

≔E◧S²ΣιθW¬υ≔ΦE⊖L⊞OθΣ…⮌⪫θω²✂θλLθ¹⁼κ✂θ⊗⁻λLθλ¹υIυ

在线尝试!链接是详细版本的代码。说明:

≔E◧S²Σιθ

输入数字,将其填充为2个字符,然后取每个字符的数字总和,并保存结果列表。

W¬υ

在循环列表为空时重复。

⊞OθΣ…⮌⪫θω²

计算前两个数字的总和,并将其添加到斐波纳契列表中。

E⊖L...✂θλLθ¹

取列表中所有不平凡的后缀。

≔Φ...⁼κ✂θ⊗⁻λLθλ¹υ

过滤掉那些不重复的结果,并将结果保存在循环列表中。

Iυ

将循环列表强制转换为字符串并打印。



1

Python 2中149个 139字节

s=input()
s=[s/10,s%10]
while zip(s,s[1:]).count((s[-2],s[-1]))<2:s+=[(s[-1]/10or s[-2]%10)+s[-1]%10]
print s[-s[::-1].index(s[-2],2)-1:-2]

在线尝试!

需要一个非负整数作为输入。较小的字节数,但对于大于99的整数可能不再起作用。

说明:

# get the input from STDIN
s=input()
# convert the input into two integers via a divmod operation
s=[s/10,s%10]
# count number of times the last two numbers appear in sequence in list.
# turn list into list of adjacent value pairs Ex: [1,1,2]->[(1,1),(1,2)]
      zip(s,s[1:])
                  # count number of times the last two items in list appear in entire list
                  .count((s[-2],s[-1]))
# if >1 matches, we have found a repeat.
while .................................<2:
        # the first digit of the last number, if it is >9
        # else the last digit of the second to last number
        (s[-1]/10or s[-2]%10)
                             # the last digit of the last number
                             +s[-1]%10
    # add the new item to the list
    s+=[..............................]
         # reverse the list, then find the second occurrence of the second to last item
         s[::-1].index(s[-2],2)
# get the section of the list from the second occurrence from the end, discard the final two items of the list
print s[-......................-1:-2]
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.