Números Motzkin


30

El enésimo número de Motzkin es el número de rutas de (0, 0) a (n, 0) donde cada paso tiene la forma (1, -1), (1, 0) o (1, 1), y la ruta nunca va por debajo de y = 0.

Aquí hay una ilustración de estas rutas para n = 1, 2, 3, 4, desde el enlace anterior:

Números Motzkin

La secuencia deseada es OEIS A001006 . OEIS tiene algunas otras caracterizaciones de la secuencia.


Se le dará un entero positivo n como entrada. Debe generar el enésimo número de Motzkin.

Aquí están los números de Motzkin del 1 al 10:

1, 2, 4, 9, 21, 51, 127, 323, 835, 2188

Todos los métodos de entrada y salida estándar están permitidos. Se aplican lagunas estándar .

Este es el código de golf. Pocos bytes ganan.


¿Cuál es el conjunto mínimo de números de Motzkin que debemos ser capaces de generar?
Addison Crump


@FlagAsSpam Todos ellos, hasta limitaciones de tiempo / memoria / tipo de datos.
isaacg

Creo que los idiomas necesitan una palabra Dyck incorporada ahora.
lirtosiast

Respuestas:


15

MATL , 13 14 bytes

i-2/t.5+hH4Zh

Ejemplo:

>> matl i-2/t.5+hH4Zh
> 6
51

EDITAR (16 de junio de 2017): ¡puedes probarlo en línea! Tenga en cuenta también que en las versiones modernas del lenguaje (que datan de este desafío) se ipodría eliminar.

Explicación

Bastante sencillo, usando la equivalencia (ver ecuación (10)) con la función hipergeométrica :

ingrese la descripción de la imagen aquí

De la definición de la función hipergeométrica

ingrese la descripción de la imagen aquí

Está claro que el orden de los dos primeros argumentos puede intercambiarse, lo que ahorra un byte.

i         % input                                                   
-2/       % divide by -2
t.5+      % duplicate and add 0.5
h         % horizontal concatenation into a vector                               
H         % number 2
4         % number literal                                          
Zh        % hypergeometric function with three inputs (first input is a vector)

1
Esta respuesta está vinculada por la más corta y más antigua por aproximadamente una hora y media, así que la estoy aceptando.
isaacg

¡Gracias! Apenas podía imaginar que MATL estaría atado a Pyth. Es un lenguaje tan difícil de superar, ¡buen trabajo al diseñarlo!
Luis Mendo

11

Retina , 59 58 bytes

+`(\D*)1(1*)
:$1<$2:$1>$2:$1_$2:
:(_|()<|(?<-2>)>)+:(?!\2)

Toma entrada en unario . La entrada 7 (es decir 1111111) toma bastante tiempo pero aún se completa en menos de un minuto. No iría mucho más lejos que eso.

Pruébalo en línea.

Explicación

Una caracterización diferente de los números de Motzkin es el número de cadenas de tres caracteres diferentes, donde dos de ellos están correctamente equilibrados (de ahí la estrecha relación con los números catalanes, que son iguales sin el tercer carácter que es independiente del equilibrio).

Grupos de equilibrio de .NET son bastante buenos en la detección cadenas que coincidan correctamente, así que simplemente generamos todas las cadenas de longitud N(usando _, <y >como los tres caracteres) y luego contar cuántos de los que se equilibran correctamente. Por ejemplo, N = 4las cadenas válidas son:

____
__<>
_<_>
_<>_
<__>
<_>_
<>__
<<>>
<><>

En comparación con la definición en el desafío, _corresponde a un (1,0)paso, <a (1,1)y >para (1,-1).

En cuanto al código real, :se utiliza como separador entre las diferentes cadenas. La segunda expresión regular es solo una forma de golf de la expresión regular .NET estándar para cadenas equilibradas .

Algo a tener en cuenta es que solo hay una única :inserción entre las cadenas en cada paso, pero la segunda expresión regular coincide con un inicio y un final :(y dado que las coincidencias no pueden superponerse, esto significa que las cadenas adyacentes generadas a partir de una plantilla en el último paso no pueden coincidir) ) Sin embargo, esto no es un problema, porque a lo sumo uno de esos tres puede coincidir:

  • Si la cadena termina en _coincidencias, el prefijo sin eso _ya está equilibrado correctamente, y / <o >eliminaría ese equilibrio.
  • Si la cadena que termina en >partidos, la cadena se equilibra con la que >, por lo que _o <sería deshacerse de ese equilibrio.
  • Las cadenas que terminan en <nunca se pueden equilibrar.

Es una pena que '\' tenga un significado especial; de lo contrario, usar caracteres '_ / \' se adaptaría mejor al espíritu de la pregunta.
Neil

9

Python 2, 51 bytes

M=lambda n:n<1or sum(M(k)*M(n-2-k)for k in range(n))

Utiliza la fórmula de Mathworld

ingrese la descripción de la imagen aquí

Guarda caracteres al poner el M[n-1]término en la suma como k=n-1, lo que da M[-1]*M[n-1], M[-1]=1como parte de la condición inicial.

Editar: Un personaje más corto escribiendo la suma de forma recursiva:

M=lambda n,k=0:n<1or k<n and M(k)*M(n-2-k)+M(n,k+1)

Otros enfoques que resultaron más largos:

M=lambda n,i=0:n and(i>0)*M(n-1,i-1)+M(n-1,i)+M(n-1,i+1)or i==0
M=lambda n:+(n<2)or(3*~-n*M(n-2)+(n-~n)*M(n-1))/(n+2)

8

Pyth, 15 bytes

Ls*V+KyMb1+t_K1

Esto define una función y. Pruébelo en línea: demostración

Explicación:

Dejado y[n]ser el n-th Número Motzkin. Calculo y[n]con la formula

y[n] = dot product of (y[0], ..., y[n-1], 1) and (y[n-2], ..., y[0], 1)

Observe que el primer vector es más grande que el segundo (excepto al calcular y[0]). Cuando este es el caso, Pyth ignora automáticamente el 1 al final del primer vector, de modo que ambos vectores tienen la misma longitud.

Ls*V+KyMb1+t_K1
L                 define a function y(b), which returns:
      yMb            compute the list [y[0], y[1], ..., y[b-1]]
     K               assign it to K
  *V                 vectorized multiplication of
    +K   1             * K with a 1 at the end
          +t_K1        * reverse(K), remove the first element, and append 1
 s                   return the sum (dot product)

Esta fórmula es una variación de una de las fórmulas enumeradas en OEIS. Puede ser un poco estúpido. Debido al 1 al final del primer vector (que hace que las longitudes sean desiguales), en realidad no tengo que darle a la recursión un caso base. Y tenía esperanzas de que los dos +...1s se puedan jugar de alguna manera. Resulta que no puedo.

Puede definir una recursión similar con un producto de puntos de vectores de igual longitud y definir el caso base y[0] = 1con el mismo número de bytes.


8

CJam (20 bytes)

.5X]{__W%.*:++}qi*W=

Demostración en línea

Como señaló Mego en los comentarios sobre la pregunta, esto está muy relacionado con los números catalanes: cambie el ay .5para 1compensar el índice por uno (o simplemente elimine por .5completo y deje el índice sin cambios) para obtener números catalanes.

La recurrencia utilizada es

a (n + 2) - a (n + 1) = a (0) * a (n) + a (1) * a (n-1) + ... + a (n) * a (0). [Bernhart]

de la página de OEIS. La recurrencia correspondiente para los números catalanes aparece como

a (n) = Suma_ {k = 0..n-1} a (k) a (n-1-k).


6

En serio, 21 bytes

,;╗r`;τ╜█@;u@τ╣║\*`MΣ

Toma prestado algún código de la solución de números catalanes de quintopia , específicamente la mejora que hice en los comentarios.

Yo uso la siguiente fórmula:

fórmula de motzkin

Como nCkes 0 para k > n, sumo hasta el final n-1, ya que todos esos valores serán 0 y, por lo tanto, no afectan la suma.

Pruébalo en línea

Explicación:

,;╗r`;τ╜█@;u@τ╣║\*`MΣ
,;╗                    push input, dupe, store one copy in register 0
   r                   push range(0, n) ([0,n-1])
    `             `M   map the function:
     ;τ╜█@               dupe k, push C(n, 2*k), swap with k
          ;u@τ╣║\        push the kth Catalan number
                 *       multiply
                    Σ  sum

C(n, 2*k)¿Qué hace ahora?
Addison Crump

@FlagAsSpam C(n,k) = nCk, o el número de combinaciones de kelementos de un grupo de nelementos.
Mego

Oh, eso tiene mucho más sentido de lo que pensé que era. +1.
Addison Crump

@FlagAsSpam No creo que quiera saber qué pensaste que era ...
Mego

5

R, 64 bytes

f=function(n)ifelse(n<2,1,f(n-1)+sum(rev(s<-sapply(2:n-2,f))*s))

Utiliza también la fórmula Mathworld de la respuesta python de @ xnor . Gracias a las reglas de precedencia, 2:n-2es equivalente a 0:(n-2).

Casos de prueba:

> f(0)
[1] 1
> f(1)
[1] 1
> f(5)
[1] 21
> f(10)
[1] 2188
> sapply(0:20,f)
 [1]        1        1        2        4        9       21       51      127
 [9]      323      835     2188     5798    15511    41835   113634   310572
[17]   853467  2356779  6536382 18199284 50852019

5

Mathematica, 31 30 bytes

AppellF1[-#/2,.5,-#/2,2,4,4]&

Por diversión, aquí hay una versión de 37 bytes

Hypergeometric2F1[(1-#)/2,-#/2,2,4]&

y versión de 52 bytes

SeriesCoefficient[1-x-Sqrt[1-2x-3x^2],{x,0,#+2}]/2&

4

Jalea , 17 14 13 bytes

×US;
1;HÇƓ¡1ị

Esto utiliza la relación de recurrencia de la respuesta de @ PeterTaylor . Pruébalo en línea!

Cómo funciona

×US;      Define a helper link. Left argument: a (list)

×U        Multiply (×) a by its reverse (U).
  S       Compute the sum of the resulting list.
   ;      Prepend it to a.
          Return the result.

1;HÇƓ¡1ị  Define the main link.

1         Set the left argument to 1.
 ;H       Append the half of 1 to 1. Result: [1, 0.5].
    Ɠ     Read an integer n from STDIN.
   Ç ¡    Call the helper link (Ç) n times.
      1ị  Retrieve the result at index 1.

2

Mathematica, 44 42 34 bytes

Sum[#!/(i!(i+1)!(#-2i)!),{i,0,#}]&

Una versión de 35 bytes:

Coefficient[(1+x+1/x)^#,x]/#&[#+1]&

2

Pari / GP , 38 36 26 bytes

n->(1+x+x^2)^n++/n\x^n++%x

Pruébalo en línea!

Usando la ecuación (11) de MathWorld :

METROnorte=1norte+1(norte+11)2

(nortek)2(nortek)2Xnorte+k(1+X+X2)norte


A 14-bytes Samau función utilizando la primera definición del coeficiente trinomio: );;7 2D$ⁿ$)╡$÷. No lo publicaré como respuesta porque el idioma es más nuevo que la pregunta.
alephalpha

Publicarlo está bien, solo tiene que agregar un descargo de responsabilidad de que el envío no es elegible para ganar porque, como usted dijo, el idioma es más nuevo que la pregunta.
Alex A.

2

05AB1E , 13 12 bytes

ÝI<ãʒ.øDŸQ}g

Pruébalo en línea!

Si bien la mayoría de las respuestas usan una fórmula o relación de recurrencia, este es un enfoque de conteo simple.

Cada posible camino a través de la cuadrícula está representado por la lista de sus coordenadas y. Para n segmentos, hay un total de (n + 1) puntos, pero el primero y el último son necesariamente 0, de modo que deja (n-1) puntos para especificar.

Ý           # range [0..n]
 I<         # n - 1
   ã        # cartesian power

Ahora tenemos una lista de rutas (sin incluir aún el 0 inicial y final). Por construcción, ninguno de ellos baja por debajo de 0. Sin embargo, algunos de ellos tienen pendientes ilegales (por ejemplo, saltan de 0 a 2), por lo que debemos filtrarlos.

ʒ      }g   # count how many paths satistfy the following condition
 0.ø        # surround with 0
      Q     # is equal to
    DŸ      # its own fluctuating range

Ÿes el rango fluctuante incorporado. Si hay algún par de números no adyacentes, completará los números que faltan (por ejemplo, [0, 2] se convierte en [0, 1, 2]). Solo los caminos legales se dejarán sin cambios.

Quizás sería una forma más intuitiva de verificar pendientes ilegales üαà(afirmar que el máximo de diferencias absolutas por pares es igual a 1). Sin embargo, esto pierde la ruta plana [0, 0, ... 0], que cuesta arreglar un byte extra.

Finalmente, tenga en cuenta que el código real se usa donde se usa esta explicación 0.ø. En lugar de rodear la ruta con ceros, esto rodea la entrada implícita con dos copias de la ruta. Esto pone el sistema de coordenadas al revés y de adentro hacia afuera, pero por lo demás es equivalente.


2

Stax , 12 bytes

îu¬@Y≤ÅÉÑ(πε

Ejecutar y depurarlo

No sé cómo hacer una composición tipográfica matemática elegante, pero esto se basa esencialmente en una construcción de programación dinámica

M(0) = 1
M(1) = 1
M(n + 1) = M(n) + sum(M(k) * M(n - k - 1) for k in [0..n-1])

1

Rubí, 50

Implementación directa de la relación de recurrencia.

g=->n{n<2?1:(3*(n-1)*g[n-2]+(2*n+1)*g[n-1])/(n+2)}

1

Brain-Flak , 90 bytes

(([{}]<(())>)<{({}()<{<>([({})]({}[({})]({}<>{}<>)))<>}<>>)}>){({}()<{}>)}{}({}{}[{}{}]<>)

Pruébalo en línea!

(norte0 0)2-(norte2)2(nortek)2donorte=(2nortenorte)-(2nortenorte+1)


0

ES6, 44 bytes

f=(n,k=0)=>n<1?1:k<n&&f(k)*f(n-2-k)+f(n,k+1)

Puerto directo de la solución recursiva de Python de @ xnor. Necesita n<1?1:porque n<1||haría f(0)volver true.


Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.