Найти паттерны Фибоначчи

16

Вы, вероятно, знакомы с последовательностью Фибоначчи, где первые два слагаемых являются 0, 1(или иногда 1, 1), а каждый последующий слагаемый является суммой двух предыдущих. Это начинается так:

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

Иногда последовательность содержит числа, которые имеют определенный шаблон, который я нахожу интересным: разница между любой парой соседних цифр такая же, как и у любой другой пары. Например, в последовательности, начинающейся с 0, 118-го члена, это 987. 9-8=1и 8-7=1. Я слегка доволен.

Вызов

Имея два начальных значения F(0)и F(1), выведите каждое число в сгенерированной последовательности, F(n) = F(n-1) + F(n-2)которое соответствует следующим критериям:

  • Разница между любой парой соседних цифр такая же, как и у любой другой пары
  • Он состоит как минимум из трех цифр (1 и 2 цифры не интересны для этого шаблона)

вход

  • Два неотрицательных целых числа меньше 10 ** 10 (10 миллиардов)

Выход

  • Все целые числа, которые меньше 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
@ Arnauld Отличная находка! Интересно, у какой стартовой пары больше всего выходных значений меньше 10В. Все, что выше, будет репигитами, и это скучно.
Тост инженера
@Arnauld Спасибо за исправления тестовых случаев. В моем оригинальном генераторе я не включил входы. Я явно скучал по этим двум, когда вернулся и добавил их.
Тост инженера

Ответы:

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

05AB1E , 17 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
Emigna
источник
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

И x, и d инициализируются анонимной функцией, которая форсирует NaNвсе арифметические операции, в которых они участвуют. Первая итерация some()всегда дает (d = [function] - n) === NaNи (r = [function] - d) === NaN(ложь). На второй итерации мы имеем d = x - n(целое число) и (r = NaN - d) === NaN(снова ложно). Начиная с третьей итерации, r устанавливается в целое число, которое не равно нулю, если разница между цифрой № 3 и цифрой № 2 не равна разнице между цифрой № 2 и цифрой № 1.

Число p соответствует требуемым критериям тогда и только тогда, когда some()оно ложно (все смежные цифры имеют одинаковую разницу), а конечное значение r равно 0 (было не менее 3 итераций). Это дает !false / 0 === true / 0 === Infinity(правда).

В противном случае мы можем иметь:

  • !true / rс r> 0 или r <0 , что дает false / r === 0(ложь)
  • !false / NaN, который дает true / NaN === NaN(ложь)

Состояние остановки

Рекурсия останавливается, когда p | qоценивается в 0 . Это гарантированно произойдет, когда p и q достигнут значений около 10 25, которые имеют длину 84 бита. Поскольку JS имеет 52 бита мантиссы, последние 32 бита обнуляются. Итак, 32-битное побитовое ИЛИ равно 0 .

Из-за быстрого роста последовательности, это происходит довольно быстро.

Arnauld
источник
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Ɗ
+ṄÇ¡ß@

Попробуйте онлайн!

dylnan
источник
5
Наши мысли на все бесстрашные байты, которые DIEƊво время процесса игры в гольф.
Арно
4

Октава , 91 90 83 байта

Сэкономили 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 внутри, чтобы сохранить несколько байтов. Пропуск двоеточий и точек с запятой, чтобы сохранить несколько. Использует тот факт, что вектор считается правдивым, если все элементы ненулевые для сохранения anyилиall .

Помимо этого, это в значительной степени прямая реализация Фибоначчи.

Стьюи Гриффин
источник
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), попробуйте его онлайн!

Объяснение / Ungolfed

Функция 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
источник
Это приятно знать, спасибо за совет! Я обновил представление.
maxb
2

Stax , 26 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,6 , 86 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+2b3 байта.) Теперь перегружает <оператор, таким образом сохраняя как байты оператора, так и скобки приоритета. (Невозможно использовать <в нашем коде , хотя, так что просто переставить endof(...)<2в2>endof(...) ).

Если разрешен какой-то посторонний вывод, мы можем сохранить 2 байта, используя @showвместо printlnпечати, n = 987а не просто 987. Мы могли бы даже использовать его dumpна 1 байт меньше, но dumpпечатать информацию о типе вместе со значением, поэтому вывод будет Int64 987вместо просто 987.

sundar - Восстановить Монику
источник