计数斐波纳契轨道


13

如果将类斐波那契数列定义为f k(n)=(f k(n-1)+ f k(n-2))%k,则对于某些整数k(其中是模运算符),该序列因为(f k(n-1),f k(n-2))只有k 2个不同的值,所以它将必定是循环的。但是,此周期通常并不包括所有可能的值对,因此根据两个初始值f k(0)f k(1),我们可能会得到不同的周期。例如,对于k = 2,根据前两个值,我们有以下四种可能性:

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)。让我们看一下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, ...

同样,只有两个不同的轨道:(0)(0,1,1,2,0,2,2,1)

对于更高的k,我们可能会获得更多的轨道,但它们仍然属于相对较少的几类。例如K = 4倍的产率的四个轨道(0) (0,1,1,2,3,1) (0,2,2) (0,3,3,2,1,3)ķ = 5三个轨道(0) 0,1,1,2,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足够接近,我不会单方面关闭它,但我将以第五次投票将其关闭。
彼得·泰勒

Answers:


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}, ...}给定广义斐波纳契数列的两个元素,找到下一个模n。的EdgeCycleMatrix给出了从循环以在该图中边的关联矩阵; 我们要计算其行数。

(有许多内置程序执行相似的任务,但是ConnectedComponents更长,并且FindCycle需要很多额外的输入才能使其工作。此外,它EdgeCycleMatrix是一个矩形数组,形状不像其他两个矩形,但以后会有所帮助。 )

要计算矩阵的行数,我们采用条目的阶乘将其转换为所有矩阵,然后进行跟踪。(每个循环至少包含一个边,因此至少有与行一样多的列-因此,这是对行而不是列进行计数。)


1

MATL38 36字节

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

在线尝试!在线编译器中输入超过超时7

说明

该代码以复数的形式定义了轨道,其中虚部是新项,实部是斐波那契数列中的前项。每个复数值编码序列的状态。即,给定下a+jb一个值计算为b+j(a+b)

可能的初始值是a+jbab[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

Haskell中196个 191字节

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和删除导入的方法。

基本思想是生成一个“状态”列表(包含前两个值的元组),以查看何时开始循环。然后,我们检查每个轨道是否不同于其先前的轨道(确实以相反的方式起作用,但是很难用语言表达出来)。为了检查轨道是否相同,我们检查长度是否相同以及一个轨道是否适合另一个与其自身相连的轨道。例如[0,2,2][2,2,0]:的长度均为3,并且[0,2,2,0,2,2]包含[2,2,0]为连续的子序列。我不确定它是否万无一失,但它似乎有效。

编辑:感谢Laikoni脱掉了5个字节!我应该阅读更多这些技巧。


1
看来您可以使用此技巧来避免length。另一个字节可以保存在!|r<-p++[a]=r!b
Laikoni '11

0

JavaScript(ES6),337335字节

对不起,Ω(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)

在线尝试!

这不是很有效,但是这是我能做的最大的事情。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.