2010-03-22 4 views
8

Je suis un Scala noob. J'ai décidé d'écrire un solitaire spider solver comme un premier exercice pour apprendre le langage et la programmation fonctionnelle en général.Répétition d'une liste dans Scala

Je voudrais générer un jeu de cartes mélangées aléatoirement contenant 1, 2 ou 4 combinaisons. Voici ce que je suis venu avec:

val numberOfSuits = 1 
(List("clubs", "diamonds", "hearts", "spades").take(numberOfSuits) * 4).take(4) 

qui devrait revenir

List("clubs", "clubs", "clubs", "clubs") 
List("clubs", "diamonds", "clubs", "diamonds") 
List("clubs", "diamonds", "hearts", "spades") 

en fonction de la valeur de numberOfSuits, sauf qu'il n'y a pas de liste d'opération « multiplier » que je peux trouver. Ai-je manqué ça? Y a-t-il un meilleur moyen de générer le jeu complet avant de le mélanger? Par ailleurs, j'ai l'intention d'utiliser une énumération pour les combinaisons, mais il était plus facile de taper ma question avec des chaînes. Je vais prendre la liste générée ci-dessus et en utilisant un pour la compréhension, itérer sur les costumes et une liste similaire de cartes "rangs" pour générer un pont complet.

+0

La partie intéressante de ce projet sera la création des générations immuables du tableau (mise en page actuelle des cartes). Je demande au tableau courant une liste de coups légaux, retournés sous forme de tuples de (colonne source, colonne de destination, et position source). J'applique ensuite chacun au tableau courant d'une manière récursive en utilisant une sorte d'algorithme mini-max pour trouver le "meilleur" mouvement.Je veux aussi que l'objet carte soit immuable, donc les tableaux ("tableaux") devront savoir si une carte est face visible. – Ralph

Répondre

7

Vous devriez rechercher le scaladoc pour l'objet List. Il a toutes les manières de méthodes intéressantes pour la création de listes. Par exemple, ce qui suit fait exactement ce que vous essayez de:

List.flatten(List.make(4, List("clubs", "diamonds", "hearts", "spades").take(numberOfSuits))).take(4) 

Un beaucoup plus agréable code, cependant, ne serait-ce (Scala 2.7):

val suits = List("clubs", "diamonds", "hearts", "spades") 
List.tabulate(4, i => suits.apply(i % numberOfSuits)) 

Sur Scala 2.8 tabulate est cari, donc la syntaxe correcte serait:

List.tabulate(4)(i => suits.apply(i % numberOfSuits)) 
+0

J'ai essayé votre exemple, mais obtenez une erreur sur 2.8.0.Beta1-prerelease. En fait, je reçois cette erreur sur la plupart des exemples de List.tabulate que je peux trouver. Ce qui donne? scala> List.tabulate (4, i => suits.apply (i% numberOfSuits)) : 5: Erreur: type de paramètre manquant List.tabulate (4, i => suits.apply (i% numberOfSuits) scala> List.tabulate (4, (i: Int) => suits.apply (i% numberOfSuits)) : 7: erreur: méthode surchargée tabulée avec des alternatives .... ne peut pas être appliquée à (Int , (Int) => java.lang.String) Liste.tabulate (4, (i: Int) => suits.apply (i% numberOfSuits)) ^ –

+0

@Adam La syntaxe a légèrement changé de 2.7 à 2.8. Voir la réponse éditée. –

+0

Drôle, vous devriez le mentionner. J'ai oublié que les docs de singleton étaient au bas des pages de doc de paquet. Dans le commentaire que j'ai écrit ci-dessus, j'ai trouvé la réponse * EXACT * que vous avez donnée en premier. – Ralph

16

Aplatir une liste finie de listes:

scala> List.fill(2)(List(1, 2, 3, 4)).flatten 
res18: List[Int] = List(1, 2, 3, 4, 1, 2, 3, 4) 

Aplatir un flux infini de listes, prendre les premiers éléments N:

scala> Stream.continually(List(1, 2, 3, 4)).flatten.take(8).toList 
res19: List[Int] = List(1, 2, 3, 4, 1, 2, 3, 4) 
+0

Est-ce une nouvelle méthode dans 2.8.0? Je ne pouvais pas le faire fonctionner, mais cela a fait: val suits = Liste ("clubs", "diamants", "coeurs", "pique"); List.flatten (List.make (4, suits.take (1))), où "1" est la valeur numberOfSuits. – Ralph

+0

Oui, certains d'entre eux sont nouveaux en 2.8. – retronym

6

Vous pouvez développer une séquence numérique et flatMap au lieu de multiplier.

scala> (1 to 3).flatMap(_=>List(1,2,3,4).take(2)).take(4) 
res1: Seq[Int] = List(1, 2, 1, 2) 

Cela fonctionne aussi dans 2.7.x. Edit: comme vous avez moins d'expérience avec Scala, vous n'avez peut-être pas encore rencontré le modèle pimp-my-library. Si vous souhaitez multiplier vos listes beaucoup, vous pouvez ajouter une classe de conversion personnalisée:

class MultipliableList[T](l: List[T]) { 
    def *(n: Int) = (1 to n).flatMap(_=>l).toList 
} 
implicit def list2multipliable[T](l: List[T]) = new MultipliableList[T](l) 

et maintenant vous pouvez

scala> List(1,2,3)*4 
res2: List[Int] = List(1, 2, 3, 1, 2, 3, 1, 2, 3, 1, 2, 3) 

(En général, de réutiliser ces implicits, les déclarer dans un objet et puis importez MyObject._ pour obtenir la conversion implicite et la classe correspondante dans la portée.)