Підрахунок орбіт Фібоначчі


13

Якщо ми визначимо послідовність, що нагадує Фібоначчі, як f k (n) = (f k (n-1) + f k (n-2))% k , для деякого цілого k (де % - оператор модуля), послідовність обов'язково буде циклічним, оскільки є лише k 2 різних значень для (f k (n-1), f k (n-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) і k = 5 три орбіти (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-й голос, щоб закрити як дупер.
Пітер Тейлор

Відповіді:


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

Мова Вольфрама (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

MATL , 38 36 байт

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

Спробуйте в Інтернеті! Час вичерпується в онлайн-компіляторі, щоб перевищити вхід7.

Пояснення

Код визначає орбіти з точки зору складних чисел, де уявна частина - це новий термін, а реальна частина - попередній термін у послідовності Фібоначчі. Кожне комплексне значення кодує стан послідовності. А саме, задане a+jbнаступне значення обчислюється як b+j(a+b).

Можливі вихідні значення знаходяться a+jbв a, bв [0, 1, ..., k-1]. Для кожного початкового значення код повторює k^2час. Власне, щоб зробити код коротшим, кожна ітерація застосовується до всіх накопичених до цього часу значень, а результати дедублюються (що було б потрібно в кінці кінців). Після останньої ітерації вектор дедупльованих комплексних значень сортується (за абсолютним значенням, потім за кутом). Це дає "підпис" для кожної орбіти.

В кінці програми підписи збираються в масив комірок. Кількість унікальних підписів - бажаний вихід.

: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]як безперервну підпослідовності. Я не впевнений, чи це надійно, але це, здається, працює.

EDIT: дякую Лайконі за зняття 5 байт! Я мав би прочитати більше цих порад.


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), це перевищило обмеження 60-х для 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)}`);

Пояснення (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 байти

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)

Спробуйте в Інтернеті!

Це не дуже ефективно, але це найголовніший гольф, який я міг зробити.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.