Conteggio delle orbite di Fibonacci


13

Se definiamo una sequenza simile a Fibonacci come f k (n) = (f k (n-1) + f k (n-2))% k , per alcuni interi k (dove % è l'operatore modulo), la sequenza sarà necessariamente ciclico, perché ci sono solo k 2 valori diversi per (f k (n-1), f k (n-2)) . Tuttavia, questo ciclo di solito non comprende tutte le possibili coppie di valori, così seconda delle due valori iniziali f k (0) ed f k (1) , si potrebbe ottenere diversi cicli. Ad esempio, per k = 2, abbiamo le seguenti quattro possibilità, a seconda dei primi due valori:

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, ...

A causa della natura ciclica delle sequenze, in realtà ci sono solo due sequenze sostanzialmente diverse qui, con orbite (0) e (0, 1, 1) . Diamo un'occhiata a 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, ...

Ancora una volta, ci sono solo due orbite diverse: (0) e (0, 1, 1, 2, 0, 2, 2, 1) .

Per k più alti potremmo avere più orbite, ma cadranno comunque in un numero relativamente piccolo di classi. Ad esempio k = 4 produce le quattro orbite (0) , (0,1,1,2,3,1) , (0, 2, 2) , (0, 3, 3, 2, 1, 3) e k = 5 le tre orbite (0) , (0, 1, 1, 2, 3, 0, 3, 3, 1, 4, 0, 4, 4, 3, 2, 0, 2, 2, 4, 1) e (1, 3, 4, 2) .

Il tuo compito in questa sfida è calcolare quante orbite genera la sequenza per un dato k . Questo è OEIS A015134 . Ecco i primi 100 valori (a partire da 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

Assicurati di controllare k = 11 , che è il primo input che produce più di k orbite.

Regole

Ti viene dato un numero intero positivo k e dovresti visualizzare A015134 (k) .

È possibile scrivere un programma o una funzione e utilizzare uno dei metodi standard per ricevere input e fornire output.

È possibile utilizzare qualsiasi linguaggio di programmazione , ma si noti che queste scappatoie sono vietate per impostazione predefinita.

Questo è , quindi la risposta valida più breve - misurata in byte - vince.


3
Questo è abbastanza vicino a codegolf.stackexchange.com/q/26578/194 che non lo chiuderò unilateralmente ma darei il 5 ° voto per chiudere come duplicato.
Peter Taylor,

Risposte:


3

Buccia , 17 16 byte

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

Provalo online!

Spiegazione

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 Language (Mathematica) , 76 70 byte

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

Provalo online!

Come funziona

Costruiamo il grafico dato dalle regole {{0,0}->{0,0}, {1,0}->{1,1}, ...}che, dati due elementi di una sequenza di Fibonacci generalizzata, trovano il modulo successivo n. IlEdgeCycleMatrix dà la matrice di incidenza dai cicli ai bordi in questo grafico; vogliamo contare le sue file.

(Ci sono un certo numero di built-in che svolgono un compito simile, ma ConnectedComponentssono più lunghi e hanno FindCyclebisogno di molti input extra per farlo funzionare. Inoltre, EdgeCycleMatrixc'è un array rettangolare, non a forma di divertente come gli altri due, che aiuta in seguito. )

Per contare le righe della matrice, prendiamo il fattoriale delle voci per trasformarlo in una matrice di tutte, quindi prendiamo la traccia. (Ogni ciclo contiene almeno un bordo e quindi ci sono almeno tante colonne quante righe - quindi questo conta le righe e non le colonne.)


1

MATL , 38 36 byte

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

Provalo online! Timeout nel compilatore online per input in eccesso7 .

Spiegazione

Il codice definisce le orbite in termini di numeri complessi, in cui la parte immaginaria è la nuovo termine e la parte reale è il termine precedente nella sequenza di Fibonacci. Ogni valore complesso codifica lo stato della sequenza. Vale a dire, dato a+jbil valore successivo viene calcolato comeb+j(a+b) .

I possibili valori iniziali sono a+jbcon a, bin [0, 1, ..., k-1]. Per ogni valore iniziale, il codice scorre più k^2volte. In realtà, per ridurre il codice, ogni iterazione viene applicata a tutti valori accumulati finora e i risultati vengono deduplicati (che sarebbe comunque necessario alla fine). Dopo l'ultima iterazione, il vettore dei valori complessi deduplicati viene ordinato (per valore assoluto, quindi per angolo). Questo dà una "firma" per ogni orbita.

Alla fine del programma, le firme vengono raccolte in un array di celle. Il numero di firme uniche è l'output desiderato.

: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 byte

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]]

Provalo online!

Questo potrebbe probabilmente essere migliorato. Soprattutto se qualcuno riesce a trovare un modo per evitareisInfixOf e rimuovere l'importazione.

L'idea di base è quella di generare un elenco di "stati" (tuple contenenti i due valori precedenti) per vedere quando inizia a scorrere. Quindi controlliamo se ogni orbita è diversa dai suoi predecessori (funziona davvero al contrario, ma è difficile da esprimere a parole). Per verificare se le orbite sono uguali, controlliamo se la lunghezza è la stessa e se una si adatta all'altra concatenata con se stessa. Ad esempio [0,2,2], [2,2,0]: lunghezza di entrambi è 3 e [0,2,2,0,2,2]contiene [2,2,0]come sottosequenza continuo. Non sono sicuro che sia infallibile ma sembra funzionare.

EDIT: grazie a Laikoni per il decollo di 5 byte! Avrei dovuto leggere più di quei suggerimenti.


1
Sembra che tu possa usare questo suggerimento per evitare length. Un altro byte può essere salvato !con |r<-p++[a]=r!b.
Laikoni,

0

JavaScript (ES6), 337 335 byte

Ci scusiamo per l'algoritmo Ω (k ^ 3) della forza bruta.

(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}

Le prestazioni ... Quando stavo calcolando A015134 (qualcosa oltre k = 50) ha superato il limite degli anni '60 su TIO.

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)}`);

Spiegazione (Ungolfed)

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 byte

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

Restituisce una funzione che restituisce il risultato. Per altri 3 byte possiamo far sì che restituisca direttamente il risultato:

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)

Entrambi hanno complessità temporale O (n 2 ).


0

Python 2 , 214 byte

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)

Provalo online!

Non è molto efficiente ma è il più golf che potessi fare.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.