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

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 возвращает произведение Фибоначчи от этого числа.


Testcases:

1: 1
2: 2
3: 3
4: 3
5: 5
6: 5
7: 10
8: 8
9: 8
42: 272
1000: 12831
12345: 138481852236
orlp
источник
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

Python, 54 байта

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

Просто старая добрая рекурсия.

Sp3000
источник
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}}{'

Ungolfed:

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 $\
}

Ideone .

Денис Ибаев
источник
В объяснении следует упомянуть, что восьмеричное 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) в стеке, пока не будет достигнуто число, превышающее значение input ( 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

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

Sok
источник
Ницца! Предлагаю опубликовать ссылку с помощью онлайн-компилятора
Луис Мендо
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.

Jakube
источник
1

Haskell, 44 байта

Yay для взаимной рекурсии:

(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
Mego
источник
На самом деле есть своя собственная кодировка? Я считаю 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
Mama Fun Roll
источник
Я считаю 46 байтов через 42 символа. Если RETURN использует какую-то особую кодировку, то она должна быть 42 байта через 42 символа, но это, похоже, юникод, так что это 46.
cat
На самом деле, я только что понял, что я забыл положить некоторые непечатные.
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 .

axiac
источник
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 - различные аргументы

пишет

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 применяет функцию (function (function (... function (args)))) n раз (внутренне использует рекурсию тала) и возвращает последовательность результатов. Мы вычисляем 60 первых элементов ряда Фибоначчи как *+60(|+\)\1 0. В этом случае функция равна ( | +): + \, примененный к последовательности, вычисляет частичные суммы (ex + \ 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, ...*+ примененные к этому результату, переворачивают (traspose) и принимают первое. Результатом является последовательность 1 1 2 3 5 8 13 21 34 55 ..

(cond)function\args применяет функцию (function (.. function (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 число для обработки. Бинарный поиск (bin) используется для определения индекса большего числа Фибоначчи <= 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 сег

Оригинальная версия рассчитывает фиббонитную серию один раз для каждой функции приложения; Новая версия Фибоначчи рассчитывает только один.

В обоих случаях для вычисления ряда Фибоначчи используется хвостовая рекурсия

Дж. Сендра
источник