Продукти Фібоначчі


13

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

1 = 1
2 = 2
3 = 3
4 = 3 + 1
12 = 8 + 3 + 1
13 = 13
100 = 89 + 8 + 3

Тепер я називаю твір Фібоначчі ті самі списки, що і вище, але з додаванням, заміненим на множення. Наприклад, f(100) = 89 * 8 * 3 = 2136.

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


Тести:

1: 1
2: 2
3: 3
4: 3
5: 5
6: 5
7: 10
8: 8
9: 8
42: 272
1000: 12831
12345: 138481852236

6
Заява не зовсім коректна. Наприклад, 2можна розкласти як -1 + 3. Правильне твердження теореми Зекендорфа полягає в тому, що позитивне число Фібоначчі може бути однозначно розкладене як сума непослідовних чисел Фібоначчі з позитивним індексом.
Пітер Тейлор

1
@PeterTaylor Я не вважаю негативні числа Фібоначчі частиною серії для цього питання. Послідовні чи не лише важливі значення, коли потрібно індекси, ми не дбаємо про індекси цього питання.
orlp

1
Я не кажу, що ви повинні змінити питання, щоб підтримати негативні числа Фібоначчі: я кажу, що ви повинні відредагувати це, щоб бути ясним щодо припущень, які ви робите.
Пітер Тейлор

1
@orlp послідовно чи не має великого значення, оскільки дві різні форми дають два різні продукти. Ви вже заявляли про проблему таким чином, що вже неявно виключає послідовні терміни Фібоначчі, тому там нічого турбуватися.
варення

2
(конкретно: F (n) та F (n + 1) не можуть відображатися у висновку, оскільки алгоритм гарантує, що, перш ніж їх розглядати, решта вже менше F (n + 2) = F (n) + F (n + 1))
варильні панелі

Відповіді:


5

Желе , 16 15 байт

Rf1+С¤ṪạµÐĿIAP

Не особливо швидкий і не сприятливий для пам'яті, але досить ефективний для всіх тестових випадків. Спробуйте в Інтернеті!

Як це працює

Rf1+С¤ṪạµÐĿIAP  Main link. Argument: n (integer)

         µ       Combine the chain to the left into a link.
          ÐĿ     Apply that link until the results are no longer unique.
                 Return the list of unique results.
      ¤            Combine the two links to the left into a niladic chain.
  1                  Set the left (and right) argument to 1.
   +D¡               Apply + to the left and right argument, updating the left
                     argument with the sum, and the right argument with the
                     previous value of the left one. Return the list of results.
                     Repeat this process n times.
                   This yields n + 1 Fibonacci numbers, starting with 1, 2.
R                  Range; map k to [1, ..., k].
 f                 Filter; keep the items in the range that are Fibonacci numbers.
       Ṫ           Tail; yield the last one or 0 if the list is empty.
        ạ          Absolute difference with k.
                   This is the argument of the next iteration.
            I    Compute the increments of the arguments to the loop, yielding
                 the selected Fibonacci numbers (with changed sign).
             A   Apply absolute value to each.
              P  Compute their product.  

6
Це здається великим, Деннісе.
orlp

9

Пітон, 54 байти

f=lambda n,a=1,b=1:n<1or b>n and a*f(n-a)or f(n,b,a+b)

Просто якась стара стара рекурсія.


5

Perl, 69 63 + 4 ( -pl61прапор) = 67 байт

#!perl -pl61
while($_){$n=$m=1;($n,$m)=($m,$n+$m)until$m>$_;$_-=$n;$\*=$n}}{

Використання:

> echo 42 | perl -pl61e 'while($_){$n=$m=1;($n,$m)=($m,$n+$m)until$m>$_;$_-=$n;$\*=$n}}{'

Безголівки:

while (<>) {
# code above added by -p
    # $_ has input value
    # $\ = 1 by -l61
    while ($_ != 0) {
        my $n = 1;
        my $m = 1;
        while ($m <= $_) {
            ($n, $m) = ($m, $n + $m);
        }
        $_ -= $n;
        $\ *= $n;
    }
} {
# code below added by -p
    print;  # prints $_ (undef here) and $\
}

Ідеон .


У поясненні слід згадати, що восьмерика 061- це кодування ASCII для символу '1'. Хороший хак для використання, $\щоб надрукувати його майже безкоштовно.
Пітер Кордес

2

JavaScript (ES6), 78 42 байт

f=(n,a=1,b=1)=>n?b>n?a*f(n-a):f(n,b,a+b):1

Порт відповіді @ Sp3000 Оригінальна версія 78 байт:

f=(n,a=[2,1])=>n>a[0]?f(n,[a[0]+a[1],...a]):a.map(e=>e>n?0:(r*=e,n-=e),r=1)&&r

2

> <> , 57 байт

111\ ;n{/
:@+>:{:})?\$:@@
~{*}:0=?\}>:0${:})?$~:{$-$:1@?$

Очікує, що вхідний номер буде присутній у стеку при запуску програми.

Вибудовує послідовність Фібоначчі ( f0, f1, f2, ..., fn) на стеку, поки не буде досягнуте число, яке перевищує вхід ( i). Потім із продуктом ( p), ініціалізованим на 1...

while (i != 0)
   if (fn <= i)
      i = i - fn
      p = p * fn
   else
      i = i - 0
      p = p * 1
   discard fn
output p

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


Приємно! Я пропоную вам опублікувати посилання за допомогою онлайн-компілятора
Луїс Мендо


1

Pyth, 24 байти

W=-QeaYh.WgQeH,eZsZ1;*FY

Спробуйте в Інтернеті: Демонстрація або Тестовий набір

Пояснення:

Q присвоюється номер введення.

Частина h.WgQeH,eZsZ1обчислює найбільше число Фібоначчі, яке менше або дорівнюєQ

h.WgQeH,eZsZ1
            1   start with H=Z=1
 .WgQeH         while Q >= end(H):
       ,eZsZ       H=Z=(end(Z), sum(Z))
h               first

Тож якщо Q = 10, він генерує числа / пари:

1 -> (1,1) -> (1,2) -> (2,3) -> (3,5) -> (5,8) -> (8,13) -> 8

Решта коду обчислює розділ і множує числа разом:

W=-QeaY...;*FY    implicit: Y = empty list
     aY...        add the calculated Fibonacci number to the empty list
    e             take the last element of Y (yes the number we just added)
 =-Q              and update Q with the difference of Q and ^
W         ;       continue until Q == 0
           *FY    multiply all number in Y and print

Очевидно, є дуже багато коротших рішень (хоча і справді погані терміни виконання), як *FhfqQsTyeM.u,eNsNQ1.


1

Haskell, 44 байти

Так для взаємної рекурсії:

(a&b)c|c<1=1|b>c=a*f(c-a)|d<-a+b=b&d$c
f=0&1
  • a - попереднє число Фібоначчі
  • b - поточне число Фібоначчі
  • c є вхід
  • f - бажана функція

Менше гольфу:

(a & b) c | c == 0    = 1
          | c <  b    = a * f (c-a)
          | otherwise = b & (a + b) $ c
f x = (0 & 1) x

1

Власне, 22 байти

W;╗uR♂F;`╜≥`M░M;╜-WXkπ

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

Пояснення:

W;╗uR♂F;`╜≥`M░M;╜-WXkπ
                        (implicit input)
W                 W     while top of stack is truthy:
 ;╗                       push a copy of n to reg0
   uR♂F;                  push 2 copies of [Fib(a) for a in range(1, n+2)]
        `╜≥`M░            filter: take values where n <= Fib(a)
              M;          two copies of maximum (call it m)
                ╜-        subtract from n (this leaves n-m on top of the stack to be the new n next iteration, with a copy of m below it)
                   X    discard the 0 left over after the loop ends
                    kπ  product of all stack values

Чи має насправді власне кодування? Я рахую 35 байт через 22 символи. mothereff.in/…
кіт

1
@cat Як і серйозно, він використовує CP437.
Мего

1

Javascript (ES6) 134 106 92 байт

Дякуємо @cat, що помітили пробіл.

n=>{for(c=[a=b=s=1,1];a+b<=n;)a+=b,c.unshift(b+=a,a);c.map(i=>i<=n&&(n-=i)&(s*=i));alert(s)}

Просто неоптимізована версія, зроблена на моєму телефоні, я гольфую її, як тільки повертаюся додому. Ідеї ​​вітаються.


Є один надлишковий пробіл. : P
кіт

1

ПОВЕРНЕННЯ , 44 байти

[a:[a;][1$[¤¤+$a;->~][]#%$␌a;\-a:]#␁[¤][×]#]

Try it here.

Дивовижно неефективна анонімна лямбда, яка залишає результат на Stack2. Використання:

12345[a:[a;][1$[¤¤+$a;->~][]#%$␌a;\-a:]#␁[¤][×]#]!

ПРИМІТКА: ␌ і ␁ є заповнювачами для відповідних недрукованих символів: подача форми та початок заголовка .

Пояснення

[                                           ]  lambda
 a:                                            store input to a
   [  ][                         ]#            while loop
    a;                                           check if a is truthy
        1$[¤¤+$a;->~][]#%                        if so, generate all fibonacci numbers less than a 
                         $␌                      push copy of TOS to stack2
                           a;\-a:                a-=TOS
                                   ␁[¤][×]#   get product of stack2

Я рахую 46 байт через 42 символи. Якщо RETURN використовує якесь особливе спеціальне кодування, воно має бути 42 байти через 42 символи, але, схоже, це unicode, так що це 46.
кіт

Власне, я просто зрозумів, що забув поставити якісь недруковані матеріали.
Mama Fun Roll

Мені потрібен був мікроскоп, щоб сказати, що вони є, тому я зв’язав їх із вами. : D (я не міг сказати, чи це SOH чи BOM)
кіт

0

PHP, 119 байт

Код (загорнутий на два рядки для читабельності):

for($o=$c=1;$c<=$n=$argv[1];$f[++$k]=$c,$a=$b,$b=$c,$c+=$a);
for($i=$k;$i;$i--)for(;$n>=$d=$f[$i];$n-=$d,$o*=$d);echo$o;

Перший рядок обчислює $fчисла Фібоначчі, менші за $n(аргумент, наведений у командному рядку). Другий рядок обчислює коефіцієнти Фібоначчі (відніманням) і множує їх для обчислення добутку в $o.

Заздалегідь додайте код <?php(технічно не є частиною програми), покладіть його у файл ( fibonacci-factors.php), а потім запустіть його як:

$ php -d error_reporting=0 fibonacci-factors.php 100
# The output:
2136

Або запустити його за допомогою php -d error_reporting=0 -r '... code here ...' 100.

Невикористаний код та тестовий набір можна знайти в Github .


0

Q, 47 байт

m:{*/1_-':|(0<){y-x x bin y}[*+60(|+\)\1 0]\x}

Тест

+(i;m'i:1 2 3 4 5 6 7 8 9 42 1000 12345)

читайте його як пари (i, map (m, i)), де m - обчислювальна функція, i i різні аргументи

пише

1     1
2     2
3     3
4     3
5     5
6     5
7     10
8     8
9     8
42    272
1000  12831
12345 138481852236

Пояснення

n funtion\arg застосовує функцію (функція (функція (... функція (арг.))), n разів (внутрішньо використовує тал рекурсії), і повертає послідовність результатів. Обчислюємо 60 перших елементів серії фібонаків як *+60(|+\)\1 0. У цьому випадку функція ( | +): + \, застосований до послідовності, обчислює часткові суми (наприклад, + \ 1 2 3 є 1 3 6), і | обертається послідовність. Отже, при кожній "ітерації" ми обчислюємо часткові суми двох попередніх чисел поля і повертаємо часткове суми, зворотні, 60(|+\)\1 0генерує послідовності 1 0, 1 1, 2 1, 3 2, 5 3, 8 5, 13 8, 21 13, ..., *+застосовані над цим результатом, переверніть його (відкладіть) і приймайте перший. Результат - послідовність 1 1 2 3 5 8 13 21 34 55 ..

(cond)function\args застосовує функцію (функцію (.. функція (args))), коли cond true, і повертає послідовність часткових результатів

function[arg] застосований над функцією більш ніж одного аргументу створює проекцію (часткове застосування)

Ми можемо назвати аргументи, але неявні імена - x, y, z

{y-x x bin y}[*+60(|+\)\1 0]оголошує лямбда з аргами x, y з частковою проекцією (arg x - це поле серії, обчислюється як * + 60 (| +) \ 1 0). x представляють значення значень рівня, і y число, яке слід обробити. Бінарний пошук (бін) використовується для пошуку індексу більшого числа значень <= y ( x bin y) і підрегулювання відповідного значення x.

Щоб обчислити добуток за частковими результатами, ми повернемо їх і обчислимо різницю кожної пари ( -':|), опустимо першу ( 1_бо дорівнює 0) і помножимо на ( */).

Якщо нас цікавить накопичена сума, код той самий, але +/замість цього */. Також ми можемо використовувати будь-який інший діадичний оператор замість + або *

Про ефективність виконання

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

Я розробив другу версію (довжина 48 байт без урахування коментарів) і повторив тестові випадки батареї 1000 разів на обох версіях.

f:*+60(|+\)\1 0;m:{*/1_-':|(0<){x-f f bin x}\x}    /new version

час виконання: оригінальна версія 0'212 с., нова версія 0'037 с

Оригінальна версія обчислює серію fibbonaci один раз за програмою функції; нова версія обчислює лише один.

В обох випадках для розрахунку серій фільтрів використовується хвостова рекурсія

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.