2010-09-29 21 views
5

He querido aprender algo de Haskell desde hace un tiempo, y sé que él y lenguajes similares tienen muy buen soporte para varios tipos de listas infinitas. Entonces, ¿cómo podría representar la secuencia de números tetraédricos en Haskell, preferiblemente con una explicación de lo que está sucediendo?Representar secuencia de números tetraédricos en Haskell

0 0 0 
1 1 1 
2 3 4 
3 6 10 
4 10 20 
5 15 35 
6 21 56 
7 28 84 
8 36 120 

En caso de que no está claro lo que está pasando allí, la segunda columna es un total acumulado de la primera columna y la tercera columna es un total acumulado de la segunda columna. Prefiero que el código de Haskell conserve algo del enfoque de "total acumulado", ya que ese es el concepto que me preguntaba cómo expresarlo.

+0

Para más información sobre por qué le pregunté: Tengo un conjunto de buckyballs (http://www.getbuckyballs.com/) y descubrí que realmente les gusta formar bipirámides pentagonales (http://en.wikipedia.org/wiki/Pipiagonal_bipirámide) con caras equiláteras. Por lo tanto, según la respuesta de perimosocordiae, los números "bipiramidales pentagonales" son 'scanl1 (+) (scanl1 (+) (1: map (* 5) [1 ..]))'. – jnylen

Respuesta

10

Tiene razón, Haskell es muy agradable para hacer las cosas de esta manera:

first_col = [0..] 
second_col = scanl1 (+) first_col 
third_col = scanl1 (+) second_col 
  • first_col es una lista infinita de números enteros, a partir de 0
  • scanl (+) calcula una suma continua perezoso: Prelude docs

Podemos verificar que el código anterior está haciendo lo correcto:

Prelude> take 10 first_col 
[0,1,2,3,4,5,6,7,8,9] 
Prelude> take 10 second_col 
[0,1,3,6,10,15,21,28,36,45] 
Prelude> take 10 third_col 
[0,1,4,10,20,35,56,84,120,165] 
+0

¿Por qué cuando ingreso 'first_col = [0 ..]' (o incluso 'n = 1') en el intérprete, dice' analizar error en la entrada '=' '? – jnylen

+3

Ah, cuando estás usando ghci, necesitas prefijar asignaciones con 'let'. Pruebe 'let first_col = [0..1]' – perimosocordiae

6

Agregando a la gran respuesta de perimosocordiae, los idiomas como Haskell son tan hábiles que le permiten hacer una lista infinita de listas infinitas.

En primer lugar permite definir el operador que produce cada fila sucesiva:

op :: [Integer] -> [Integer] 
op = scanl1 (+) 

Como se explica por perimosocordiae, esto es sólo una suma continua perezoso.

También necesitamos un caso base:

tnBase :: [Integer] 
tnBase = [0..] 

Entonces, ¿cómo obtener una lista infinita de infinitas listas de números tetraédricos? Iteramos esta operación en el caso base, la salida producida por el caso base, a continuación, que la producción ...

tn = iterate op tnBase 

iterate está en el preludio, dichas funciones pueden encontrarse usando Hoogle y searching by name (si tiene una buena suposición) o type signature (generalmente conoce la firma de lo que necesita). Source code generalmente se vincula desde haddock documentation.

Presentación

(en caso de que no se siente cómodo con el mapa, tomar, gota, y la cabeza)

Todo esto está muy bien, pero bastante inútil si usted no sabe cómo pasar la primera lista infinita para ver el segundo, tercero, etc.Hay un montón de opciones, para conseguir justo una lista en particular se puede soltar el primer pocos:

getNthTN n = head (drop n tn) 

Obtención de los primeros resultados de cada lista es probablemente más de lo que estás buscando sin embargo:

printFirstFew n m = print $ take m (map (take n) tn) 

Aquí map (take n) tn tomará los primeros valores n de cada lista de números tetraédricos, mientras que take m limitará nuestros resultados a las primeras listas m.

Y por último, me gusta el groom paquete impresionante para juego interactivo rápida con los datos:

> groom $ take 10 (map (take 10) tn) 
[[0, 1, 2, 3, 4, 5, 6, 7, 8, 9], 
[0, 1, 3, 6, 10, 15, 21, 28, 36, 45], 
[0, 1, 4, 10, 20, 35, 56, 84, 120, 165], 
[0, 1, 5, 15, 35, 70, 126, 210, 330, 495], 
[0, 1, 6, 21, 56, 126, 252, 462, 792, 1287], 
[0, 1, 7, 28, 84, 210, 462, 924, 1716, 3003], 
[0, 1, 8, 36, 120, 330, 792, 1716, 3432, 6435], 
[0, 1, 9, 45, 165, 495, 1287, 3003, 6435, 12870], 
[0, 1, 10, 55, 220, 715, 2002, 5005, 11440, 24310], 
[0, 1, 11, 66, 286, 1001, 3003, 8008, 19448, 43758]] 
+0

Ambas buenas respuestas, ¡gracias! – jnylen

Cuestiones relacionadas