2011-03-11 3 views
2

J'essaye de résoudre une question euler de projet. Je veux créer la liste des éléments dans une spirale entière.créer une liste récursive infinie dans haskell en utilisant une fonction renvoyant une sous-liste

I ont pour fonction:

next_four_numbers last size = map (\p -> last + p*(size-1)) [1,2,3,4] 
  • avec des paramètres 1 et 3 il retourne [3,5,7,9]
  • avec des paramètres 9 et 5, il retourne [13,17,21 , 25]
  • avec les paramètres 25 et 7, il retourne [31,37,43,49] ...

J'ai certainement d'autres moyens pour générer, mais à la fin je veux avoir l'infini séquence:

diagonal_spiral_numbers = [...] 1,3,5,7,9,13,17,21,25,31,37,43,49

Comment pourrais-je finir par créer ce infinte séquence en utilisant ma fonction "next_four_numbers"? Bien sûr, je veux être en mesure de mapper ce efficace (je voudrais être en mesure de le faire, par exemple):

take 20000 (filter is_prime diagonal_spiral_numbers) 

Merci,

ps: bien sûr, je suis d'apprentissage haskell et pourrait être plus facile que je ne l'imagine.

+0

Je pense que la question n'est pas si claire. De quelle liste avez-vous besoin, comment devrait-elle contenir? Pourriez-vous poster un lien vers le projet? – peoro

+0

Voici Projet Euler [Problème 58] (http://projecteuler.net/index.php?section=problems&id=58) – interjay

+0

Il y a une faute de frappe, 'n' devrait être' last' dans '(\ p -> n + p * (size-1)) ' – Jonathan

Répondre

4

Si vous avez une fonction qui génère l'état suivant sur la base du précédent, vous pouvez utiliser la fonction iterate pour créer la liste entière. Dans ce cas, l'état se compose des quatre nombres et de la taille. Après avoir appelé itérer, j'appelle map fst pour se débarrasser des valeurs size, et concat pour concaténer toutes les listes.

nextState (prev,size) = (next_four_numbers (last prev) size, size+2) 
allNums = concat $ map fst $ iterate nextState ([1],3) 
1

Vous pouvez le faire comme ceci:

diagonal_spiral_numbers = 
    let helper l s = 
      let next_four_numbers last size = map (\p -> last + p*(size-1)) [1,2,3,4] 
       (a:b:c:d:[]) = next_four_numbers l s 
      in a:b:c:d : helper d (s+2) 
    in 1 : helper 1 3 

Voici la sortie:

take 20 diagonal_spiral_numbers 
[1,3,5,7,9,13,17,21,25,31,37,43,49,57,65,73,81,91,101,111] 

Cependant, je me demande pourquoi vous avez besoin d'utiliser vos next_four_numbers fonctions: la liste résultante pourrait être générés dans beaucoup plus simple (et je dirais globalement mieux) façons.

+0

Ceci est juste un extrait de code et n'offre aucune explication, insight, ou direction pour la façon dont on pourrait comprendre ou dériver un tel code. -1 – luqui

+0

'[a, b, c, d] = ...' est un moyen plus lisible (imho) pour correspondre à une liste de quatre éléments. –

0

Il peut certainement se faire de cette façon, générer une liste de listes puis flattening (cochez la fonction concatMap), mais la manière habituelle est d'avoir votre fonction d'aide un argument de « queue » supplémentaire, puis renvoyer a: b: c: d: tail.

Une autre approche serait d'utiliser zipWith3.

0

Notez que vos last et size paramètres sont toujours de la forme (2x+1)^2 et 2x+3, respectivement (pour x en 0,1,2,3,...)

Vous avez juste besoin d'appeler next_four_numbers une fois avec chacun de ces paramètres.Ceci peut être accompli avec une compréhension de la liste:

diagonals = [next_four_numbers ((2*x+1)*(2*x+1)) (2*x+3) | x <- [0..]] 

Ou avec une carte (si vous êtes plus à l'aise avec cela):

diagonals = map (\x -> next_four_numbers ((2*x+1)*(2*x+1)) (2*x+3)) [0..] 

Ensuite, il est juste une question d'aplatir la liste et préfixer 1 :

actual_diagonals = 1:concat diagonals 
main = print (take 20 actual_diagonals) 

Cela peut probablement être nettoyé un peu, mais je vais laisser vous;) BTW, [0..] est un raccourci juste pour la liste infinie 0,1,2,3,...

Questions connexes