找到斐波那契模式


16

您可能熟悉斐波那契数列,其中前两个项是0, 1(或有时是1, 1),其后的每个项都是前两个项的总和。它是这样开始的:

0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, ...

有时,序列包含具有特殊图案的数字,我发现这很有趣:相邻数字对之间的差异与其他任何对相同。例如,在以开头的序列中0, 1,第18个项是9879-8=18-7=1。我很满意。

挑战

给定两个初始值F(0)F(1),输出由生成的序列F(n) = F(n-1) + F(n-2)中满足以下条件的每个数字:

  • 任何一对相邻数字之间的差异与任何其他一对相同
  • 至少三位数字长(此模式对1位和2位数字不感兴趣)

输入值

  • 小于10 ** 10(100亿)的两个非负整数

输出量

  • 所有小于10 ** 10且符合“挑战”部分中的条件的整数
  • 输出大于10 ** 10的数字是可以接受的,但这不是必需的
  • 假设重复的数字符合模式(例如777),则可能有无数个符合条件的数字,但您的程序不需要永远输出
  • 如果不存在这样的整数,则输出任何您想要的东西,只要它不是数字即可(无,空,空数组,错误消息,悲伤的面孔等)。
  • 如果与模式匹配的数字在序列中出现多次,则可以将其输出一次或多次
  • 如果任何输入符合条件,则应将其包含在输出中

规则

示例/测试用例

Input , Output   
[1,10] , []   

[0,1] , [987]   
[2,1] , [123]   
[2,3] , [987]   

[61,86] , [147]   
[75,90] , [420]   
[34,74] , [1234]   
[59,81] , [2468]   
[84,85] , [7531]   

[19,46] , [111]   
[60,81] , [222]   
[41,42] , [333]   
[13,81] , [444]   
[31,50] , [555]   
[15,42] , [666]   
[94,99] , [777]   
[72,66] , [888]  
[3189,826] , [888888888]    

[15,3] , [159,258]   
[22,51] , [321,1357]   
[74,85] , [159,4444]   
[27,31] , [147,11111]   

[123,0] , [123,123,123,246,369]   
[111,0] , [111,111,111,222,333,555,888]
[111,222] , [111,222,333,555,888]      

[33345,692] , [987654321]   
[3894621507,5981921703] , [9876543210]
[765432099,111111111] , [111111111,876543210,987654321]   

[1976,123] , [123, 2222, 4321, 6543, 45678]   

1
建议测试用例:[1976, 123] -> [123, 2222, 4321, 6543, 45678][3189, 826] -> [888888888][33345, 692] -> [987654321]
阿尔诺

@Arnauld太好了!我想知道哪个起始对的最大输出值小于10B。上面的任何东西都是repdigits,那很无聊。
土司工程师

@Arnauld感谢测试用例的更正。在我的原始生成器中,我没有包含输入。当我返回并添加它们时,我显然想念这两个。
敬酒工程师

Answers:


9

MATL,14字节

感谢Emigna指出了一个错误,现已更正

`yVdd~?yD]wy+T

无限循环,输出找到的数字。

在线尝试!请注意,在线解释器中的结果将在1分钟超时后显示。

说明

F(n)F(n+1)表示斐波那契数列的两个通用连续项。该循环的每次迭代与含有堆栈开始F(n)F(n+1)对于一些n

`         % Do...while
  y       %   Duplicate from below. Takes the two inputs F(0), F(1) (implicitly)
          %   in the first iteration
          %   STACK: F(n), F(n+1), F(n)
  V       %   Convert to string. Let the digits of F(n) be '3579' for example
          %   STACK: F(n), F(n+1), '3579'
  d       %   Consecutive differences (of ASCII codes)
          %   STACK: F(n), F(n+1), [2 2 2]
  d       %   Consecutive differences
          %   STACK: F(n), F(n+1),  [0 0]
  ~       %   Logical negate, element-wise
          %   STACK: F(n), F(n+1), [1 1]
  ?       %   If top of the stack is non-empty and only contains non-zero entries
          %   (this is the case for digits '3579', but not for '3578' or '33')
          %   STACK: F(n), F(n+1)
    y     %     Duplicate from below
          %     STACK: F(n), F(n+1), F(n)
    D     %     Display immediately. This prints the copy of F(n)
          %     STACK: F(n), F(n+1)
  ]       %   End
  w       %   Swap
          %   STACK: F(n+1), F(n)
  y       %   Duplicate from below
          %   STACK: F(n+1), F(n), F(n+1)
  +       %   Add. Note that F(n)+F(n+1) is F(n+2) 
          %   STACK: F(n+1), F(n+2)
  T       %   Push true. This will be used as loop condition
          %   STACK: F(n+1), F(n+2), true
          % End (implicit). The top of the stack is consumed as loop condition.
          % Since it is true, a new iteration will begin, with the stack
          % containing F(n+1), F(n+2)

6

05AB1E17 16 15字节

тFÂ2£O¸«}ʒS¥¥_W

在线尝试!

说明

                  # implicitly input list of F(0) and F(1)
тF      }         # 100 times do:
  Â               # bifurcate current list
   2£             # take the first 2 items
     O            # sum
      ¸«          # append to list
         ʒ        # filter, keep only elements that are true after:
          S¥¥     # delta's of delta's of digits
             _    # logically negate each
              W   # min

5

JavaScript(ES6),85 84 81字节

f=(p,q,a=[])=>p|q?f(q,p+q,![...p+''].some(x=d=n=>r=d-(d=x-(x=n)))/r?[...a,p]:a):a

在线尝试!

测试相邻数字

![...p + ''].some(x = d = n => r = d - (d = x - (x = n))) / r

这两个Xd被初始化到一个匿名函数,它的力量NaN为他们参与了所有的算术运算。第一次迭代some()总是给人(d = [function] - n) === NaN(r = [function] - d) === NaN(falsy)。在第二次迭代中,我们有d = x - n(整数)和(r = NaN - d) === NaN(再次伪造)。从第三次迭代开始,如果数字#3和数字#2之间的差不等于数字#2和数字#1之间的差,则r设置为非零的整数。

p是满足所要求的标准,当且仅当some()是falsy(所有相邻位具有相同的差)和最终值[R0(至少有3次迭代)。这给出了!false / 0 === true / 0 === Infinity(真实的)。

否则我们可能有:

  • !true / rr> 0r <0时,给出false / r === 0(falsy)
  • !false / NaN,给出true / NaN === NaN(虚假)

停止条件

p | q求值为0时,递归停止。当pq都达到10 25 25左右的值(84位长)时,肯定会发生这种情况。由于JS的尾数为52位,因此最后32位为零。因此,32位按位或的计算结果为0

由于序列的快速增长,因此发生的速度相当快。


4

Java 8,151 144 140 136 130字节

(a,b)->{for(long n,m,d,p;;System.out.print(m>99&p==d?m+" ":""),m=a+b,a=b,b=m)for(m=n=a,d=p=10;n>9&d==p|p>9;d=n%10-(n/=10)%10)p=d;}

无限循环在找到数字时输出它们。
在线尝试(60秒后超时)。

136字节版本,增加了10 10个限制(a<1e10):

(a,b)->{for(long n,m,d,p;a<1e10;System.out.print(m>99&p==d?m+" ":""),m=a+b,a=b,b=m)for(m=n=a,d=p=10;n>9&d==p|p>9;d=n%10-(n/=10)%10)p=d;}

在线尝试。

说明:

(a,b)->{         // Method with two long parameters and no return-type
  for(long n,m,  //  Temp numbers
           d,p;  //  Current and previous differences
      a<1e10;    //  Loop as long as `a` is still below 10^10
      ;          //    After every iteration:
       System.out.print(
                 //     Print:
        m>99     //      If the number has at least three digits,
        &p==d?   //      and the previous and current differences are still the same
         m+" "   //       Print the current number with a space delimiter
        :        //      Else:
         ""),    //       Print nothing
                 //     Go to the next Fibonacci iteration by:
       m=a+b,    //      Setting the temp-number `m` to `a+b`
       a=b,      //      Replacing `a` with `b`
       b=m)      //      And then setting `b` to the temp number `m`
    for(m=n=a,   //   Set both `m` and `n` to `a`
        d=p=10;  //   Set both `d` and `p` to 10
        n>9      //   Inner loop as long as `n` has at least two digits,
        &d==p    //   and `p` and `d` are still the same,
         |p>9    //   or `p` is still 10
        ;        //     After every iteration:
         d=n%10-(n/=10)%10)
                 //      Set `d` to the difference between the last two digits of `n`
                 //      And integer-divide `n` by 10 at the same time
      p=d;}      //    Set the previous difference `p` to `d`

4

果冻20 19 18字节

>ȷ2ȧDIEƊ
+ƝḢ;Ɗȷ¡ÇƇ

在线尝试!

+ƝḢ;Ɗȷ¡产生系列中的前千(ȷ)个词,这些词总是足够的。我认为可能有更短的方法可以做到这一点。+ȷ¡接近,但仅在第一项为零时有效。

我假设我们可以取两个相反的数字,从而允许一个字节DIE

如果不需要我们输出任何一个输入:

果冻,15个字节

>ȷ2ȧDIEƊ
+ṄÇ¡ß@

在线尝试!


5
我们DIEƊ在打高尔夫球的过程中全力以赴。
阿诺尔德

4

八度91 90 83字节

感谢Luis Mendo,节省了7个字节!

@(t)eval"for i=3:99,if~diff(diff(+num2str(t(1))))disp(t(1))end,t=[t(2) sum(t)];end"

在线尝试!

好吧,它起作用了!

eval里面有for循环以节省一些字节。跳过冒号和分号以节省一些。使用矢量被认为是真实的事实,前提是所有元素都不为零即可保存anyall

除此之外,它几乎是斐波那契的直接实现。



2

Haskell,105个字节

u%v|let s=u:scanl(+)v s=[n|n<-s,d<-[f(-).map fromEnum.show$n],length d>1,and$f(==)d]
f g=zipWith g=<<tail

定义运算符(%),该运算符将返回包含所有解的无限列表。要在stdout上实际看到结果,我们需要禁用缓冲(或在中运行ghci或使用runhaskell),请在线尝试!

解释/取消

该函数f只是一个辅助函数,需要一个二进制函数和一个列表,它将该函数g应用于所有相邻对。它基本上与以下内容相同:

adjacent g xs = zipWith (tail xs) xs

运算符(%)只是一个列表理解,它会进行一些过滤(确保至少有3位数字且相邻的数字具有相同的距离):

u % v
  -- recursively define s as the "Fibonacci sequence" with f(0) = u and f(1) = v
  | let sequence = u : scanl (+) v sequence
  -- take all numbers from that sequence using the filters below
  = [ number | number <- sequence
  -- convert to string, get the ASCII codepoints and build a list of the adjacent differences
        , let differences = adjacent (-) . map fromEnum . show $ number
  -- numbers with > 3 digits have >= 2 adjacent digits (or rather differences of digits)
        , length differences > 1
  -- make sure all of these are equal by comparing them and reducing with logical and
        , and $ adjacent (==) differences
    ]

2

CJam,55个字节

q~{1$_99>"_`2\ew{{-}*}%""3,"?~_(+="0$p"*~;_@+_11_#<}g;;

在线尝试!

我第一次提交CJam,不是很简短,但很有趣。欢迎任何建议!


很高兴知道,谢谢您的提示!我已经更新了提交内容。
maxb

2

Stax26 24 字节

Ç╕SôεPN^:·░ßⁿ {@ÿ}Ü╫╣1╣X

运行并调试

说明

E{b+}99*L{E%2>|cd_E:-u%1=!C_Qf    # Full program, unpacked, implicit input
E                                 # Push all elements from array onto stack.
 {b+}99*L                         # Generate the first 99 numbers of the  Fibonacci sequence given the input
         {                   f    # Loop through all Fibonacci elements
          E                       # Array of decimal digit
           %2>                    # Does the array have at least 3 digits
              |c                  # Assume Truthy past this point
                d                 # discard top of stack
                 _E               # Copy the current element of the Fibonacci sequence and Digitize it
                  :-              # Pairwise difference of array.
                    :u            # Is there exactly 1 unique number
                        !C        # Flip the comparison, if truthy proceed
                          _Q      # Copy the current element of the Fibonacci sequence and Peek and print with a newline.

没有我想要的那么短,也许可以打更多的高尔夫球,但是它起作用。



1

朱0.686 81个字节

a<b=b>=0&&((n->n>99&&2>endof(∪(diff(digits(n))))&&println(n)).([a,b]);a+b<a+2b)

在线尝试!

非常简单-检查输入是否至少包含3个数字(n>99),然后取数字()中每个数字对之间的差diff(digits(n)),检查()的长度是否endof是唯一的()这些差为1(即所有差相同),如果是,则打印数字。对两个给定的数字都执行此操作,然后用接下来的两个数字递归调用该函数。

(不幸的是,它的±优先级似乎比更高+,否则最终调用本来可以a+b±a+2b节省3个字节。)现在使<运算符超载,从而节省了运算符字节和优先级括号。(<尽管不能在我们的代码中使用,所以将其重新排列endof(...)<22>endof(...))。

如果允许一些无关紧要的输出,我们可以使用@show而不是printlnprint n = 987代替just 来保存2个字节987。我们甚至可以使用dump比其低1个字节的字节,但是会dump打印类型信息和值,因此输出将Int64 987不是just 987

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.