Что такое повторяющиеся цифры Фибоначчи?

30

Как вы, вероятно, знаете, число Фибоначчи - это число, которое является суммой двух предыдущих чисел в серии.

Цифра Фибоначчи ™ - это сумма двух предыдущих цифр .

Например, для начала 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,2: 2,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,1и 11учитывается отдельно.

Каждое число выходных данных может быть разделено тем, что вы хотите, если это соответствует. Во всех моих примерах я использую запятые, но разрешены пробелы, разрывы строк, случайные буквы и т. Д., Если вы всегда используете одинаковое разделение. Так 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

Это , поэтому побеждает меньшее количество байтов.

DonielF
источник
1
Можем ли мы взять 2 цифры вместо ? 0N99
Арно
1
Как, взять два входа, а не один вход, который разделен? Нет
DonielF
Я до сих пор не понимаю почему 14и 59даю такой же результат. Если 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,5и 5,9,14,5,9. Оба они повторяют, начиная со второго 5. Как я сказал ранее, только вход разделен; более поздние числа сохраняют свои цифры в последовательности.
DonielF

Ответы:

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
Arnauld
источник
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.

Изменить: Упрощенный поиск, если последние два элемента уже появились в последовательности.

Изменить: Изменен формат вывода из списка на кортеж + заменен lambdaнаdef

Изменить: Вернуться, lambdaно встроен tв f.

Редактировать: Входные данные nмогут фактически интерпретироваться как глава растущей коллекции, zкоторая будет представлять хвост в рекурсивном подходе. Также снова побеждает решение @ Arbo .

Изменить: На самом деле вы можете распаковать два предмета из головы, который сокращает еще 16 байтов.

Изменить: На самом деле 17 байтов.

Редактировать: Как отмечает @ Arbo, решение давало ответы 14и 59кейсы, которые были в первоначальных тестовых примерах, которые впоследствии оказались неверными. Пока это не так коротко, но, по крайней мере, работает правильно.


Довольно злоупотребление 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
}
attinat
источник
1
да, do...whileфигурные скобки не нужны, если это одно утверждение O_o
только для ASCII
3

Perl 5, 90 76 байт

s/.\K/ /;s/(.?) *(.)\K$/$".($1+$2)/e until/^0|\b(.\B.|. .)\b.*(?= \1)/;$_=$&

TIO

Науэль Фуйе
источник
@JoKing, исправлено и оптимизировано
Науэль Фуйе
2

Java (JDK) , 194 байта

n->"acdfinehlcdfinehfjofj".chars().map(x->x-97).skip((n="abbicbcsfibbbgqifiibbgbbbcsfbiiqcigcibiccisbcqbgcfbffifbicdqcibcbicfsisiibicfsiffbbicfsifiibicfsifii".charAt(n)%97)).limit(n<1?1:n<9?8:3)

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

Жесткий код казался самым коротким, учитывая, что у Python уже был ответ 187 ...

Оливье Грегуар
источник
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из всех двухзначных пар, которые встречаются в последовательности, которая инициализируется с помощью мусора, чтобы сохранить несколько байтов. Сама последовательность встроена в кортеж l, а последние два элемента этого кортежа хранятся bдля удобства (и краткости). Как только повторение будет найдено, мы можем посмотреть индекс bв pзнать , где начинается цикл.

РЕДАКТИРОВАТЬ: немного убрал это, и сбрил еще один байт ... Мой метод, кажется, приближается к пределу количества байтов, и я действительно должен прекратить работать над этим.

ARBO
источник
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]
Triggernometry
источник