フィボナッチ軌道を数える


13

フィボナッチ数列をf k(n)=(f k(n-1)+ f k(n-2))%kとして定義する場合、整数kはモジュロ演算子)に対して、シーケンス(f k(n-1)、f k(n-2))にはk 2個の異なる値しかないため、必然的に周期的です。ただし、このサイクルには通常、可能なすべての値のペアが含まれているわけではないため、2つの開始値f k(0)およびf k(1)に応じて、異なるサイクルが得られる場合があります。たとえば、k = 2の場合、最初の2つの値に応じて、次の4つの可能性があります。

0, 0, 0, 0, 0, 0, 0, 0, 0, ...
0, 1, 1, 0, 1, 1, 0, 1, 1, ...
1, 0, 1, 1, 0, 1, 1, 0, 1, ...
1, 1, 0, 1, 1, 0, 1, 1, 0, ...

シーケンスの周期的性質のため、ここでは、軌道が(0)(0、1、1 )の 2つの基本的に異なるシーケンスのみが実際にあります。k = 3を見てみましょう。

0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ...
0, 1, 1, 2, 0, 2, 2, 1, 0, 1, 1, 2, 0, 2, 2, 1, ...
0, 2, 2, 1, 0, 1, 1, 2, 0, 2, 2, 1, 0, 1, 1, 2, ...
1, 0, 1, 1, 2, 0, 2, 2, 1, 0, 1, 1, 2, 0, 2, 2, ...
1, 1, 2, 0, 2, 2, 1, 0, 1, 1, 2, 0, 2, 2, 1, 0, ...
1, 2, 0, 2, 2, 1, 0, 1, 1, 2, 0, 2, 2, 1, 0, 1, ...
2, 0, 2, 2, 1, 0, 1, 1, 2, 0, 2, 2, 1, 0, 1, 1, ...
2, 1, 0, 1, 1, 2, 0, 2, 2, 1, 0, 1, 1, 2, 0, 2, ...
2, 2, 1, 0, 1, 1, 2, 0, 2, 2, 1, 0, 1, 1, 2, 0, ...

繰り返しますが、2つの異なる軌道しかありません:(0)(0、1、1、2、2、0、2、2、1)

より高いkの場合、より多くの軌道が得られる可能性がありますが、それらは依然として比較的少数のクラスに分類されます。たとえば、k = 4は4つの軌道を生成します(0) (0,1,1,2,3,1) (0、2、2) (0、3、3、2、1、3)及びK = 5 3つの軌道(0)(0、1、1、2、3、0、3、3、1、4、0、4、4、3、2、0、2、2、4、1)および(1、3、4、2)

この課題でのタスクは、与えられたkに対してシーケンスが生成する軌道の数を計算することです。これはOEIS A015134です。以下に、最初の100個の値を示します(k = 1から始まります):

1, 2, 2, 4, 3, 4, 4, 8, 5, 6, 14, 10, 7, 8, 12, 16, 9, 16, 22, 16,
29, 28, 12, 30, 13, 14, 14, 22, 63, 24, 34, 32, 39, 34, 30, 58, 19,
86, 32, 52, 43, 58, 22, 78, 39, 46, 70, 102, 25, 26, 42, 40, 27, 52,
160, 74, 63, 126, 62, 70, 63, 134, 104, 64, 57, 78, 34, 132, 101, 60,
74, 222, 37, 38, 62, 328, 89, 64, 82, 124, 41, 86, 42, 172, 75, 44,
184, 178, 181, 132, 82, 180, 99, 140, 104, 246, 49, 50, 114, 76

必ずk = 11を確認してください。これは、kを超える軌道を生成する最初の入力です。

ルール

正の整数kが与えられ、A015134(k)を出力するはずです。

プログラムまたは関数を作成し、入力を受け取って出力を提供する標準的な方法を使用できます。

任意のプログラミング言語を使用できますが、これらの抜け穴はデフォルトでは禁止されていることに注意してください

これはであるため、バイト単位で測定された最短の有効な回答が勝ちます。


3
これはcodegolf.stackexchange.com/q/26578/194に十分近いため、一方的に閉じることはできませんが、第5票を投じてduとして閉じることにします。
ピーターテイラー

回答:


3

ハスク17 16バイト

Lüȯ€U¡ȯ↔m%⁰∫π2ŀ⁰

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

説明

Lüȯ€U¡ȯ↔m%⁰∫π2ŀ⁰  Implicit input, say n=4.
              ŀ⁰  Lowered range: [0,1,2,3]
            π2    Cartesian second power: [[0,0],[0,1],[1,0],[0,2]..
 üȯ                Deduplicate with respect to this function:
   €U¡ȯ↔m%⁰∫       Arguments are two pairs, say a=[0,2], b=[1,1]
     ¡ȯ            Iterate on a:
           ∫       Cumulative sum,
        m%⁰        take modulo n of each,
       ↔           then reverse: [[0,2],[2,0],[2,2],[0,2],[2,0]..
    U              Cut at first repeated element: [[0,2],[2,0],[2,2]]
   €               Is b in this list? No, so they are distinct in ü.
L                 Number of remaining pairs.


1

Wolfram言語(Mathematica)76 70バイト

Tr[EdgeCycleMatrix[#->{#[[2]],Tr@#~Mod~n}&/@Tuples[Range[n=#]-1,2]]!]&

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

使い方

{{0,0}->{0,0}, {1,0}->{1,1}, ...}一般化フィボナッチ数列の2つの要素が与えられたときに、次のモジュロを見つけるという規則によって与えられたグラフを作成しますn。のEdgeCycleMatrixこのグラフ内のエッジサイクルから入射行列を与えます。行をカウントしたいです。

(同様のタスクを実行するビルトインがいくつかありますが、ConnectedComponentsより長く、FindCycle動作させるために多くの追加の入力が必要です。さらに、EdgeCycleMatrix他の2つのようなおかしな形ではない長方形の配列があります。 )

行列の行をカウントするには、エントリの階乗を使用してすべての行列に変換し、トレースを取得します。(各サイクルには少なくとも1つのエッジが含まれているため、少なくとも行と同じ数の列があります。したがって、列ではなく行をカウントします。)


1

MATL38 36バイト

:qt!J*+le"@GU:"t&Zjwy+G\J*+hu]S]Xhun

オンラインでお試しください!入力を超えるとオンラインコンパイラでタイムアウトします7

説明

このコードは、フィボナッチ数列の虚数部が新しい項で、実数部が前の項である複素数で軌道を定義します。各複素数値は、シーケンスの状態をエンコードします。つまり、a+jb次の値がとして計算されb+j(a+b)ます。

可能な開始値はa+jb、でありabである[0, 1, ..., k-1]。各開始値に対して、コードはk^2時間を繰り返します。実際には、コードを短くするために、各反復がすべてに適用されますこれまでに累積 so値に、結果は重複排除されます(いずれにしても最後に必要になります)。最後の反復の後、重複排除された複素数値のベクトルが(絶対値で、次に角度で)ソートされます。これにより、各軌道に「署名」が与えられます。

プログラムの最後に、署名がセル配列に収集されます。一意の署名の数が望ましい出力です。

:q          % Implicit input: k. Push row vector [0, 1, ..., k-1]
t!          % Duplicate, transpose: gives column vector [0; 1; ...; k-1]
J*+         % Multiply by 1j, add with broadcast. Gives a k × k matrix of
            % values a+jb with a, b in [0, 1, ..., k-1]
le          % Linearize into a row vector
"           % For each c in that vector
  @         %   Push c
  GU:"      %   Do the following k^2 times
    t&Zj    %     Duplicate and split into real and imaginary parts: a, b
    wy+     %     Swap, duplicate, from below, add: transforms a, b into
            %     b, a+b. This is the basic step in the Fibonacci sequence
            %     In subsequent iterations a and b may be vectors instead
            %     of numbers, as they include all values obtained so far
    G\      %     Modulo k, element-wise
    J*+     %     Times 1j, add. Gives the next complex number for each of
            %     the complex numbers so far
    hu      %     Append to values so far and deduplicate. This may extend
            %     the vector of complex numbers
  ]         %   End
  S         %   Sort
]           % End
Xh          % Collect entire stack into a cell array
u           % Deduplicate
n           % Number of entries. Implicit display

1

Haskell196191バイト

import Data.List
o(a:b)=1+o[x|x<-b,not$(0<$a)==(0<$x)&&isInfixOf a(x++x)]
o _=0
k#(a,b)=(b,mod(a+b)k)
p!(a:b)|elem a p=fst<$>p|r<-p++[a]=r!b
f k=o[[]!iterate(k#)(a,b)|a<-[0..k-1],b<-[0..k-1]]

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

これはおそらく改善される可能性があります。特に、誰かがisInfixOfインポートを回避および削除する方法を見つけられる場合。

基本的な考え方は、「状態」のリスト(前の2つの値を含むタプル)を生成して、いつサイクルを開始するかを確認することです。次に、各軌道が前の軌道と異なるかどうかを確認します(実際には逆に機能しますが、言葉で表現するのは困難です)。軌道が同じであるかどうかを確認するために、長さが同じであるかどうか、および一方がそれ自体と連結された他方に適合するかどうかを確認します。たとえば[0,2,2][2,2,0]:両方の長さは3で、連続したサブシーケンスとして[0,2,2,0,2,2]含ま[2,2,0]れています。それが絶対確実かどうかはわかりませんが、うまくいくようです。

編集:5バイトを削除するLaikoniに感謝!これらのヒントをもっと読むべきでした。


1
このヒントを使用して回避できるようですlength。別のバイトをして保存することができます!|r<-p++[a]=r!b
ライコニ

0

JavaScript(ES6)、337 335バイト

Ω(k ^ 3)ブルートフォースアルゴリズムでごめんなさい。

(k,x=o=0,u=[],s=(q,w,v,j=d=0)=>{while(j++<v)d|=q.reduce((a,b,i)=>a&=b==w[(i+j)%v],1);return d})=>{for(;x<k;x++)for(y=0;y<k;y++){l=2;r=[x,y];do{r.push((c=(d=r[(l+=2)-3])+r[l-4])%k,(c+d)%k)}while(!(t=r.slice(0,h=l/2)).reduce((a,b,i)=>a&=b==r[i+h],1));if(!u.reduce((q,z)=>q|=(t.length-(a=z.length)?0:s(t,z,a)),0)){o++;u.push(t)}}return o}

パフォーマンス... A015134(k = 50を超えるもの)を計算していたとき、TIOの60秒の制限を超えていました。

var g=(k,x=o=0,u=[],s=(q,w,v,j=d=0)=>{while(j++<v)d|=q.reduce((a,b,i)=>a&=b==w[(i+j)%v],1);return d})=>{for(;x<k;x++)for(y=0;y<k;y++){l=2;r=[x,y];do{r.push((c=(d=r[(l+=2)-3])+r[l-4])%k,(c+d)%k)}while(!(t=r.slice(0,h=l/2)).reduce((a,b,i)=>a&=b==r[i+h],1));if(!u.reduce((q,z)=>q|=(t.length-(a=z.length)?0:s(t,z,a)),0)){o++;u.push(t)}}return o}

for (var ix = 1; ix <= 15; ix++)
 console.log(`A015134(${ix}) = ${g(ix)}`);

説明(ゴルフなし)

function CheckIfSameOrbit(Array_1, Array_2, Length) { // Checks if the orbits are equal
  var d = false, j = 0;                               // Assume both have same length
  while (j < v) {                                     // Checks for different startings
    j++;                                                
    d |= Array_1.reduce(function(Acc, Item, Index) {  // Element-by-element comparison
      Acc &= Item == w[(Index + j) % v], 1);                     
    });                                               // Return true if any starting
  }                                                   // point makes two orbits identical
}

function A015134(k) {                                 // Main Program
  var o = 0, u = [];                                    
  for (var x = 0; x < k; x++) {                       // Checks different pairs of (x, y)
    for (var y = 0; y < k; y++) {
      var l = 2, r = [x, y], h = 1, t;
      do {                                            // Find until a complete orbit is
        l += 2;                                       // found (except for (0, 0) case)
        h = l / 2;
        var d = r[l - 3], c = r[l - 3] + r[l - 4];
        r.push(c % k, (c + d) % k);
        t = r.slice(0, h);
      }                                                 
      while (!t.reduce(function(Acc, Item, Index) {   // Which is, if 2 identical copies
        Acc &= Item == r[Index + h];                  // of the orbit are calculated
      }, 1));

      if (!u.reduce(function(Acc, Item) {             // If the orbit is a new one
        var a = Item.length;
        Acc |= (t.length - a ? 0 : s(t, Item, a));
      }, 0)) {
        o++;                                          // Increment the counter, and
        u.push(t);                                    // record it to the list
      }
    }
  }
  return o;                                           // Ultimately return the counter;
}



0

JavaScript(ES6)、102バイト

k=>F=(a=0,b=0,C=0,q)=>q?F[q=[a,b%=k]]?0:1|F(b,a+b,C,F[q]=1):b<k?F(a,b+1,C+F(a,b,C,1)):++a<k?F(a,0,C):C

結果を返す関数を返します。さらに3バイトの場合、結果を直接返すことができます。

k=>(F=(a,b,C,q)=>q?F[q=[a,b%=k]]?0:1|F(b,a+b,C,F[q]=1):b<k?F(a,b+1,C+F(a,b,C,1)):++a<k?F(a,0,C):C)(0,0,0)

どちらも時間の複雑さはO(n 2)です。


0

Python 2、214バイト

def h(k):
 R=[]
 for p in[[i/k,i%k,(i/k+i%k)%k]for i in range(k*k)]:
	while p[:2]!=p[-2:]:
		p.append(sum(p[-2:])%k)
	p=p[:-2]
	if not any([p==x[i:]+x[:i]for i in range(len(p))for x in R]):R.append(p)
 print len(R)

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

それは非常に効率的ではありませんが、私ができる最高のゴルフです。

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