フィボナッチ製品


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つの異なる形式が2つの異なる製品を与えるため、かなり重要です。ただし、連続したフィボナッチ項をすでに暗黙的に除外する方法で問題をすでに述べているので、心配する必要はありません。
ホブス

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)

ちょうどいくつかの古き良き再帰。


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

イデオネ


説明では、8進数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

実際には独自のエンコーディングがありますか?22文字にわたって35バイトをカウントします。mothereff.in/…–

1
@cat真剣に、CP437を使用します。
メゴ

1

ジャバスクリプト(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)}

携帯電話で作成された最適化されていないバージョンで、家に帰ってからゴルフをします。アイデアは大歓迎です。


余計な余白が1つあります。:P

1

RETURN、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

42文字で46バイトをカウントします。RETURNが何らかの特殊なエンコードを使用する場合、42文字で42バイトになるはずですが、ユニコードであるように見えるため、46になります。–
cat

実際、印刷できないものを入れるのを忘れたことに気付きました。
ママファンロール

それらが何であるかを知るために顕微鏡が必要だったので、あなたのためにそれらにリンクしました。:D(SOHかBOMかはわかりませんでした)

0

PHP、119バイト

コード(読みやすくするために2行でラップ):

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(コマンドラインで提供される引数)よりも小さい値を計算します。2行目は、フィボナッチ係数を(減算により)計算し、それらを乗算して次の積を計算します。$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は異なる引数です。

書く

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回(内部TAL再帰を使用して)適用し、結果のシーケンスを返す。我々はfibonnaci一連の60の最初の項目を計算する*+60(|+\)\1 0。その場合、関数は、(あります| +):+ \シーケンスに適用すると、部分和(ex + \ 1 2 3は1 3 6)が計算され、|はseqを逆にします。合計が逆になり60(|+\)\1 0、シーケンス1 0、1 1、2 1、3 2、5 3、8 5、13 8、21 13、...が生成されます*+ reverse。シーケンス1 0、1 1、2 1、3 2、5 3、8 5、13 8、21し、この結果に適用して、反転(対置)し、最初に取得します。 1 2 3 5 8 13 21 34 55 ..

(cond)function\args cond trueの間にfunction(function(.. function(args))))を適用し、部分的な結果のシーケンスを返します

function[arg] 複数の引数の関数に適用すると、投影が作成されます(部分的なアプリケーション)

引数に名前を付けることはできますが、暗黙的な名前はx、y、zです

{y-x x bin y}[*+60(|+\)\1 0]部分投影を使用してargs x、yでラムダを宣言します(arg xはフィボナッチ数列で、* + 60(| +)\ 1 0として計算されます)。xはフィボナッチ値を表し、yは処理する数を表します。より大きいフィボナッチ数<= y(x bin y)のインデックスを見つけ、xの対応する値を減算するには、バイナリ検索(bin)が使用されます。

部分的な結果から製品を計算するには、それらを逆にして各ペアの差を計算し(-':|)、最初の(1_0であるため)をドロップし、乗算します(*/)。

累積和に関心がある場合、コードは同じですが、+/ではなくになり*/ます。また、+または*の代わりに他のダイアディック演算子を使用することもできます

実行効率について

このコンテストでは効率が問題にならないことを知っています。しかし、この問題では、線形コストから指数コストまで幅があるため、私はそれについて興味があります。

2つ目のバージョン(コメントを除く長さ48バイト)を開発し、両方のバージョンでテストケースを1000回繰り返しました。

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

実行時間:オリジナルバージョン0'212 seg、新しいバージョン0'037 seg

元のバージョンでは、関数アプリケーションごとにfibbonaciシリーズを計算します。新しいバージョンでは、フィボナッチを1つだけ計算します。

どちらの場合でも、フィボナッチ数列の計算は末尾再帰を使用します

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.