Realmente no está claro lo que está pidiendo. Podría ser una de las pocas cosas diferentes. Primero serían combinaciones simples de diferentes elementos en una lista. Scala lo ofrece con el método combinations()
de colecciones. Si los elementos son distintos, el comportamiento es exactamente el que espera de la definición clásica de "combinaciones". Para combinaciones de n elementos de elementos p, habrá p!/N! (P-n)! combinaciones en la salida.
Sin embargo, si hay elementos repetidos en la lista, Scala generará combinaciones con el elemento que aparece más de una vez en las combinaciones. Pero solo las diferentes combinaciones posibles, con el elemento posiblemente replicado tantas veces como existan en la entrada. Genera solo el conjunto de combinaciones posibles, por lo tanto, elementos repetidos, pero no combinaciones repetidas. No estoy seguro si subyacente hay un iterador a un Set
real.
Ahora, lo que en realidad quiere decir si entiendo correctamente es combinaciones de un conjunto dado de diferentes elementos p, donde un elemento puede aparecer varias veces n veces en la combinación.
Bueno, volviendo un poco, para generar combinaciones cuando hay elementos repetidos en la entrada, y quiere ver las combinaciones repetidas en la salida, el camino a seguir es simplemente generarlo por "fuerza bruta" "usando n bucles anidados. Tenga en cuenta que realmente no hay nada de bruto, es solo el número natural de combinaciones, en realidad, que es O (p^n) para n pequeña, y no hay nada que pueda hacer al respecto. Sólo se debe tener cuidado para recoger estos valores correctamente, así:
val a = List(1,1,2,3,4)
def comb = for (i <- 0 until a.size - 1; j <- i+1 until a.size) yield (a(i), a(j))
resultando en
scala> comb
res55: scala.collection.immutable.IndexedSeq[(Int, Int)] = Vector((1,1), (1,2), (1,3), (1,4), (1,2), (1,3), (1,4), (2,3), (2,4), (3,4))
Esto genera las combinaciones de estos valores repetidos en una, creando en primer lugar las combinaciones intermedias de 0 until a.size
como (i, j) ...
Ahora para crear las "combinaciones con repeticiones" sólo hay que cambiar los índices de este tipo:
val a = List('A','B','C')
def comb = for (i <- 0 until a.size; j <- i until a.size) yield (a(i), a(j))
producirá
List((A,A), (A,B), (A,C), (B,B), (B,C), (C,C))
Pero no estoy seguro de cuál es la mejor manera de generalizar esto a combinaciones más grandes.
Ahora cierro con lo que estaba buscando cuando encontré esta publicación: una función para generar las combinaciones de una entrada que contiene elementos repetidos, con índices intermedios generados por combinations()
. Es bueno que este método produce una lista en lugar de una tupla, por lo que significa en realidad podemos resolver el problema con un "mapa de un mapa", algo que estoy seguro de que nadie más ha propuesto aquí, pero eso es bastante ingenioso y hará que tu amor por FP y Scala crezca un poco más después de que lo veas!
def comb[N](p:Seq[N], n:Int) = (0 until p.size).combinations(n) map { _ map p }
resultados en
scala> val a = List('A','A','B','C')
scala> comb(a, 2).toList
res60: List[scala.collection.immutable.IndexedSeq[Int]] = List(Vector(1, 1), Vector(1, 2), Vector(1, 3), Vector(1, 2), Vector(1, 3), Vector(2, 3))
usted puede también pegar el código en la cuestión, marcándolo como código fuente. –
Por favor, edite la pregunta en lugar de volver a publicarla como una "respuesta". –