この番号は密かにフィボナッチですか?


23

バックグラウンド

あなたのほとんどはフィボナッチ数が何であるか知っています。ツェッケンドルフの定理によれば、正の整数はすべて、1つ以上の異なるフィボナッチ数の合計として表現できることを知っている人もいるかもしれません。整数の最適なツェッケンドルフ表現の項の数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

ノート

  • 最適なZeckendorf表現は、貪欲なアルゴリズムを使用して見つけることができます。最大のフィボナッチ数<= nを取得し、0に達するまでnから減算します。
  • すべてのフィボナッチ数は、1つのフィボナッチ数(それ自体)の合計として表すことができます。1はフィボナッチ数であるため、すべてのフィボナッチ数も密かにフィボナッチ数です。

チャレンジ

あなたの課題は、整数を受け取り、その整数が密かにフィボナッチであるかどうかを返すプログラムまたは関数を書くことです。

入力

妥当な形式で入力できます。入力は単一の正の整数であると仮定できます。

出力

入力が密かにフィボナッチであるかどうかについて、2つの異なる結果の1つを出力します。例には、True/ False1/ 0などが含まれます。

得点

これはなので、バイト単位の最短回答が勝ちです!標準的な抜け穴は禁止されています。

テストケース

Truthy (secretly Fibonacci)
1
2
4
50
140
300099

Falsey (NOT secretly Fibonacci)
33
53
54
139
118808

6
これは彼らが好奇心re盛だということですか?
ケビン

2
誰にでも役立つ場合:最適な合計は、2つの連続したフィボナッチ数を使用しない一意のソリューションです。
カスペルド

2
@kasperdあなたは正しいです、それについて考えれば理にかなっています。ソリューションに2つの連続したフィボナッチ数がある場合、それらを加算して次のフィボナッチ数を作成できます。ソリューションに5と8が含まれていた場合、単一の13を持つよりも最適性は低くなります
。– Cowabunghole

@Cowabungholeそれは直感です。完全な証明は、それよりも少し複雑です。ソリューションにすでに5、8、および13が含まれている場合、5 + 8ではなく8 + 13を追加します。そして、他の方向も同様に証明される必要があります。
カスペルド

回答:



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の 2つの記述が同等であるという定理を利用しています。

フィビナリ数:がツェッケンドルフ表現で(つまり、フィボナッチ数体系でを書く)。 また、バイナリ表現に2つの隣接するが含まれない数値。n=F(i1)+F(i2)++F(ik)nna(n)=2i1+2i2++2ik1

このような数を十分に生成zし、1を2進数でカウントすることにより、負でない整数から「のツェッケンドルフ表現にいくつの項があるか」へのマッピングとして使用します。n

次にz[n]、フィボナッチ数であるかどうかを確認しz[z[n]] == 1ます。

*少なくとも、n2+1 十分であると感じており、実験的には十分であると思われます。これについては後ほど証明します。


周りのバックティックを削除することで2バイトをカットできますbin(x)。に変更range(n*n+1)して削除することもできrange(n<<n)ます。(0が無効であると想定)
nedla2004

私は周りのバックティックスで考えていたことを知らなかったbin(x)、ハハ。そして、HMは、1<<nすでに道、十二分な方法ですが、私は、ランタイム非天文維持したいのですが
リン

まあ、コードを実行できることは重要な属性かもしれません。:)
nedla2004

6

ゼリー、15 バイト

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

1「Secretly Fibonacci」の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コア)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の外側に戻り(おかげ切り替えケビンCruijssen
場合に移動させる第二のループに変更された条件:-17バイトループ外で、最後のループでbおよびc変数を再利用してreturnと結合します(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)そのため、変数は1つだけreturnです。
ケビンクルーッセン

両方に良い電話。whileループをforに変更しようとしましたが、どうにかして簡単な方法を逃していました。戻り用に別の変数を用意することも間違いなく優れています。
ミーアキャット

1
2番目のループの条件を変更することにより、ループの後にto e<nを移動し、ifその結果をreturnfor 101バイトと組み合わせることができます
raznagul

1
最後のループでandを再利用してband cを削除するdと、さらに3バイト節約できます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

このシーケンスから1を引くと、それが数字、その長さとして扱われ、差はフィボナッチ数の数になります。フィボナッチ数は合計して入力数を与えます。次に、この番号の最初のフィボナッチ数列のメンバーシップがチェックされます。


私は&[+]以前にそのトリックを見たことがない!最初の2つの用語を定義する必要がないという素晴らしい節約
Jo King

1
フィボナッチ数列を関数に割り当て、その他のいくつかの変更により51バイト
ジョーキング

l4m2のJavaScript回答のポート、50バイト
-nwellnhof

@nwellnhofハ、私はほとんど同じことをしていましたが、わずかな違い
ジョーキング

3

Perl 6、48バイト

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

オンラインでお試しください!

入力を単一の数値に達するまで繰り返しZeckendorf Representationのリストに変換し、シーケンスの長さが4未満かどうかを確認します。

中央のZenckendorf関数は、主にSeanの回答にいくつかの改善を加えたものです。

説明:

{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既にフィボナッチ数です。のシーケンス140140 5 1で、5はフィボナッチ数であるため、trueを返します。のシーケンス3333 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入力用1396入力用の140ためにあるため、Δスタックをチェックする-loop同じままであったことはもちろん、追加の反復のありません、。



2

Retina 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に、\1while の前の値を\1取り、2つの値の合計を取ります。

したがって、できるだけ多くのフィボナッチ数を一致させ、追加しながら追加します。シーケンスの部分和ので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}

前の手順を合計2回実行します。これは、フィボナッチ数の合計に必要なフィボナッチ数の数を取ります。

^1$

数値がひそかにフィボナッチだった場合、結果は1です。


1

パイソン2146の 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()は、指定された数値のZeckendorf表現を整数のリストとして返す再帰関数です。

すべてのフィボナッチ数はg()から1つの項目の長さを返すため、h()はg(n)== 1のg()の長さをチェックします。

編集:nedla2004のおかげで9バイト節約されました。私はラムダが常に最良の解決策ではないことを忘れない...


1
138バイト。ほとんどの場合、変数をg定義できるように関数を作成しましたf(n-1)。カップルその他の変更==<それらが同じであるところ。
nedla2004
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.