Re: [Python-es] Re: Asignación de eventos en Python
Joan Pallarès
joan.pallares en gmail.com
Jue Jul 24 01:55:03 CEST 2008
He copiado y pegado tu codigo y solo he añadido que imprima solucion delante
de cada solucion y que imprima la matriz al final. Bueno y por no cambiar la
lista de parejas y puesto un diccionario, así:
*def parejasAMatriz(p) :
# genera la matriz a partir de la lista de parejas
dict = {'a':1,'b':2,'c':3,'d':4}
nfilas = max([i[0] for i in p])
ncols = max([i[1] for i in p])
NUMncols = dict[ncols]
m = [ list([0]*NUMncols) for i in xrange(nfilas) ]
for f, c in p :
m[f-1][dict[c]-1] = 1
return m*
y me imprime lo que te he puesto antes:
Solucion [0, 1, 2]
Solucion [0, 1, 3]
[[1, 1, 1, 1], [1, 1, 1, 0], [1, 1, 1, 1]]
Debo haber cambiado algo mientras copiaba y pegaba, no valgo ni para eso
xD......:
Entiendo perfectamente lo que es backtracking, y sí, es una buena idea lo
que me dices de las funciones next y prev pero en el caso real que voy a
utilizar este algoritmo sera una matriz de 100x100 o incluso más y no se si
será del todo eficiente calcular todas las soluciones de golpe. Sería mejor
generar una a una según las pidiera el usuario (pero claro no se hacerlo).
Aunque quizá con este sistema de la matriz es muy rápido y lo puedo calcular
todo de golpe. Pero bueno primero tengo que conseguir que me funcione con
este caso sencillo y luego adaptarlo al grande.
Pongo todo el código que me devuelve lo que he dicho antes, que puede pasar
para que no nos devuelva lo mismo?:
*parejas = [(1, 'a'), (1, 'b'), (1, 'c'), (1, 'd'),
(2, 'a'), (2, 'b'), (2, 'c'),
(3, 'a'), (3, 'b'), (3, 'c'), (3, 'd')]
def parejasAMatriz(p) :
# genera la matriz a partir de la lista de parejas
dict = {'a':1,'b':2,'c':3,'d':4}
nfilas = max([i[0] for i in p])
ncols = max([i[1] for i in p])
NUMncols = dict[ncols]
m = [ list([0]*NUMncols) for i in xrange(nfilas) ]
for f, c in p :
m[f-1][dict[c]-1] = 1
return m
def genDisponible(m, e, p) :
# a partir de la matriz y una solucion parcial devuelve una lista
# con las columnas disponibles para una fila determinada
ncols = len(m[0])
res = []
for i in xrange(ncols) :
if i not in e and m[p][i] :
# la columna esta disponible y la asignacion es valida
res.append(i)
return iter(res)
def generaSoluciones(p) :
matriz = parejasAMatriz(p)
nfilas = len(matriz)
ncols = len(matriz[0])
estado = [-1] * nfilas
disponible = [ None ] * nfilas
fila = 0
disponible[fila] = iter(range(ncols))
while True :
while not disponible[fila] :
estado[fila] = -1
fila -= 1 # retrocede
if fila < 0 : # no hay mas soluciones
raise StopIteration()
estado[fila] = disponible[fila].next()
fila += 1
if fila >= nfilas :
yield estado
fila -= 1
else :
disponible[fila] = genDisponible(matriz, estado, fila)
for s in generaSoluciones(parejas) :
print 'Solucion',s
print parejasAMatriz(parejas)*
Voy a la cama que mañana toca madrugar. Muchas gracias Alexis
Saludos
2008/7/23 Alexis Roda <alexis.roda.villalonga en gmail.com>:
> En/na Joan Pallarès ha escrit:
>
>> Hola,
>>
>> Muchas gracias con tu ayuda. Aunque me interesa alguna forma "más
>> elegante"
>> de volver atrás"
>>
>
> En backtracking, volver atrás no significa encontrar la solución "anterior"
> (que me parece que es lo que quieres) sino retroceder, deshaciendo el último
> "cambio" y probando otra posibilidad para encontrar la "siguiente" solución.
>
>
> Para lo que (creo que) quieres solo tienes que implementa una clase con dos
> metodos, prev y next, una lista que almacene las soluciones encontradas
> hasta el momento y el indice de la "solución actual". Si al llamar a next no
> quedan "soluciones anteriores" se calcula una nueva solución y se almacena
> en la lista.
>
> class Soluciones :
> def __init__(self, parejas) :
> self._encontrado = []
> self._indice = 0
> matr = parejasAMatriz(parejas)
> self._generador = iter(generaSoluciones(matr))
>
> def next(self) :
> if self._indice >= len(self._encontrado) :
> self._encontrado.append(list(self._generador.next()))
> self._indice += 1
> return self._encontrado[self._indice - 1]
>
> def prev(self) :
> if self._indice <= 0 :
> return None
> self._indice -= 1
> return self._encontrado[self._indice]
>
> Deberías añadir alguna comprobación extra para el caso que se agoten todas
> las soluciones y asegurarte que las comprobaciones que hace son correctas.
>
>
> acabo de usar tu codigo y me escupe esto:
>>
>> Solucion [0, 1, 2]
>> Solucion [0, 1, 3]
>> [[1, 1, 1, 1], [1, 1, 1, 0], [1, 1, 1, 1]]
>>
>
> No entiendo de donde sale la última linea. Mi código no imprime la matriz!
>
> por lo que no hace bactracking, no?
>>
>
> El bucle "while not disponible[fila]" implementa el retroceso: si no quedan
> posibilidades para una posición retrocede una posición para seguir probando.
>
> te has olvidado algo? o yo me he dejado algo?
>>
>
> Al ejecutarlo me imprime:
>
> [0, 1, 2]
> [0, 1, 3]
> ...
> [3, 2, 0]
> [3, 2, 1]
>
>
>
>
> Saludos
> _______________________________________________
> Lista de correo Python-es http://listas.aditel.org/listinfo/python-es
> FAQ: http://listas.aditel.org/faqpyes
>
Más información sobre la lista de distribución Python-es