¿Hacer una combinación de coeficientes para un rango?
Frecuentes
Visto 111 veces
-1
Tengo problemas para hacer una combinación de coeficientes. Básicamente, tengo una lista de elementos y quiero obtener todas las combinaciones únicas de coeficientes para ellos de esta manera:
dog:1 cat:1
dog:2 cat:1
dog:3 cat:1
dog:1 cat:2
dog:2 cat:2
No estoy realmente seguro de cuál es la mejor manera de hacer esto (programación dinámica, recursión, fuerza bruta, etc.), así que intenté comenzar haciendo una recursión:
list = ["dog", "cat"]
coeff = [1] * len(list)
main_queue = []
def recursion(k, list):
for item in list[0:k-1]:
for data in range(5):
coeff_temp = coeff
coeff_temp[k] = data
main_queue.append(coeff_temp)
#print item, data
if k == (len(list)-1):
return
else:
recursion(k+1, list)
recursion(0, list)
print "*" * 30
for x in main_queue:
print x
la salida es:
******************************
[4, 1]
[4, 1]
[4, 1]
[4, 1]
[4, 1]
Solo cambia la última entrada en la cola principal que hice. ¿Qué estoy haciendo mal?
p.d. ¿Es esta la mejor manera de hacer esto (el rango es entre 1 y 5 y habrá entre 20 y 30 elementos en la lista... es mejor usar la programación dinámica)?
5 Respuestas
2
data = ["dog", "cat"]
upto = 4
def all_combos(items, upto):
if items < 1:
yield []
else:
for r in range(upto+1):
for rest in all_combos(items-1, upto):
yield [r] + rest
for coeffs in all_combos(len(data), upto):
print ", ".join("{}s: {}".format(n, coeff) for n,coeff in zip(data,coeffs))
resultados en
dogs: 0, cats: 0
dogs: 0, cats: 1
dogs: 0, cats: 2
dogs: 0, cats: 3
dogs: 0, cats: 4
dogs: 1, cats: 0
dogs: 1, cats: 1
dogs: 1, cats: 2
dogs: 1, cats: 3
dogs: 1, cats: 4
dogs: 2, cats: 0
dogs: 2, cats: 1
dogs: 2, cats: 2
dogs: 2, cats: 3
dogs: 2, cats: 4
dogs: 3, cats: 0
dogs: 3, cats: 1
dogs: 3, cats: 2
dogs: 3, cats: 3
dogs: 3, cats: 4
dogs: 4, cats: 0
dogs: 4, cats: 1
dogs: 4, cats: 2
dogs: 4, cats: 3
dogs: 4, cats: 4
que es lo que buscas. Ten en cuenta que el número de combinaciones será (len(data))**upto
que aumenta explosivamente a medida que los datos y hasta crecen.
Edit: como se ha señalado, otra forma de lograrlo es
from itertools import product
def all_combos(items, upto):
return product(*(range(upto+1) for i in range(items)))
contestado el 22 de mayo de 12 a las 18:05
1
Tu error es esta línea:
coeff_temp = coeff
Eso no hace una copia de coeff
: que hace referencia al mismo objeto. Cuando lo modificas en la siguiente línea:
coeff_temp[k] = data
Está modificando todos los que ha insertado hasta ahora: ¡todos son la misma lista!
Para copiar realmente la lista, use:
coeff_temp = list(coeff)
or
coeff_temp = coeff[:]
Aquí está la mejor solución a su problema:
import itertools
data = {
"dog": xrange(1, 5),
"cat": xrange(1, 5)
#add more here...
}
combinations = (dict(zip(data.keys(), c)) for c in itertools.product(*data.values()))
for c in combinations:
print c
contestado el 22 de mayo de 12 a las 17:05
Gracias Eric, me di cuenta de que también cometí otro error. Usé list como variable, así que usé tu ejemplo y cambié el nombre de la variable, pero ahora aparece un error. TypeError: 'type' object is not iterable
en el primer bucle for en la función de recursión - Alma perdida
@Error_404 Entonces todavía estás usando list
como variable. - Eric
tienes razón, hubo una instancia que me perdí. Parece que funciona ahora, pero hay resultados duplicados. - Alma perdida
@Error_404: Eche otro vistazo. Lo hice genérico - Eric
Acabo de darme cuenta de eso... gracias. Y gracias por tu respuesta/ayuda. - Alma perdida
1
Me parece que lo que desea es un número de base M de N dígitos, donde N es la cantidad de elementos en la lista y M es la cantidad de valores posibles para cada uno.
Solo por ejemplo, si tuviera 3 elementos en la lista y quisiera valores del 1 al 4 para cada uno, usaría un número de base 3 de 3 dígitos. Como tu primer dígito es 1
, agregaría uno a cada dígito a medida que lo asigna al elemento de la lista.
En esto, la primera columna es el número real a medida que cuentas, y la segunda columna es el mismo número con 1 agregado a cada dígito, luego los valores asignados a cada uno de los tres animales:
000 111 cat 1 dog 1 hamster 1
001 112 cat 1 dog 1 hamster 2
002 113 cat 1 dog 1 hamster 3
010 121 cat 1 dog 2 hamster 1
011 122 cat 1 dog 2 hamster 2
012 123 cat 1 dog 2 hamster 3
020 131 cat 1 dog 3 hamster 1
021 132 cat 1 dog 3 hamster 2
022 133 cat 1 dog 3 hamster 3
100 211 cat 2 dog 1 hamster 1
y así sucesivamente para los números restantes de base 3 de 3 dígitos.
contestado el 22 de mayo de 12 a las 17:05
0
Intenta ver itertools lib http://docs.python.org/library/itertools.html donde puede encontrar la función combinaciones (), debe ayudarlo.
contestado el 22 de mayo de 12 a las 17:05
0
Si desea combinaciones, la recursividad es la respuesta correcta casi todo el tiempo.
Hay un problema con tu código: Dentro del recursion
función, cuando dices coeff_temp = coeff
estás copiando el referencia a coeff
, por lo que solo está agregando la misma lista cada vez. Es por eso . De lo contrario, el método me parece bien.
Cambiar la linea
coeff_temp = coeff
a
coeff_temp = list(coeff)
para copiar la lista y continuar desde allí.
El módulo itertools es una buena solución para combinaciones.
contestado el 23 de mayo de 12 a las 19:05
Lo siento, @Eric ya respondió este mismo problema mientras escribía mi respuesta, así que no la vi hasta que la publiqué. El crédito debe ser para él. - Alejandro Piad
Llegaste primero, mientras yo estaba escribiendo, mira los tiempos. Sin embargo, su razonamiento es incorrecto: el hecho de que coeff
es global es irrelevante. - Eric
@Eric: Seguramente mi explicación no fue lo suficientemente clara. Estaba tratando de decir exactamente lo mismo que tú, que estaba usando una referencia a la misma lista. Ahora veo que no está muy claro, y lo he arreglado. Gracias por el comentario. - Alejandro Piad
No es la respuesta que estás buscando? Examinar otras preguntas etiquetadas python algorithm or haz tu propia pregunta.
No entiendo de su descripción lo que está tratando de lograr. - murgatroid99
Por favor podría proporcionar un completar ejemplo que especificaría claramente la entrada y la salida esperada. - NPE
@ murgatroid99 Tengo un ejemplo de la salida prevista... ¿Qué parte tiene problemas para entender? - Lostsoul
No veo la conexión entre la entrada dada, su descripción de su objetivo y la salida dada. Y la salida real es tan diferente que no parece estar relacionada. - murgatroid99
I pensar quiere todas las combinaciones de 0 a 4 perros, 0 a 4 gatos, 0 a 4 monos, etc. - Hugh Bothwell