Los números de Lucas-nacci

19

Antecedentes

Casi todos están familiarizados con los números de Fibonacci F(n) :

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

Estos están formados por la función de recursión F(n) = F(n-1) + F(n-2)con F(0)=0y F(1)=1. A000045

Una secuencia estrechamente relacionada son los números de Lucas L(m) :

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

Estos están formados por la función de recursión L(m) = L(m-1) + L(m-2)con L(0)=2y L(1)=1. A000032

Podemos alternar entre las dos secuencias en función de índices pares / impares, con la construcción
A(x) = F(x)si x mod 2 = 0y de lo A(x) = L(x)contrario. Por ejemplo, A(4)es igual a F(4)desde 4 mod 2 = 0. Vamos a llamar a esta secuencia de los números Lucas-NACCI , A(x):

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

Esto puede estar formado por la función de recursión A(x) = 3*A(x-2) - A(x-4)con A(0)=0, A(1)=1, A(2)=1, y A(3)=4. A005013

Desafío

Dada entrada n, salida de la secuencia de n+1números hasta e incluyendo A(n)como se describe anteriormente. Pocos bytes (o equivalentes de bytes, como para LabVIEW , como se determina individualmente en Meta) gana.

Entrada

Un solo entero no negativo n.

Salida

Una lista de números que corresponden a la subsecuencia de números de Lucas-nacci de A(0)a A(n). La lista debe estar en orden secuencial como se describió anteriormente.

Reglas

  • Se aplican las reglas estándar de código de golf y las restricciones de escapatoria .
  • Se aplican las reglas estándar de entrada / salida .
  • El número de entrada puede estar en cualquier formato adecuado: unario o decimal, leído desde STDIN, función o argumento de línea de comando, etc. - usted elige.
  • La salida puede imprimirse en STDOUT o devolverse como resultado de la llamada a la función. Si se imprimen, se deben incluir delimitadores adecuados para diferenciar los números (separados por espacios, separados por comas, etc.).
  • Además, si la salida a STDOUT, los espacios en blanco circundantes, la nueva línea final, etc., son opcionales.
  • Si la entrada es un número entero no negativo o entero, el programa puede hacer cualquier cosa o nada, ya que el comportamiento no está definido.

Ejemplos

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
AdmBorkBork
fuente
¿Newline se considera un delimitador aceptado?
corsiKa
@corsiKa Claro, está bien.
AdmBorkBork

Respuestas:

9

Jalea, 12 bytes

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

Pruébalo en línea!

Antecedentes

Podemos extender F y L a -1 definiendo F (-1) = 1 y L (-1) = -1. Esto es consistente con la función recursiva.

Nuestro programa comienza con

-1  1
 0  2

En cada paso, para formar el siguiente par, invertimos el último par y lo agregamos al penúltimo par. Por ejemplo:

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

Si continuamos este proceso por unos pocos pasos más, obtenemos

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

La secuencia de Lucas-Nacci es simplemente la columna izquierda.

Cómo funciona

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

С mira los dos enlaces a la izquierda: 2y U+¥. Como el más a la izquierda es un nilad, no puede ser el cuerpo del bucle. Por lo tanto, U+¥se usa como cuerpo y se lee un número desde la entrada. Como no hay argumentos de línea de comandos, ese número se lee desde STDIN.

Dennis
fuente
2
Tengo la impresión de que haces este tipo de cosas (jugar al golf en Jelly) para vivir. Lo que me aterroriza.
Draco18s
24
Si alguien sabe cómo jugar golf (código) para ganarse la vida, hágame ping en el chat. Pidiendo un amigo ...
Martin Ender
2
Básicamente, solo estás calculando ambas secuencias, pero retrocediendo en cada paso, lo que efectivamente cambia entre las secuencias.
Neil
1
@Neil Sí, exactamente. Evita entrelazar las secuencias después, que es un poco más larga.
Dennis
6

CJam, 21 20 bytes

Gracias a Sp3000 por guardar 1 byte.

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

Pruébalo aquí.

Explicación

Simplemente usa la recurrencia dada en la especificación de desafío.

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.
Martin Ender
fuente
1
¿Quién (o qué) es Sp3000 que agradeces en cada respuesta?
CJ Dennis
55
@CJDennis Algunos dicen que es el mejor golfista de Python que haya existido. Algunos dicen que vive en una cabaña aislada en la cima de una montaña, construida con un número mínimo de troncos. Algunos dicen que él es la voz en la parte posterior de nuestras cabezas, lo que nos fastidia cuando publicamos soluciones que se pueden jugar más. Pero la mayoría de nosotros solo decimos que es el usuario cuyo perfil ha vinculado Martin.
Mego
6

Perl 6, 42 bytes

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

uso

> 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)
Teclas de acceso rápido
fuente
1
La lambda más clara que se me ocurrió es{( (0,1,*+*...*) Z (2,1,*+*...*) ).flat.rotor( 1=>2, 1=>0 )[ 0..$_ ].flat}
Brad Gilbert b2gills
Teniendo en cuenta que la redacción exacta es "dado N", se puede ahorrar un byte con: (0,1,1,4,{$^b;$^d;3*$^c-$^a}...*)[^(n+1)].
raiph
6

Haskell, 59 , 57 , 56 , 52 , 51 bytes

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

Definición de serie adaptada de esta respuesta .

Menos golfizado:

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 startda una lista infinita, que se define: f(0)=start, f(1)=1, f(n)=f(n-1) + f(n-2). whichStart idevuelve 2 para entrada impar (serie Lucas) o 0 para par (serie Fibonacci). lucasNacci ida el número i-ésimo de Lucas-nacci. firstN nmapas sobre la lista.

Un byte salvado por Boomerang.

Michael Klein
fuente
1
Creo que puedes obtener un byte más moviéndote 2*mod i 2y lluego puedes quitar el paréntesis. Así: l a=2*mod a 2:scanl(+)1(l a)yf n=[l i!!i|i<-[0..n]]
basile-henry
@Boomerang Sí, eso funciona. Gracias
Michael Klein
5

ES6, 65 bytes

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

Utiliza la relación de recurrencia dada en la pregunta.

Neil
fuente
5

Retina , 70 62 59 bytes

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

f
1

Pruébalo en línea

  • La entrada está en base unaria, n 1s.
  • 1? $`¶- Cree una línea para cada número de 0 a n : , 1, 11, 111, 1111, ...
  • m`^(11)*1$ $&ff- Agregar ffa líneas impares. Esto sembrará la función con L (0) = 2.
  • m`$  f- Añadir  fa todas las líneas (tenga en cuenta el espacio). Esto siembra la función con 0 y 1 para los números de Fibonacci, y 2 y 1 para los números de Lucas.
  • +`1(f*) (f*) $2 $2$1 - Bucle: calcular F (n + 1) = F (n) + F (n-1) mientras todavía hay 1s.
  •  f*   - Retire F (n + 1) del final de cada línea.
  • Reemplace fs de nuevo a 1s. Si esto no es necesario y podemos quedarnos con fs, la longitud es de solo 55 bytes.
Kobi
fuente
5

Oracle SQL 11.2, 218 216 201 bytes

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;

Sin golf

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;

Logré ganar algunos bytes usando (¿abusando?) La función SIGN para generar los primeros 3 elementos de la secuencia.

Jeto
fuente
3

Japt, 25 22 21 bytes

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

¡Pruébalo en línea!

Antecedentes

Es algo difícil crear una secuencia de Fibonacci en Japt, pero tenemos una función integrada Mgpara hacerlo por nosotros. Sin embargo, esto solo nos da la secuencia de Fibonacci, no la secuencia de Lucas. Podemos lograr la secuencia de Lucas con bastante facilidad usando este truco:

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

Como puede ver, F(N-1) + F(N+1)es igual L(N)para todos N. Sin embargo, dado que solo necesitamos números de Lucas en los índices impares, podemos combinar las dos fórmulas en una:

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

Cómo funciona

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.)
ETHproducciones
fuente
3

Mathematica, 52 51 bytes

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

Una idea muy similar a la de Martin anterior, pasé algún tiempo tratando de encontrar una forma más corta de definir los "casos base" para la función. La interpolación polinómica fue un fracaso, así que decidí utilizar esta extensión en negativos para obtener una definición bastante corta.

Un simmons
fuente
2

Mathematica, 56 bytes

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

Implementación muy sencilla. Define una función auxiliar fy luego se evalúa como una función sin nombre que se aplica fa un rango para obtener todos los resultados. Esto se siente innecesariamente engorroso.

Sin embargo, una sola función sin nombre parece ser un byte más:

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

MATL , 17 18 bytes

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

Traducción casi directa de la respuesta de Martin CJam .

Pruébalo en línea!

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
Luis Mendo
fuente
2

Brachylog , 51 bytes

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

Esto toma un número como entrada e imprime en STDOUT la lista, con espacios que separan cada número.

Explicación

§ 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

El corte !en la primera regla del sub-predicado 1 es necesario para que cuando retrocedamos ( \), no terminemos en un bucle infinito donde el intérprete probará la segunda regla para una entrada menor que 4.

Fatalizar
fuente
2

Mathematica, 41 bytes

LinearRecurrence[{0,3,0,-1},{0,1,1,4},#]&
alephalpha
fuente
2

Groovy, 50 bytes

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

Esto define la función x, que toma n como su primer argumento y tiene el caso base de los primeros cuatro números en la secuencia de Fibocas como argumentos predeterminados para el resto de la función.

un aquí es n. b, c, dye son los siguientes cuatro elementos en la secuencia.

Disminuye n y se repite hasta que n es menor que cero; cuando se repite, agrega al valor de retorno final el primer elemento en su secuencia actual. Los nuevos valores para los siguientes cuatro elementos en la secuencia se dan a la llamada recursiva: los últimos tres elementos se desplazan para ser los primeros tres, y se genera un nuevo cuarto elemento a partir de dos de los elementos anteriores usando 3 * db.

Delimita nuevos valores con anidaciones de listas, ya que Groovy puede devolver múltiples valores al insertarlos en una lista, por lo que cada llamada devuelve el primer elemento actual y el resultado de la recursión, que será su propia lista.

Patrick Stephen
fuente
1

Pilones , 19

Esta es una traducción bastante directa del enfoque de Martin.

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

Cómo funciona:

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.
Morgan Thrapp
fuente
1

DUP , 32 bytes

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

Try it here!

Una lambda anónima que deja una secuencia de números en la pila. Uso:

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

Explicación

[                              {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}
Mama Fun Roll
fuente
1

Python 2, 71 bytes

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)

Esto definitivamente parece demasiado largo. Sin embargo, me complació poder usar el notoperador bit a bit ... dos veces. Una vez como una especie de paridad, voltee hacia adelante y hacia atrás, y una vez para terminar la recursión cuando nllegue -1.

La variable psiempre será 0o -1, por lo que alternará entre entradas 0o -1de la lista. (Elegir la entrada -1de una lista de Python significa elegir el último elemento).

Mathmandan
fuente
1

Metaprogramación de plantilla C ++, 130 bytes

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)

Las definiciones recursivas de alguna manera claman por C ++ TMP, uso:

L<x>::v

con xser lo que A(x)te gusta.

Karl Napf
fuente