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


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.

Выход

Список чисел, которые соответствуют подпоследовательности чисел Lucas-nacci от 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 Деннис


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]]
Вот так

@ Бумеранг Да, это работает. Спасибо
Майкл Кляйн

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 1 с.
  • 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), пока еще есть 1 с.
  •  f*   - Удалить F (n + 1) с конца каждой строки.
  • Заменить fs обратно на 1 с. Если это не нужно, и мы можем остаться с 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;

Un-golfed

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возможность сделать это за нас. Однако это дает нам только последовательность Фибоначчи, а не последовательность Лукаса. Мы можем выполнить последовательность Lucas довольно легко, используя этот трюк:

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

Mathematica, 52 51 байт

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

Идея, очень похожая на рассмотренную Мартином выше, я потратил некоторое время, пытаясь найти более короткий способ определения «базовых вариантов» для функции. Полиномиальная интерполяция была неудачей, поэтому я пошел на это, используя расширение в негативы, чтобы получить довольно короткое определение.


2

Mathematica, 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\

Он принимает число в качестве ввода и печатает для вывода списка, с пробелами, разделяющими каждое число.

объяснение

§ 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 в качестве аргументов по умолчанию для остальной части функции.

а вот п. b, c, d и e - следующие четыре элемента в последовательности.

Он уменьшает n и повторяется до тех пор, пока n не станет меньше нуля - когда он повторяется, он добавляет к окончательному возвращаемому значению первый элемент в своей текущей последовательности. Новые значения для следующих четырех элементов в последовательности передаются рекурсивному вызову - последние три элемента сдвигаются, чтобы быть первыми тремя, и новый четвертый элемент генерируется из двух из предыдущих элементов с использованием 3 * дБ.

Он разграничивает новые значения с помощью вложенности списка, так как 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.