2010-03-22 10 views
8

Soy un novato de Scala. Decidí escribir un solucionador de spider solitario como primer ejercicio para aprender el lenguaje y la programación funcional en general.Repetición de una lista en Scala

Me gustaría generar una baraja barajada aleatoriamente que contenga 1, 2 o 4 palos. Esto es lo que ocurrió:

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

que debe devolver

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

dependiendo del valor de numberOfSuits, excepto que no hay lista de "multiplicar" operación que puedo encontrar. ¿Lo extrañé? ¿Hay una mejor manera de generar el mazo completo antes de barajar?

Por cierto, planeo usar una enumeración para los trajes, pero fue más fácil escribir mi pregunta con cuerdas. Tomaré la lista que se generó arriba y usaré para comprensión, iterar sobre los palos y una lista similar de "rangos" de cartas para generar un mazo completo.

+0

La parte interesante de este proyecto creará las generaciones inmutables del cuadro (diseño actual de las tarjetas). Solicito al cuadro actual una lista de movimientos legales, devueltos como tuplas de (columna de origen, columna de destino y posición de origen). A continuación, aplico cada uno al cuadro actual de forma recursiva usando algún tipo de algoritmo mini-max para encontrar el "mejor" movimiento.También quiero que el objeto de la tarjeta sea inmutable, por lo que los cuadros ("cuadros?") Tendrán que saber si una carta está boca arriba. – Ralph

Respuesta

7

Debe buscar el scaladoc para el objeto List. Tiene todas las maneras de métodos interesantes para la creación de listas. Por ejemplo, la siguiente es exactamente lo que estaba tratando de:

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

un código mucho más agradable, sin embargo, sería la siguiente (Scala 2.7):

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

En Scala 2,8 tabulate es al curry, por lo la sintaxis correcta sería:

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

He intentado con tu ejemplo, pero aparece un error en 2.8.0.Beta1-prerelease. De hecho, obtengo este error en la mayoría de las muestras de List.tabulate que puedo encontrar. ¿Lo que da? Scala> List.tabulate (4, i => suits.apply (I% numberOfSuits)) : 5: error: falta tipo de parámetro List.tabulate (4, i => suits.apply (i% numberOfSuits)) scala> List.tabulate (4, (i: Int) => suits.apply (i% numberOfSuits)) : 7: error: valor de método sobrecargado tabulate con alternativas .... no se puede aplicar a (Int) , (Int) => java.lang.String) List.tabulate (4, (i: Int) => suits.apply (i% numberOfSuits)) ^ –

+0

@ Adam La sintaxis cambió ligeramente de 2.7 a 2.8. Ver la respuesta editada. –

+0

Es curioso que lo menciones. Olvidé que los documentos singleton estaban en la parte inferior de las páginas del documento del paquete. En el comentario que escribí arriba, se me ocurrió la * EXACT * misma respuesta que ofrecieron primero arriba. – Ralph

16

aplana un listas finitas de listas:

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

aplanar un flujo infinito de listas, dar los primeros N elementos:

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

¿Es este un nuevo método en 2.8.0? No pude hacer que funcionara, pero lo hice: val suits = List ("clubs", "diamonds", "hearts", "spades"); List.flatten (List.make (4, suits.take (1))), donde el "1" es el valor numberOfSuits. – Ralph

+0

Sí, algunos de estos son nuevos en 2.8. – retronym

6

pueden ampliar una secuencia numérica y flatMap en lugar de multiplicar.

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

Esto también funciona en 2.7.x.


edición: ya que eres menos experiencia con Scala, es posible que todavía no han llegado a través del patrón proxeneta-mi-biblioteca. Si desea multiplicar sus listas mucho, puede agregar una clase de conversión personalizada:

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) 

y ahora puede hacerlo

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

(En general, la reutilización de dichos implícitos, declararlos en un objeto y luego importe MyObject._ para obtener la conversión implícita y la clase correspondiente en el alcance.)

Cuestiones relacionadas