Числа Лукаса-Начі


19

Фон

Більшість усіх знайомі з числами Фібоначчі F(n) :

0, 1, 1, 2, 3, 5, 8, 13, 21 ...

Вони утворені функцією рекурсії F(n) = F(n-1) + F(n-2)з F(0)=0і F(1)=1. A000045

Тісно пов'язана послідовність номерів Лукаса L(m) :

2, 1, 3, 4, 7, 11, 18, 29 ...

Вони утворені функцією рекурсії L(m) = L(m-1) + L(m-2)з L(0)=2і L(1)=1. A000032

Ми можемо чергувати дві послідовності на основі парних / непарних індексів, з побудовою,
A(x) = F(x)якщо x mod 2 = 0і A(x) = L(x)інше. Наприклад, A(4)дорівнює F(4)з 4 mod 2 = 0. Ми будемо називати цю послідовність в Lucas-nacci Числа , A(x):

0, 1, 1, 4, 3, 11, 8, 29, 21, 76 ...

Це може бути сформовано з допомогою функції рекурсії A(x) = 3*A(x-2) - A(x-4)з A(0)=0, A(1)=1, A(2)=1і A(3)=4. A005013

Виклик

Задавши введення n, виведіть послідовність n+1чисел до та включаючи, A(n)як описано вище. Виграє найменше байт (або еквівалентів байтів, наприклад, для LabVIEW , визначених індивідуально на Meta).

Вхідні дані

Єдине невід'ємне ціле число n.

Вихідні дані

Список номерів, які відповідають послідовності чисел Лукаса-Начі від A(0)до A(n). Список повинен бути у послідовному порядку, як описано вище.

Правила

  • Застосовуються стандартні правила коду-гольфу та обмеження лазівки .
  • Застосовуються стандартні правила введення / виводу .
  • Номер введення може бути у будь-якому підходящому форматі: одинарний або десятковий, зчитувати з STDIN, аргумент функції або командного рядка тощо - на ваш вибір.
  • Вихід може бути надрукований в STDOUT або повернутий в результаті виклику функції. Якщо вони надруковані, повинні бути включені відповідні роздільники для розмежування чисел (розділені пробілами, розділені комами тощо).
  • Крім того, якщо вихід у режим STDOUT, навколишній пробіл, трейлінг нового рядка тощо не є обов'язковим.
  • Якщо вхід є не цілим чи від'ємним цілим числом, програма може зробити що-небудь або нічого, оскільки поведінка не визначена.

Приклади

Input -> Output
0 -> 0
5 -> 0, 1, 1, 4, 3, 11
18 -> 0, 1, 1, 4, 3, 11, 8, 29, 21, 76, 55, 199, 144, 521, 377, 1364, 987, 3571, 2584

Чи вважається новий рядок прийнятим роздільником?
corsiKa

@corsiKa Звичайно, це добре.
AdmBorkBork

Відповіді:


9

Желе, 12 байт

;2U+¥Ð¡-,1ZḢ

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

Фон

Ми можемо продовжити F і L до -1, визначивши F (-1) = 1 і L (-1) = -1. Це узгоджується з рекурсивною функцією.

Наша програма починається з

-1  1
 0  2

На кожному кроці, щоб сформувати наступну пару, ми перевертаємо останню пару і додаємо її до передостанньої пари. Наприклад:

[0, 2] U+¥ [-1, 1] -> [2, 0] + [-1, 1] -> [1, 1]

Якщо продовжити цей процес ще на кілька кроків, ми отримаємо

-1  1
 0  2
 1  1
 1  3
 4  2
 3  7
11  5

Послідовність Лукаса-Начі - це просто лівий стовпчик.

Як це працює

;2U+¥Ð¡-,1ZḢ  Niladic link. No implicit input.
              Since the link doesn't start with a nilad, the argument 0 is used.

;2            Concatenate the argument with 2, yielding [0, 2].
       -,1    Yield [-1, 1]. This is [L(-1), F(-1)].
    ¥         Create a dyadic chain of the two atoms to the left:
  U             Reverse the left argument.
   +            Add the reversed left argument and the right one, element-wise.
     С       For reasons‡, read a number n from STDIN.
              Repeatedly call the dyadic link U+¥, updating the right argument with
              the value of the left one, and the left one with the return value.
              Collect all intermediate results.
          Z   Zip the list of results, grouping the first and seconds coordinates.
           Ḣ  Head; select the list of first coordinates.

С заглядає в два лінки зліва: 2і U+¥. Оскільки крайній лівий край - це вушко, воно не може бути тілом петлі. Тому U+¥використовується як тіло, і число зчитується із введення. Оскільки аргументів командного рядка немає, це число зчитується з STDIN.


2
У мене складається враження, що ти займаєшся подібними речами (гольф у Джеллі) на життя. Що мене жахає.
Draco18s

24
Якщо хтось розбирається, як заробляти на гольф (код) на життя, будь ласка, напишіть мені в чаті. Просити друга ...
Мартін Ендер

2
Отже, ви просто обчислюєте обидві послідовності, але реверсуєте на кожному кроці, що ефективно перемикається між послідовностями.
Ніл

1
@Neil Так. Це дозволяє уникнути переплетення послідовностей після цього, що трохи довше.
Денніс

6

CJam, 21 20 байт

Завдяки Sp3000 за збереження 1 байта.

TXX4ri{1$3*4$-}*?;]p

Перевірте це тут.

Пояснення

Просто використовує повторення, вказане в специфікації виклику.

TXX4 e# Push 0 1 1 4 as base cases.
ri   e# Read input and convert to integer N.
{    e# Run this N times...
  1$ e#   Copy a(n-2).
  3* e#   Multiply by 3.
  4$ e#   Copy a(n-4).
  -  e#   Subtract.
}*
?;   e# Discard the last three values, using a ternary operation and popping the result.
]p   e# Wrap the rest in an array and pretty-print it.

1
Хто (чи що) Sp3000, якому ви дякуєте за кожну відповідь?
CJ Dennis


5
@CJDennis Деякі кажуть, що він найбільший гольфіст Python, який коли-небудь жив. Деякі кажуть, що він живе в усамітненій каюті на вершині гори, побудованій з мінімальної кількості колод. Деякі кажуть, що він - це голос у задній частині нашої голови, який нас нудить, коли ми розміщуємо рішення, які можна подати в гольф. Але більшість із нас просто кажуть, що він користувач, з профілем якого Мартін пов’язаний.
Мего

6

Perl 6, 42 байти

{(0,1,1,4,{$^b;$^d;3*$^c-$^a}...*)[0..$_]}

використання

> my &f = {(0,1,1,4,{$^b;$^d;3*$^c-$^a}...*)[0..$_]}
-> ;; $_? is raw { #`(Block|184122176) ... }
> f(0)
(0)
> f(5)
(0 1 1 4 3 11)
> f(18)
(0 1 1 4 3 11 8 29 21 76 55 199 144 521 377 1364 987 3571 2584)

1
Найясніша лямбда, яку я придумав,{( (0,1,*+*...*) Z (2,1,*+*...*) ).flat.rotor( 1=>2, 1=>0 )[ 0..$_ ].flat}
Бред Гілберт b2gills

З огляду на , що точне формулювання « з урахуванням п», ви можете зберегти байти з: (0,1,1,4,{$^b;$^d;3*$^c-$^a}...*)[^(n+1)].
raiph

6

Haskell, 59 , 57 , 56 , 52 , 51 байт

l a=2*mod a 2:scanl(+)1(l a)
f n=[l i!!i|i<-[0..n]]

Визначення серії адаптовано з цієї відповіді .

Менше гольфу:

fibLike start = start : scanl (+) 1 (fibLike start)
whichStart i = (2*mod i 2)
lucasNacci i = fibLike (whichStart i) !! i
firstN n = [ lucasNacci i | i <- [0..n]]

fibLike startдає нескінченний список, визначається: f(0)=start, f(1)=1, f(n)=f(n-1) + f(n-2). whichStart iповертає 2 для непарного введення (серія Лукаса) або 0 для парного (серія Фібоначчі). lucasNacci iдає i-е число Лукаса-Начі. firstN nкарти над списком.

Один байт збережений Бумерангом.


1
Я думаю , що ви можете отримати ще один байт, переміщаючи 2*mod i 2в lто ви можете видалити дужки. Подобається це:l a=2*mod a 2:scanl(+)1(l a) іf n=[l i!!i|i<-[0..n]]
Базиль-Генрі

@Boomerang Yup, це працює. Дякую
Майкл Кляйн

5

ES6, 65 байт

n=>[...Array(n)].map(_=>a.shift(a.push(a[2]*3-a[0])),a=[0,1,1,4])

Використовується відношення рецидивів, наведене у запитанні.


5

Сітківка , 70 62 59 байт

1
¶$`1
m`^(11)*1$
$&ff
m`$
 f
+`1(f*) (f*)
$2 $2$1
 f*

f
1

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

  • Вхід знаходиться в одинарній базі, n 1s.
  • 1? $`¶- Створіть рядок для кожного числа від 0 до n : , 1, 11, 111, 1111, ...
  • m`^(11)*1$ $&ff- Додайте ffнепарні рядки. Це запустить функцію з L (0) = 2.
  • m`$  f- Додайте  fдо всіх рядків (відмітьте пробіл). Це визначає функцію з 0 і 1 для чисел Фібоначчі та 2 та 1 для чисел Лукаса.
  • +`1(f*) (f*) $2 $2$1 - Петля: обчисліть F (n + 1) = F (n) + F (n-1), поки є ще 1s.
  •  f*   - Видаліть F (n + 1) з кінця кожного рядка.
  • Замініть fs назад на 1s. Якщо це не потрібно, і ми можемо залишитися з fs, довжина становить всього 55 байт.

5

Oracle SQL 11.2, 218 216 201 байт

WITH v(a,b,c,d,i)AS(SELECT 0,1,1,4,3 FROM DUAL UNION ALL SELECT b,c,d,3*c-a,i+1 FROM v WHERE i<:1)SELECT SIGN(LEVEL-1) FROM DUAL WHERE LEVEL-1<=:1 CONNECT BY LEVEL<4UNION ALL SELECT d FROM v WHERE:1>2;

Без гольфу

WITH v(a,b,c,d,i) AS 
(
  SELECT 0,1,1,4,3 FROM DUAL 
  UNION ALL 
  SELECT b,c,d,3*c-a,i+1 FROM v WHERE i<:1
)
SELECT SIGN(LEVEL-1) FROM DUAL WHERE LEVEL-1<=:1 CONNECT BY LEVEL<4
UNION ALL SELECT d FROM v WHERE:1>2;

Мені вдалося набрати кілька байтів, використовуючи (зловживаючи?) Функцію SIGN для генерації перших 3 елементів послідовності.


3

Japt, 25 22 21 байт

Uò £MgXf2)+X%2*Mg°X)r

Перевірте це в Інтернеті!

Фон

Дещо складно створити послідовність Фібоначчі в Japt, але у нас є вбудований, Mgщоб зробити це за нас. Однак це дає нам лише послідовність Фібоначчі, а не послідовність Лукаса. Ми можемо виконати послідовність Лукаса досить легко, використовуючи цей трюк:

N    F(N-1)  F(N+1)  F(N-1)+F(N+1)
0    1       1       2
1    0       1       1
2    1       2       3
3    1       3       4
4    2       5       7
5    3       8       11
6    5       13      18
7    8       21      29

Як бачимо, F(N-1) + F(N+1)рівний L(N)для всіх N. Однак, оскільки нам потрібні лише номери Лукаса на непарних показниках, ми можемо поєднати дві формули в одну:

N    N-N%2  N+N%2    F(N-N%2)  F(N+N%2)*(N%2)  F(N-N%2)+F(N+N%2)*(N%2)
0    0      0        0         0               0
1    0      2        0         1               1
2    2      2        1         0               1
3    2      4        1         3               4
4    4      4        3         0               3
5    4      6        3         8               11
6    6      6        8         0               8
7    6      8        8         21              29

Як це працює

Uò £  MgX-1 +X%2*Mg° X)r
Uò mX{MgX-1 +X%2*Mg++X)r

             // Implicit: U = input integer
Uò mX{       // Create the inclusive range [0..U], and map each item X to:
MgXf2)+      //  Floor X to a multiple of 2, calculate this Fibonacci number, and add:
+X%2*Mg++X)  //  Calculate the (X+1)th Fibonacci number and multiply by X%2.
)r           //  Round the result. (The built-in Fibonacci function returns
             //  a decimal number on higher inputs.)

3

Математика, 52 51 байт

If[#>2,3#0[#-2]-#0[#-4],#-If[#>1,1,0]]&/@0~Range~#&

Дуже схожа на думку Мартіна вище, я провів деякий час, намагаючись знайти коротший спосіб визначення "базових випадків" функції. Поліноміальна інтерполяція була погруддю, тому я взявся за це, використовуючи розширення на негативи, щоб дати досить коротке визначення.


2

Математика, 56 байт

f@0=0
f@1=f@2=1
f@3=4
f@n_:=3f[n-2]-f[n-4];
f/@0~Range~#&

Дуже відверта реалізація. Визначає функцію помічника, fа потім оцінює неназвану функцію, яка застосовується fдо діапазону для отримання всіх результатів. Це відчуває себе непотрібно громіздким.

Здається, що одна неназвана функція на один байт довше:

Switch[#,0,0,1,1,2,1,3,4,_,3#0[#-2]-#0[#-4]]&/@0~Range~#&

2

MATL , 17 18 байт

0ll4i:"y3*5$y-](x

Майже прямий переклад відповіді Мартіна CJam .

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

0ll4       % push first four numbers: 0,1,1,4
i:         % input n and generate array [1,2,...,n]
"          % for loop. Repeat n times
  y        % copy second-top element from stack
  3*       % multiply by 3
  5$y      % copy fifth-top element from stack
  -        % subtract. This is the next number in the sequence
]          % end loop
(x         % indexing operation and delete. This gets rid of top three numbers

2

Брахілог , 51 байт

:0re{:4<:[0:1:1:4]rm!.|-4=:1&I,?-2=:1&*3-I=.}w,@Sw\

Це приймає число як вхідне і друкує для STDOUT списку, з пробілами, що розділяють кожне число.

Пояснення

§ Main predicate

:0re{...}               § Enumerate integers between 0 and the Input, pass the integer 
                        § as input to sub-predicate 1      
         w,@Sw          § Write sub-predicate 1's output, then write a space
              \         § Backtrack (i.e. take the next integer in the enumeration)


§ Sub-predicate 1

:4<                     § If the input is less than 4
   :[0:1:1:4]rm!.       § Then return the integer in the list [0,1,1,4] at index Input

|                       § Else

-4=:1&I,                § I = sub_predicate_1(Input - 4)
        ?-2=:1&*3-I=.   § Output = sub_predicate_1(Input - 2) * 3 - I

Розріз !у першому правилі підказка 1 необхідний, щоб, коли ми повертаємося назад ( \), ми не опинилися у нескінченному циклі, де інтерпретатор спробує друге правило для введення менше 4.



2

Groovy, 50 байт

x={a,b=0,c=1,d=1,e=4->a<0?:[b,x(a-1,c,d,e,3*d-b)]}

Це визначає функцію x, яка приймає n як перший аргумент і має базовий регістр перших чотирьох чисел у послідовності Fibocas як аргументи за замовчуванням для решти функції.

a ось n. b, c, d і e - наступні чотири елементи в послідовності.

Він зменшує n і повторюється, поки n не дорівнює нулю - коли він повторюється, він додає до кінцевого значення повернення перший елемент у його поточній послідовності. Нові значення для наступних чотирьох елементів у послідовності задаються рекурсивному виклику - останні три елементи зміщуються на перші три, а новий четвертий елемент формується з двох попередніх елементів за допомогою 3 * db.

Він розмежовує нові значення за допомогою вкладки списку, оскільки groovy може повернути кілька значень, додавши їх до списку-- тому кожен виклик повертає поточний перший елемент та результат рекурсії, який буде його власним списком.



1

Пілони , 19

Це досить прямий переклад підходу Мартіна.

0114{@-4@-33*-,i}=4

Як це працює:

0114    # Push 0, 1, 1, 4 to the stack.
{       # Start a for loop.
 @-4    # Get the stack element at index -4
 @-3    # Get the stack element at index -3
 3      # Push 3 to the stack.
 *      # Multiply the top two elements of the stack.
 -      # Subtract the top two elements of the stack.
  ,     # Switch to loop iterations.
 i      # Get command line args.
}       # End for loop.
=4      # Discard the top 4 elements of the stack.

1

DUP , 32 байти

[a:0 1$4[a;1-$a:][1ø3*4ø-]#%%]

Try it here!

Анонімна лямбда, яка залишає послідовність чисел на стеку. Використання:

8[a:0 1$4[a;1-$a:][1ø3*4ø-]#%%]!

Пояснення

[                              {start lambda}
 a:                            {save input number to a}
   0 1$4                       {base cases to get us started}
        [       ][       ]#    {while loop}
         a;1-$a:               {a--, check if a>0}
                  1ø3*4ø-      {3*stack[n-2]-stack[n-4]}

                           %%  {discard top 2 stack items}
                             ] {end lambda}

1

Python 2, 71 байт

def a(n,x=0,y=1,z=2,w=1,p=0):
 if~n:print[x,z][p];a(n-1,y,x+y,w,z+w,~p)

Це, безумовно, здається занадто довгим. Однак я був задоволений тим, що мені вдалося скористатися розрядним notоператором ... двічі. Один раз як паритет перевертається туди-сюди, а раз припиняє рекурсію, колиn досягає -1.

Змінна pзавжди буде або 0або -1, так що вона буде чергуватися між записами 0або -1списком. (Вибір запису -1списку Python означає вибір останнього елемента.)


1

Мета + програмування шаблонів на C ++, 130 байт

template<int X>struct L{enum{v=3*L<X-2>::v-L<X-4>::v};};
#define D(X,A) template<>struct L<X>{enum{v=A};};
D(0,0)D(1,1)D(2,1)D(3,4)

Рекурсивні визначення так чи інакше кричать на C ++ TMP, використання:

L<x>::v

з xтим, що A(x)ти любиш.

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