El problema de las N reinas consiste en colocar N reinas en tablero rectangular de dimensiones N por N de forma que no se encuentren más de una en la misma línea: horizontal, vertical o diagonal. Por ejemplo, una solución para el problema de las 4 reinas es
|---|---|---|---|
| | R | | |
|---|---|---|---|
| | | | R |
|---|---|---|---|
| R | | | |
|---|---|---|---|
| | | R | |
|---|---|---|---| |
|---|---|---|---|
| | R | | |
|---|---|---|---|
| | | | R |
|---|---|---|---|
| R | | | |
|---|---|---|---|
| | | R | |
|---|---|---|---|
Los estados del problema de las N reinas son los tableros con las reinas colocadas. Inicialmente el tablero está vacío y, en cda paso se coloca una reina en la primera columna en la que aún no hay ninguna reina.
Cada estado se representa por una lista de números que indican las filas donde se han colocado las reinas. Por ejemplo, el tablero anterior se representa por [2,4,1,3].
Usando la librería de árboles Data.Tree, definir las funciones
arbolReinas :: Int -> Tree [Int]
nEstados :: Int -> Int
soluciones :: Int -> [[Int]]
nSoluciones :: Int -> Int |
arbolReinas :: Int -> Tree [Int]
nEstados :: Int -> Int
soluciones :: Int -> [[Int]]
nSoluciones :: Int -> Int
tales que
- (arbolReinas n) es el árbol de estados para el problema de las n reinas. Por ejemplo,
λ> putStrLn (drawTree (fmap show (arbolReinas 4)))
[]
|
+- [1]
| |
| +- [3,1]
| |
| `- [4,1]
| |
| `- [2,4,1]
|
+- [2]
| |
| `- [4,2]
| |
| `- [1,4,2]
| |
| `- [3,1,4,2]
|
+- [3]
| |
| `- [1,3]
| |
| `- [4,1,3]
| |
| `- [2,4,1,3]
|
`- [4]
|
+- [1,4]
| |
| `- [3,1,4]
|
`- [2,4]
λ> putStrLn (drawTree (fmap show (arbolReinas 5)))
[]
|
+- [1]
| |
| +- [3,1]
| | |
| | `- [5,3,1]
| | |
| | `- [2,5,3,1]
| | |
| | `- [4,2,5,3,1]
| |
| +- [4,1]
| | |
| | `- [2,4,1]
| | |
| | `- [5,2,4,1]
| | |
| | `- [3,5,2,4,1]
| |
| `- [5,1]
| |
| `- [2,5,1]
|
+- [2]
| |
| +- [4,2]
| | |
| | `- [1,4,2]
| | |
| | `- [3,1,4,2]
| | |
| | `- [5,3,1,4,2]
| |
| `- [5,2]
| |
| +- [1,5,2]
| | |
| | `- [4,1,5,2]
| |
| `- [3,5,2]
| |
| `- [1,3,5,2]
| |
| `- [4,1,3,5,2]
|
+- [3]
| |
| +- [1,3]
| | |
| | `- [4,1,3]
| | |
| | `- [2,4,1,3]
| | |
| | `- [5,2,4,1,3]
| |
| `- [5,3]
| |
| `- [2,5,3]
| |
| `- [4,2,5,3]
| |
| `- [1,4,2,5,3]
|
+- [4]
| |
| +- [1,4]
| | |
| | +- [3,1,4]
| | | |
| | | `- [5,3,1,4]
| | | |
| | | `- [2,5,3,1,4]
| | |
| | `- [5,1,4]
| | |
| | `- [2,5,1,4]
| |
| `- [2,4]
| |
| `- [5,2,4]
| |
| `- [3,5,2,4]
| |
| `- [1,3,5,2,4]
|
`- [5]
|
+- [1,5]
| |
| `- [4,1,5]
|
+- [2,5]
| |
| `- [4,2,5]
| |
| `- [1,4,2,5]
| |
| `- [3,1,4,2,5]
|
`- [3,5]
|
`- [1,3,5]
|
`- [4,1,3,5]
|
`- [2,4,1,3,5] |
λ> putStrLn (drawTree (fmap show (arbolReinas 4)))
[]
|
+- [1]
| |
| +- [3,1]
| |
| `- [4,1]
| |
| `- [2,4,1]
|
+- [2]
| |
| `- [4,2]
| |
| `- [1,4,2]
| |
| `- [3,1,4,2]
|
+- [3]
| |
| `- [1,3]
| |
| `- [4,1,3]
| |
| `- [2,4,1,3]
|
`- [4]
|
+- [1,4]
| |
| `- [3,1,4]
|
`- [2,4]
λ> putStrLn (drawTree (fmap show (arbolReinas 5)))
[]
|
+- [1]
| |
| +- [3,1]
| | |
| | `- [5,3,1]
| | |
| | `- [2,5,3,1]
| | |
| | `- [4,2,5,3,1]
| |
| +- [4,1]
| | |
| | `- [2,4,1]
| | |
| | `- [5,2,4,1]
| | |
| | `- [3,5,2,4,1]
| |
| `- [5,1]
| |
| `- [2,5,1]
|
+- [2]
| |
| +- [4,2]
| | |
| | `- [1,4,2]
| | |
| | `- [3,1,4,2]
| | |
| | `- [5,3,1,4,2]
| |
| `- [5,2]
| |
| +- [1,5,2]
| | |
| | `- [4,1,5,2]
| |
| `- [3,5,2]
| |
| `- [1,3,5,2]
| |
| `- [4,1,3,5,2]
|
+- [3]
| |
| +- [1,3]
| | |
| | `- [4,1,3]
| | |
| | `- [2,4,1,3]
| | |
| | `- [5,2,4,1,3]
| |
| `- [5,3]
| |
| `- [2,5,3]
| |
| `- [4,2,5,3]
| |
| `- [1,4,2,5,3]
|
+- [4]
| |
| +- [1,4]
| | |
| | +- [3,1,4]
| | | |
| | | `- [5,3,1,4]
| | | |
| | | `- [2,5,3,1,4]
| | |
| | `- [5,1,4]
| | |
| | `- [2,5,1,4]
| |
| `- [2,4]
| |
| `- [5,2,4]
| |
| `- [3,5,2,4]
| |
| `- [1,3,5,2,4]
|
`- [5]
|
+- [1,5]
| |
| `- [4,1,5]
|
+- [2,5]
| |
| `- [4,2,5]
| |
| `- [1,4,2,5]
| |
| `- [3,1,4,2,5]
|
`- [3,5]
|
`- [1,3,5]
|
`- [4,1,3,5]
|
`- [2,4,1,3,5]
- (nEstados n) es el número de estados en el problema de las n reinas. Por ejemplo,
nEstados 4 == 17
nEstados 5 == 54
map nEstados [0..10] == [1,2,3,6,17,54,153,552,2057,8394,35539] |
nEstados 4 == 17
nEstados 5 == 54
map nEstados [0..10] == [1,2,3,6,17,54,153,552,2057,8394,35539]
- (soluciones n) es la lista de estados que son soluciones del problema de las n reinas. Por ejemplo,
λ> soluciones 4
[[3,1,4,2],[2,4,1,3]]
λ> soluciones 5
[[4,2,5,3,1],[3,5,2,4,1],[5,3,1,4,2],[4,1,3,5,2],[5,2,4,1,3],
[1,4,2,5,3],[2,5,3,1,4],[1,3,5,2,4],[3,1,4,2,5],[2,4,1,3,5]] |
λ> soluciones 4
[[3,1,4,2],[2,4,1,3]]
λ> soluciones 5
[[4,2,5,3,1],[3,5,2,4,1],[5,3,1,4,2],[4,1,3,5,2],[5,2,4,1,3],
[1,4,2,5,3],[2,5,3,1,4],[1,3,5,2,4],[3,1,4,2,5],[2,4,1,3,5]]
- (nSoluciones n) es el número de soluciones del problema de las n reinas. Por ejemplo,
nSoluciones 4 == 2
nSoluciones 5 == 10
map nSoluciones [0..10] == [1,1,0,0,2,10,4,40,92,352,724] |
nSoluciones 4 == 2
nSoluciones 5 == 10
map nSoluciones [0..10] == [1,1,0,0,2,10,4,40,92,352,724]
Soluciones
import Data.List ((\\))
import Data.Tree
-- Definición de arbolReinas
-- =========================
arbolReinas :: Int -> Tree [Int]
arbolReinas n = expansion n []
where
expansion m xs = Node xs [expansion (m-1) ys | ys <- sucesores n xs]
-- (sucesores n xs) es la lista de los sucesores del estado xs en el
-- problema de las n reinas. Por ejemplo,
-- sucesores 4 [] == [[1],[2],[3],[4]]
-- sucesores 4 [1] == [[3,1],[4,1]]
-- sucesores 4 [4,1] == [[2,4,1]]
-- sucesores 4 [2,4,1] == []
sucesores :: Int -> [Int] -> [[Int]]
sucesores n xs = [y:xs | y <- [1..n] \\ xs
, noAtaca y xs 1]
-- (noAtaca y xs d) se verifica si la reina en la fila y no ataca a las
-- colocadas en las filas xs donde d es el número de columnas desde la
-- de la posición de x a la primera de xs.
noAtaca :: Int -> [Int] -> Int -> Bool
noAtaca _ [] _ = True
noAtaca y (x:xs) distH = abs(y-x) /= distH &&
noAtaca y xs (distH + 1)
-- Definición de nEstados
-- ======================
nEstados :: Int -> Int
nEstados = length . arbolReinas
-- Definición de solucionesReinas
-- ==============================
-- λ> soluciones 4
-- [[3,1,4,2],[2,4,1,3]]
-- λ> soluciones 5
-- [[4,2,5,3,1],[3,5,2,4,1],[5,3,1,4,2],[4,1,3,5,2],[5,2,4,1,3],
-- [1,4,2,5,3],[2,5,3,1,4],[1,3,5,2,4],[3,1,4,2,5],[2,4,1,3,5]]
soluciones :: Int -> [[Int]]
soluciones n =
filter (\xs -> length xs == n) (estados n)
-- (estados n) es la lista de estados del problema de las n reinas. Por
-- ejemplo,
-- λ> estados 4
-- [[],
-- [1],[2],[3],[4],
-- [3,1],[4,1],[4,2],[1,3],[1,4],[2,4],
-- [2,4,1],[1,4,2],[4,1,3],[3,1,4],
-- [3,1,4,2],[2,4,1,3]]
estados :: Int -> [[Int]]
estados = concat . levels . arbolReinas
-- Definición de nSoluciones
-- =========================
nSoluciones :: Int -> Int
nSoluciones = length . soluciones |
import Data.List ((\\))
import Data.Tree
-- Definición de arbolReinas
-- =========================
arbolReinas :: Int -> Tree [Int]
arbolReinas n = expansion n []
where
expansion m xs = Node xs [expansion (m-1) ys | ys <- sucesores n xs]
-- (sucesores n xs) es la lista de los sucesores del estado xs en el
-- problema de las n reinas. Por ejemplo,
-- sucesores 4 [] == [[1],[2],[3],[4]]
-- sucesores 4 [1] == [[3,1],[4,1]]
-- sucesores 4 [4,1] == [[2,4,1]]
-- sucesores 4 [2,4,1] == []
sucesores :: Int -> [Int] -> [[Int]]
sucesores n xs = [y:xs | y <- [1..n] \\ xs
, noAtaca y xs 1]
-- (noAtaca y xs d) se verifica si la reina en la fila y no ataca a las
-- colocadas en las filas xs donde d es el número de columnas desde la
-- de la posición de x a la primera de xs.
noAtaca :: Int -> [Int] -> Int -> Bool
noAtaca _ [] _ = True
noAtaca y (x:xs) distH = abs(y-x) /= distH &&
noAtaca y xs (distH + 1)
-- Definición de nEstados
-- ======================
nEstados :: Int -> Int
nEstados = length . arbolReinas
-- Definición de solucionesReinas
-- ==============================
-- λ> soluciones 4
-- [[3,1,4,2],[2,4,1,3]]
-- λ> soluciones 5
-- [[4,2,5,3,1],[3,5,2,4,1],[5,3,1,4,2],[4,1,3,5,2],[5,2,4,1,3],
-- [1,4,2,5,3],[2,5,3,1,4],[1,3,5,2,4],[3,1,4,2,5],[2,4,1,3,5]]
soluciones :: Int -> [[Int]]
soluciones n =
filter (\xs -> length xs == n) (estados n)
-- (estados n) es la lista de estados del problema de las n reinas. Por
-- ejemplo,
-- λ> estados 4
-- [[],
-- [1],[2],[3],[4],
-- [3,1],[4,1],[4,2],[1,3],[1,4],[2,4],
-- [2,4,1],[1,4,2],[4,1,3],[3,1,4],
-- [3,1,4,2],[2,4,1,3]]
estados :: Int -> [[Int]]
estados = concat . levels . arbolReinas
-- Definición de nSoluciones
-- =========================
nSoluciones :: Int -> Int
nSoluciones = length . soluciones