Це таємно Фібоначчі?


23

Фон

Більшість із вас знає, що таке число Фібоначчі . Деякі з вас можуть знати, що всі додатні цілі числа можуть бути представлені у вигляді суми одного або декількох чітких чисел Фібоначчі, згідно з теоремою Зеккендорфа . Якщо кількість доданків в оптимальному представленні цілого числа Зекендорфа nє самим числом Фібоначчі, ми будемо називати n"таємно" Фібоначчі.

Наприклад:

139 = 89 + 34 + 13 + 3
This is a total of 4 integers. Since 4 is not a Fibonacci number, 139 is not secretly Fibonacci

140 = 89 + 34 + 13 + 3 + 1
This is a total of 5 integers. Since 5 is a Fibonacci number, 140 is secretly Fibonacci

Примітки

  • Оптимальне представлення Зекендорфа можна знайти за допомогою жадібного алгоритму. Просто візьміть найбільше число Фібоначчі <= n і відніміть його від n, поки не досягнете 0
  • Всі числа Фібоначчі можна представити у вигляді суми 1 числа Фібоначчі (себе). Оскільки 1 - число Фібоначчі, усі числа Фібоначчі також є таємно Фібоначчі.

Виклик

Ваше завдання полягає в тому, щоб написати програму або функцію, яка приймає ціле число і повертає, чи це ціле число є таємно Фібоначчі.

Вхідні дані

Ви можете взяти інформацію в будь-якому розумному форматі. Ви можете припустити, що вхід буде єдиним натуральним числом.

Вихідні дані

Виведіть один з двох різних результатів для того, чи є вхід таємно Фібоначчі. Приклади включають True/ False, 1/ 0тощо.

Оцінка балів

Це , тому найкоротша відповідь у байтах виграє! Стандартні лазівки заборонені.

Випробування

Truthy (secretly Fibonacci)
1
2
4
50
140
300099

Falsey (NOT secretly Fibonacci)
33
53
54
139
118808

6
Це означає, що вони цікаві?
кевін

2
У випадку, якщо це комусь корисне: Оптимальна сума - це унікальне рішення, яке не використовує двох послідовних чисел Фібоначчі.
kasperd

2
@kasperd Ти маєш рацію, що має сенс, якщо ти думаєш про це. Якщо рішення мало два послідовних числа Фібоначчі, їх можна було б скласти разом, щоб утворити наступне. Якби ваше рішення містило 5 та 8, це було б менш оптимально, ніж наявність одного 13.
Cowabunghole

@Cowabunghole У цьому полягає інтуїція. Повний доказ трохи складніше, ніж це. Якщо розчин вже містив 5, 8 і 13, то слід додати 8 + 13, а не 5 + 8. І інший напрям також повинен бути доведений.
kasperd

Відповіді:



8

Python 2 , 77 байт

def f(n):z=[bin(x).count('1')for x in range(n*n+1)if x&2*x<1];print z[z[n]]<2

Спробуйте в Інтернеті!

З цього використовується теорема про те, що два описи OEIS A003714 є рівнозначними:

н=Ж(i1)+Ж(i2)++Ж(iк)нна(н)=2i1+2i2++2iк1's.

zн

Тоді залишається перевірити, чи z[n]є число Фібоначчі, тобто z[z[n]] == 1.

н2+1


Ви можете вирізати два байти, видаливши задню поверхню bin(x). Ви також можете видалити його, перейшовши range(n*n+1)на range(n<<n). (Припустимо, що 0 недійсний)
неділя 2004

Я не знаю, що я думав із задніми руками bin(x), ха-ха. І, хм, 1<<nвже так, спосіб більш ніж достатньо, але я хотів би тримати час неастрономічного
Лінн

Справедливий момент, я думаю, що можливість запуску коду може бути важливим атрибутом. :)
nedla2004

6

Желе , 15 байт

‘ÆḞ€fRṪạµƬL’Ɗ⁺Ị

Монадична посилання, що приймає невід'ємне ціле число, яке виходить, 1якщо "Таємно Фібоначчі" та 0інше.

Спробуйте в Інтернеті! (занадто неефективно для великих тестових випадків)

Як?

‘ÆḞ€fRṪạµƬL’Ɗ⁺Ị - Link: integer, I
        µƬ      - perform the monadic link to the left as a function of the current I,
                - collecting up all the inputs until the results are no longer unique:
‘               -   increment I -> I+1
 ÆḞ€            -   nth Fibonacci number for €ach n in [1,I+1]
     R          -   range from 1 to I
    f           -   filter discard (discard Fibonacci numbers not in the range, i.e. > I)
      Ṫ         -   tail (get the largest)
       ạ        -   absolute difference with I
                - This gives us a list from I decreasing by Fibonacci numbers to 0
                - e.g. for 88 we get [88,33,12,4,1,0]
                -      because (88-33)+(33-12)+(12-4)+(4-1)+(1-0)=55+21+8+3+1=88 
          L     - length (the number of Fibonacci numbers required plus one)
           ’    - decrement (the number of Fibonacci numbers required)
            Ɗ   - treat the last three links (which is everything to the left) as a monad:
             ⁺  - ...and repeat it
                - i.e. get the number of Fibonacci numbers required for the number of
                -      Fibonacci numbers required to represent I.
                -      This is 1 if I is Secretly Fibonacci, and greater if not)
              Ị - insignificant? (is the absolute value of that <= 1?)


5

C # (.NET Core) , 124 115 98 байт

a=>{int n=0,b,c;for(;a>0;a-=b,n++)for(b=c=1;c<=a;b=c-b)c+=b;for(b=c=1;c<n;c+=b)b=c-b;return c==n;}

Спробуйте в Інтернеті!

-3 байти: змінено під час циклу на для (завдяки Олів'є Грегоаре )
-6 байт: переключений повертається на використання змінних, ініціалізовані b і c поза петлями (завдяки Кевіну Крейсейну )
-17 байт: змінено стан у другому циклі для переміщення, якщо з циклу та поєднуються із поверненими, повторно використаними b та c змінними в останньому циклі (завдяки raznagul )

Безголівки:

a => {
    int n = 0, b, c;                        // initialize variables

    for(; a > 0; a -= b, n++)               // increase n until a is 0
        for(b = c = 1; c <= a; b = c - b)   // set b and c to 1 for each a; set second largest Fibonacci number until largest Fibonacci number reaches a
            c += b;                         // set largest Fibonacci number of current sequence

    for(b = c = 1; c < n; c += b)           // while e is less than or equal to n, continue incrementing largest (e) Fibonacci number in the sequence
        b = c - b;                          // increment second-largest (d) Fibonacci number

    return c == n;                          // if c equals n, a is a secret Fibonacci number
}

1
for(;c<=a;b=c-b)c+=b;заощадить 3 байти.
Олів’є Грегоар

1
115 байт . Я видалив усі {}-вибрачки ваших петель і поставив все в- forпетлі. Крім того, я додав змінну, rяку ми встановили 1у вашому if(e==n)і повернемо наприкінці, тож у вас є лише одна return.
Kevin Cruijssen

Гарний дзвінок обом. Я намагався змінити цикл while на «for» і якось пропустив простий спосіб зробити це. Маючи окрему змінну для повернення, безумовно, також краще.
Meerkat

1
Змінюючи умови в другому контурі до e<nвам можна перемістити , ifщоб після циклу і consequentlly об'єднати його з returnдля 101 байт .
рознагул

1
Ви можете зберегти ще 3 байти шляхом повторного використання bта cв останньому циклі та видалення dта e.
raznagul

4

Perl 6 , 58 байт

{(1,&[+]...*>$_)∋($_,{$^n-(1,&[+]...^*>$n).tail}...0)-1}

Спробуйте в Інтернеті!

1, &[+] ... * > $_ це лише послідовність Фібоначчі, зупинена на зручному нескінченному місці (вхідне число).

$_, { $^n - (1, &[+] ...^ * > $n).tail } ... 0являє собою послідовність чисел, починаючи з вхідного числа, і кожен наступний елемент, отриманий шляхом віднімання найбільшого числа Фібоначчі, меншого або рівного попереднього елемента, від попереднього елемента. Послідовність завершується, коли 0буде досягнуто. Наприклад, якщо $_є 140, то така послідовність є 140, 51, 17, 4, 1, 0.

Віднімання одного з цієї послідовності трактує його як число, його довжину, а різниця - це число чисел Фібоначчі, які, складені разом, дають вхідне число. Потім це число перевіряється на приналежність до першої послідовності Фібоначчі.


Я не бачив цього фокусу з &[+]раніше! Приємно заощадити на тому, що не потрібно визначати два початкові терміни
Jo King

1
51 байт шляхом присвоєння послідовності Фібоначчі функції та декількох інших змін
Джо Кінг,

Порт l4m2 у відповідь JavaScript, 50 байт
nwellnhof

@nwellnhof Ha, у мене було майже те саме, за винятком невеликої різниці
Джо Кінг

3

Perl 6 , 48 байт

{4>($_,{$_,{$_-(1,&[+]...*>$_)[*-2]}...^0}...1)}

Спробуйте в Інтернеті!

Перетворює вхід до списку представництва Зекендорфа кілька разів, поки він не досягне єдиного числа, а потім перевіряє, чи довжина послідовності була меншою за 4.

Функція Zenckendorf посередині - це головним чином відповідь Шона з парою вдосконалень.

Пояснення:

{4>($_,{$_,{$_-(1,&[+]...*>$_)[*-2]}...^0}...1)}
{                                              } # Anonymous code block
                                          ...     # Define a sequence:
    $_  # That starts at the input
      ,{                                 }  # Each element is defined by:
                                   ... # Another sequence that:
        $_,   # Starts at the previous element
            $_-   # The previous element minus
                1,&[+]...*     # The Fibonacci sequence
                          >$_  # Ending when it is larger than the previous element
               (             )[*-2]  # The second from last element
          {                        }...^0  # Run until 0, discarding the last element
         # This returns the length of the Zeckendorf Representation
                                         ...1  # Run this until it is length 1
 4>(                                         )  # Return true if the length of the sequence is smaller than 4

Наприклад, послідовність для 2є, 2 1оскільки 2це вже число Фібоначчі. Послідовність для 140є 140 5 1, і оскільки 5 є числом Фібоначчі, це повертає істину. Послідовність для 33є 33 4 2 1, і оскільки 4це не число Фібоначчі, послідовність має довжину 4.


3

05AB1E , 14 байт

ΔDÅFθ-¼}¾ÅF¾<å

Спробуйте в Інтернеті . Немає тестового набору для всіх тестових випадків, оскільки counter_variableнеможливо відновити до 0 .. Я перевірив все вручну, і вони є правильними.

Пояснення:

Δ      }          # Loop until the top of the stack no longer changes
 D                #  Duplicate the top of the stack
                  #  (implicitly the input in the first iteration)
  ÅF              #  Get a list of all Fibonacci numbers lower than this number
    θ             #  Get the last item (largest one)
     -            #  Subtract it from the number
      ¼           #  Increase the counter_variable by 1 every iteration
        ¾         # After the loop, push the counter_variable
         ÅF       # Get all Fibonacci numbers below this counter_variable
           ¾<     # Push the counter_variable again, and subtract 1
             å    # Check if this value is in the list of Fibonacci numbers
                  # (and output implicitly)

ПРИМІТКА. Було counter_variableб як 5для введення, так 139і 6для введення 140, оскільки для того, щоб Δ-loop перевіряв стек залишився колишнім, це, звичайно, додаткова ітерація.



2

Сітківка 0,8,2 , 61 байт

.+
$*
M`((?>\2?)(\1|\G.))*..|.
.+
$*
^(((?>\3?)(\2|^.))*.)?.$

Спробуйте в Інтернеті! Посилання включає тестові випадки. Пояснення:

.+
$*

Перетворити в одинарне.

M`((?>\2?)(\1|\G.))*..|.

Порахуйте кількість необхідних чисел Фібоначчі.

Перше чергування стосується чисел Фібоначчі, що принаймні 2. На першому проході \2ще не існує, але, на щастя, це необов'язково, тому нам не доведеться відповідати цьому. \1Не існує також, але, на щастя, у нас є альтернатива, \G.яка відповідає одному символу на початку матчу. І те \2й \1інше набуває значення 1.

На наступних переходах \2існує, тому ми намагаємося відповідати цьому. Цього разу, якщо вона не вдається, то вона \1також не працює (оскільки вона більша, ніж \2), але якщо вона досягає успіху, (?>)перешкоджає зворотному відстеженню, тож якщо \2збігається, але \1чи не, ми не намагаємося просто \1. ( \G1завжди не вдається, оскільки ми просунулися минулого початку виправлення.) Нарешті, \2отримує попереднє значення, \1а час \1приймає суму двох значень.

Тому ми співставляємо стільки чисел Фібоначчі, скільки можемо, додаючи по мірі того, як ми йдемо. Оскільки часткові суми послідовності 1, 2, 3, 5..., 0, 1, 3, 6, 11...тобто на 2 менше, ніж числа Фібоначчі, то ми закінчуємо зіставленням 2 в кінці.

Це очевидно не відповідає сумі 1, тому чергування обробляє цей випадок.

.+
$*

Перетворити в одинарне.

^(((?>\3?)(\2|^.))*.)?.$

Перевірте, чи це число Фібоначчі. Для цього використовується та сама ідея, що і перший тест, але вона використовується ^замість цього, \Gі ми також повинні точно відповідати, тому він використовує необов'язковий захоплення замість чергування, як це гольфіст (але це збільшує кількість захоплення на 1).

Сітківка , 35 байт

.+
*
2}C`((?>\2?)(\1|\G.))*..|.
^1$

Спробуйте в Інтернеті! Посилання включає тестові випадки. Пояснення:

.+
*

Перетворити в одинарне.

C`((?>\2?)(\1|\G.))*..|.

Порахуйте кількість необхідних чисел Фібоначчі. (Цикло і конверсія, і лічильник економлять цілий байт над тим, щоб отримувати підрахунок в одинаковому спочатку.)

2}

Виконайте попередні кроки двічі. Для цього потрібно підрахувати числа Фібоначчі, необхідні для підрахунку чисел Фібоначчі.

^1$

Якщо число було таємно Фібоначчі, то результат дорівнює 1.


1

Python 2 , 146 137 байт

lambda a:len(g(len(g(a))))<2
f=lambda n:n<3or f(n-2)+f(n-1)
def g(a,n=1):j=f(n-1);return[j]if a-j<1else[j]+g(a-j)if a-f(n)<0else g(a,n+1)

Спробуйте в Інтернеті!

f () - рекурсивна функція, яка повертає значення n-го числа Фібоначчі. Взяте з цієї відповіді .

g () - рекурсивна функція, яка повертає представлення Зекендорфа заданого числа у вигляді списку цілих чисел.

Оскільки всі числа Фібоначчі матимуть зворотну довжину одного елемента з g (), h () перевіряє, чи довжина g () g (n) == 1.

EDIT: Збережено 9 байт завдяки nedla2004 . Я постійно забуваю, що лямбда - це не завжди найкраще рішення ...


1
138 байт . Я здебільшого просто робив gфункцію, щоб міг визначити f(n-1)змінну. З'єднайте інші зміни з того ==місця, <де вони однакові.
nedla2004
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.