algoritmo-8-reinas-iv

11
ALGORITMO 8 REINAS METODOLOGIA ~ 1 ~ ALGORITMO 8 REINAS Sabiendo el movimiento de la pieza de la reina en un tablero de ajedrez encontrar las posiciones de 8 reinas en el mismo tablero para que ninguna pueda comer a las otras 7 y por tanto tampoco ser comida. (Investigando un poco encuentro que para este problema clásico hay 92 soluciones) Primera valoración del ejercicio No se puede repetir fila ni columna No se puede repetir diagonal En cada fila solo 1 reina En cada columna sólo 1 reina Marcar filas y columnas ocupadas El algoritmo se podría definir con dos líneas como. “Probar a colocar la reina de la fila i-ésima en cada una de las posiciones disponibles.” “Colocar las reinas restantes operando de modo recursivo.”

Transcript of algoritmo-8-reinas-iv

Page 1: algoritmo-8-reinas-iv

ALGORITMO8 REINAS METODOLOGIA ~ 1 ~

ALGORITMO 8 REINAS

Sabiendo el movimiento de la pieza de la reina en un tablero de ajedrez encontrar las posiciones de 8 reinas en el mismo tablero para que ninguna pueda comer a las otras 7 y por tanto tampoco ser comida. (Investigando un poco encuentro que para este problema clásico hay 92 soluciones)

Primera valoración del ejercicio

No se puede repetir fila ni columna

No se puede repetir diagonal

En cada fila solo 1 reina

En cada columna sólo 1 reina

Marcar filas y columnas ocupadas

El algoritmo se podría definir con dos líneas como.

“Probar a colocar la reina de la fila i-ésima en cada una de las posiciones disponibles.”

“Colocar las reinas restantes operando de modo recursivo.”

Page 2: algoritmo-8-reinas-iv

ALGORITMO8 REINAS METODOLOGIA ~ 2 ~

Estado Inicial

Las reinas que hay

Estado final

Las posiciones que quedan libres

Procesamiento

Colocar ficha en lugar permitido y no ocupado

ENT Columnas ocupadas por vacías anteriores

SALIDA Columnas disponibles

Creación del pseudocódigo

Disponibles(ocup). //recibe un vector o una lista con

d=[0,1,2,3,4,5,6,7]

k= tamaño(ocup)

Para cada c en ocup:

Eliminar c de d

Eliminar (c+k) de d

Eliminar (c-k) de d

K - -

devolver d

caso concreto

ocup=[3 5 0 4]

k=4 3 2 1

d=[0 1 2 3 4 5 6 7]

Page 3: algoritmo-8-reinas-iv

ALGORITMO8 REINAS METODOLOGIA ~ 3 ~Date: 2010-07-29

IMPLEMENTACIÓN ALGORITMO 8 REINAS EN JAVA

Implementamos el método disponibles y comprobamos si funciona para un caso concreto.

import java.util.Iterator;import java.util.LinkedList;import java.util.List;/** * @author nessy* */public class OchoReinas {

//PSEUDOCODIGO// Disponibles(ocup). //recibe un vector o una lista con // d=[0,1,2,3,4,5,6,7]// k= tamaño(ocup)// Para cada c en ocup:// Eliminar c de d// Eliminar (c+k) de d// Eliminar (c-k) de d// K - -// devolver d/**Este método sirve para determinar las columnas en las que * se puede colocar la siguiente reina, habiéndose puesto ya algunas * reinas cuyas columnas se dan * @param ocup Columnas que ocupan las reinas previas * @return Columnas disponibles sin comerse */public static List<Integer> disponibles(List<Integer>ocup){

//creamos la lista de disponibles que inicialmente tiene todas las columnas

// d=[0,1,2,3,4,5,6,7]List<Integer> d= new LinkedList<Integer>();//podría haber utilizado un

ArrayListfor(int i=0;i<8;i++){

d.add(new Integer(i));}//averiguamos cuántas reinas hay ya colocadas y lo guardamos en la

variable k// k= tamaño(ocup)int k=ocup.size();/*recorremos la lista de columnas ocupadas para ir tachando los lugares

que * no nos vale. Podriamos hacerlo con un for, pero para listas mejor el

Iterator*///Para cada c en ocup:// Eliminar c de d// Eliminar (c+k) de d// Eliminar (c-k) de d// K - -for (Iterator<Integer> j=ocup.iterator();j.hasNext();k--){

Integer c=j.next();//trabajamos con objetos que contienen números enteros por eso uso

el removed.remove(c);d.remove(new Integer(c.intValue()+k));d.remove(new Integer(c.intValue()-k));

}//finalmente devolvemos lo que nos queda//devolver dreturn d;

}

Page 4: algoritmo-8-reinas-iv

ALGORITMO8 REINAS METODOLOGIA ~ 4 ~

public static void main(String[] args) {/* Creo un ejemplo para ver si la funcion disponibles funciona bien*//* Creamos la lista de prueba*/LinkedList<Integer> a = new LinkedList<Integer>();a.add(new Integer(3));a.add(new Integer(5));/* Creo otra lista para guardar lo que devuelve el método disponibles*/ List<Integer> z = disponibles(a);for (Iterator<Integer> j=z.iterator();j.hasNext();){

System.out.println(j.next().intValue());}

}}

ALGORITMO RESOLVER

MEJORA. Pseudocódigo del método resolver que nos va a mostrar las 92 soluciones posibles de colocar las 8 reinas.

resolver(ocup):si tamaño(ocup)<8:d←disponibles(ocup)para cada c en d:

resolver(ocup+c)en caso contrario:

mostrar soluciónimport java.util.Iterator;import java.util.LinkedList;import java.util.List;/** * @author nessy* */public class OchoReinas {

static int cont=0;//para contar el número de soluciones del método resolver//PSEUDOCODIGO// Disponibles(ocup). //recibe un vector o una lista con // d=[0,1,2,3,4,5,6,7]// k= tamaño(ocup)// Para cada c en ocup:// Eliminar c de d// Eliminar (c+k) de d// Eliminar (c-k) de d// K - -// devolver d/**Este método sirve para determinar las columnas en las que * se puede colocar la siguiente reina, habiéndose puesto ya algunas * reinas cuyas columnas se dan * @param ocup Columnas que ocupan las reinas previas * @return Columnas disponibles sin comerse */public static List<Integer> disponibles(List<Integer>ocup){

//creamos la lista de disponibles que inicialmente tiene todas las columnas

// d=[0,1,2,3,4,5,6,7]List<Integer> d= new LinkedList<Integer>();//podría haber utilizado un

ArrayListfor(int i=0;i<8;i++){

d.add(new Integer(i));}//averiguamos cuántas reinas hay ya colocadas y lo guardamos en la

variable k

Page 5: algoritmo-8-reinas-iv

ALGORITMO8 REINAS METODOLOGIA ~ 5 ~

// k= tamaño(ocup)int k=ocup.size();/*recorremos la lista de columnas ocupadas para ir tachando los lugares

que * no nos vale. Podriamos hacerlo con un for, pero para listas mejor el

Iterator*///Para cada c en ocup:// Eliminar c de d// Eliminar (c+k) de d// Eliminar (c-k) de d// K - -for (Iterator<Integer> j=ocup.iterator();j.hasNext();k--){

Integer c=j.next();//trabajamos con objetos que contienen números enteros por eso uso

el removed.remove(c);d.remove(new Integer(c.intValue()+k));d.remove(new Integer(c.intValue()-k));

}//finalmente devolvemos lo que nos queda//devolver dreturn d;

}// resolver(ocup):// si tamaño(ocup)<8:// d=disponibles(ocup)// para cada c en d:// resolver(ocup+c)// en caso contrario:// mostrar solución/** Encuentra todas las soluciones para el problema de las 8 reinas * @param ocup Lista con las ocupaciones previas, siendo su valor inicial una

lista vacía * resolver(ocup): * si tamaño(ocup)<8: * d=disponibles(ocup) * para cada c en d: * resolver(ocup+c) * en caso contrario: * mostrar solución */public static void resolver(List<Integer> ocup){

// si tenemos ya 8 reinas ubicadas, es que encontramos una solución, si no, hay que iterar recursivamente

if (ocup.size()<8){// d=disponibles(ocup)List<Integer> d = disponibles(ocup);// para cada c en d:for (Iterator<Integer> c=d.iterator();c.hasNext();){

//resolver(ocup+c) Aquí tengo que crear una lista provisionalList<Integer> provisional = new LinkedList<Integer>(ocup);provisional.add(c.next());resolver(provisional);

}}else{

//mostramos la solución por pantalla como una lineaString solucion="";for (Iterator<Integer> j=ocup.iterator();j.hasNext();){

solucion += j.next().intValue();}cont++;

Page 6: algoritmo-8-reinas-iv

ALGORITMO8 REINAS METODOLOGIA ~ 6 ~

System.out.println("Solucion " + cont+" "+solucion + " ");}

}

public static void main(String[] args) {//1 OPCION con el método disponibles/* Creo un ejemplo para ver si la funcion disponibles funciona bien*//* Creamos la lista de prueba*/LinkedList<Integer> a = new LinkedList<Integer>();a.add(new Integer(3));a.add(new Integer(5));/* Creo otra lista para guardar lo que devuelve el método disponibles*/ List<Integer> z = disponibles(a);for (Iterator<Integer> j=z.iterator();j.hasNext();){

System.out.println(j.next().intValue());}// 2 OPCION con el algoritmo resolverLinkedList<Integer> b = new LinkedList<Integer>();System.out.println("La solucón con el método resolver es: ");resolver(b);

}}

Page 7: algoritmo-8-reinas-iv

ALGORITMO8 REINAS METODOLOGIA ~ 7 ~Date 2010-07-30

MEJORA. Mostrar la salida del programa de forma que muestre “simbólicamente” el tablero poniendo en los huecos un punto y donde hay una reina un asterisco.

Para ello crearemos el método pintaTablero( ).

El pseudocódigo sería.

para i=0 hasta 7fila=””r= elemento i de reinas // en java seria int r=reinas.get(i).intValue();para j=0 hasta 7

si (j = = r): fila +=’*’en caso contrario: fila +=’.’

imprimir fila

El método pintaTablero tiene esta pinta:

public static void pintaTablero(List<Integer>reinas){for (int i=0;i<8;i++){

String fila="";int r=reinas.get(i).intValue();for(int j=0;j<8;j++){

if (j == r){fila +='*';

}else{fila +='·';

}}System.out.println(fila);

}

Para comprobar su funcionamiento:

1ª Opción: Creo un ejemplo con una solución posible y luego se la envío al método pintaTablero para que la muestre

Para ello en el main incluyo:

//MEJORA. Visualizar el resultado en un tablero//Aqui creo "a mano" un caso concreto y luego lo pinto con //el método pintaTableroLinkedList<Integer> p = new LinkedList<Integer>();p.add(new Integer(0));p.add(new Integer(4));p.add(new Integer(7));p.add(new Integer(5));p.add(new Integer(2));p.add(new Integer(6));p.add(new Integer(1));p.add(new Integer(3));pintaTablero(p);

Page 8: algoritmo-8-reinas-iv

ALGORITMO8 REINAS METODOLOGIA ~ 8 ~2ª opción. Que pinte el tablero justo después de obtener cada opción posible

Para ello en el método Resolver hacemos una llamada al método pintarTablero, quedando el método:

public static void resolver(List<Integer> ocup){// si tenemos ya 8 reinas ubicadas, es que encontramos una solución, si

no, hay que iterar recursivamenteif (ocup.size()<8){

// d=disponibles(ocup)List<Integer> d = disponibles(ocup);// para cada c en d:for (Iterator<Integer> c=d.iterator();c.hasNext();){

//resolver(ocup+c) Aquí tengo que crear una lista provisionalList<Integer> provisional = new LinkedList<Integer>(ocup);provisional.add(c.next());resolver(provisional);

}}else{

//mostramos la solución por pantalla como una lineaString solucion="";for (Iterator<Integer> j=ocup.iterator();j.hasNext();){

solucion += j.next().intValue();}cont++;System.out.println("Solucion " + cont+" "+solucion + " ");pintaTablero(ocup);// con esta línea "pinta" todos los tableros

posibles}

}

Para mostrar solo la primera posibilidad posible que devuelve el método resolver

De momento esto queda pendiente