2010-03-22 15 views
8

I am a Scala noob. Ho deciso di scrivere un solitario solitario Spider come primo esercizio per imparare la lingua e la programmazione funzionale in generale.Ripetizione di una lista in Scala

Vorrei generare un mazzo di carte casualmente mescolato contenente 1, 2 o 4 semi. Ecco quello che mi si avvicinò con:

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

che dovrebbe tornare

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

a seconda del valore di numberOfSuits, tranne che non esiste un elenco operazione "moltiplicare" che posso trovare. Mi è mancato? C'è un modo migliore per generare il mazzo completo prima di mischiare?

BTW, ho intenzione di utilizzare un'enumerazione per i semi, ma è stato più facile digitare la mia domanda con le stringhe. Prenderò la Lista generata sopra e useremo una comprensione, itererà sopra i semi e un simile elenco di "ranghi" di carte per generare un mazzo completo.

+0

La parte interessante di questo progetto sarà la creazione delle generazioni immutabili del tableau (layout corrente delle carte). Chiedo al tableau corrente un elenco di mosse legali, restituito come tuple di (colonna di origine, colonna di destinazione e posizione di origine). Poi applico ciascuno al tableau corrente in modo ricorsivo usando una sorta di algoritmo mini-max per trovare la mossa "migliore".Voglio anche che l'oggetto della carta sia immutabile, quindi i tableau ("tableaux?") Dovranno sapere se una carta è scoperta. – Ralph

risposta

7

È necessario cercare lo scaladoc per l'oggetto List. Ha tutti i modi di metodi interessanti per la creazione di liste. Per esempio, il seguente fa esattamente quello che stavi cercando di:

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

un codice molto più bello, però, sarebbe questo (Scala 2.7):

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

Su Scala 2.8 tabulate è curry, così la sintassi corretta sarebbe:

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

Ho provato il tuo esempio, ma ho ricevuto un errore su 2.8.0.Beta1-prerelease. In effetti, ottengo questo errore sulla maggior parte dei campioni di List.tabulate che riesco a trovare. Cosa dà? scala> List.tabulate (4, i => suits.apply (I% numberOfSuits)) : 5: errore: manca tipo di parametro List.tabulate (4, i => suits.apply (% numberOfSuits i) scala> List.tabulate (4, (i: Int) => suits.apply (i% numberOfSuits)) : 7: errore: il valore del metodo di calcolo sovraccarico con alternative .... non può essere applicato a (Int , (Int) => java.lang.String) List.tabulate (4, (i: Int) => suits.apply (i% numberOfSuits)) ^ –

+0

@Adam La sintassi è leggermente cambiata da 2,7 a 2,8. Vedi la risposta modificata. –

+0

Divertente dovresti dirlo. Ho dimenticato che i documenti singleton erano in fondo alle pagine dei documenti del pacchetto. Nel commento che ho scritto sopra, ho trovato la * ESATTA * stessa risposta che hai offerto per prima. – Ralph

16

appiattire una lista definita di liste:

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

appiattire un flusso infinito di liste, prendere i primi N elementi:

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

È un nuovo metodo in 2.8.0? Non ho potuto farlo funzionare, ma questo ha fatto: val suits = List ("club", "quadri", "cuori", "picche"); List.flatten (List.make (4, suits.take (1))), dove "1" è il valore numberOfSuits. – Ralph

+0

Sì, alcuni di questi sono nuovi in ​​2.8. – retronym

6

è possibile espandere una sequenza numerica e flatMap invece di moltiplicare.

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

Questo funziona anche in 2.7.x.


Modifica: dal momento che hai meno esperienza con Scala, potresti non aver ancora trovato il modello di pimp-my-library. Se si vuole moltiplicare le vostre liste molto, è possibile aggiungere una classe di conversione personalizzato:

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) 

e ora è possibile

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

(In generale, di riutilizzare tali impliciti, li dichiara in un oggetto e quindi importare MyObject._ per ottenere la conversione implicita e la classe corrispondente nell'ambito.)

Problemi correlati