Resolver un tablero 0h n0


19

0h n0 es un juego muy simple y divertido, un poco como Sudoku o buscaminas.

Reglas del juego

(Recomiendo usar el tutorial en el juego si puedes, es muy simple y útil)

El rompecabezas comienza con un n * ntablero que contiene algunas piezas fijas y algunas celdas vacías, y el solucionador debe encontrar una manera de llenar las celdas vacías con piezas y satisfacer todas las restricciones impuestas por las piezas fijas. Estos son los tipos de piezas que utilizaremos con la abreviatura:

  • # Pieza roja (bloquea la vista de una pieza azul)
  • O Pieza azul
  • . Lugar vacío
  • numberPieza azul numerada ( numberes un número de un dígito> 0)

Todas las piezas numeradas deben ver exactamente la misma cantidad de piezas azules que el número. Por ejemplo:

#1O#O
...O.

La 1pieza solo puede ver otra pieza azul.

Cómo se ven las piezas

Dos piezas azules se pueden ver si están en la misma fila o columna y no hay una pieza roja entre ellas. Ejemplo:

( Ses una ubicación que la Opieza puede ver, Xno se puede ver)

   S
   S
X#SOSS
   #
   X

Cada pieza azul debe ver al menos otra pieza azul:

#O#

No funcionará, pero:

#OO

O:

###

Hacer trabajo.

Tablero de demostración resolver

.1..
..1.
....
22#2

La parte inferior derecha 2 solo puede ver por encima de sí misma, por lo que debe ser azul y la parte superior derecha debe ser roja.

.1.#
..1O
...O
22#2

Como 1está lleno, podemos rodearlo con piezas rojas.

.1##
.#1O
..#O
22#2

La parte superior izquierda 1solo puede ver en una dirección ahora, por lo que podemos completarlo.

O1##
.#1O
..#O
22#2

Ahora sobre esos últimos 2s. Podemos poner 2 piezas azules sobre ellas.

O1##
.#1O
OO#O
22#2

El último estará lleno de #

O1##
##1O
OO#O
22#2

Entrada

La entrada es una cadena de varias líneas. El tamaño será 9x9sin espacio final. Tiene los siguientes tipos de piezas:

  • . Vacío
  • # Rojo preestablecido, no se puede cambiar
  • number Número preestablecido, no se puede cambiar

(Tenga en cuenta que el azul nunca estará en la entrada)

Salida

La salida es lo mismo que la entrada, con el cambio de que empty ( .) se reemplaza con rojo o azul para resolver el tablero, y los números se reemplazan con piezas azules ( O).

Ejemplos

(Tenga en cuenta que pueden ser posibles varias soluciones para cada rompecabezas, pero solo necesita mostrar una de ellas)

Input:
........4
...3.1...
45...2.3.
..9......
1..6#44..
....4..5.
....4.36.
2.......6
1....4...

Output:
OOO###OOO
OOOO#O#OO
OOO#OO#OO
#OOOO#O##
O#OO#OOOO
O#OOOO#OO
#OOOO#OOO
OO#O#OOOO
O#OOOO#O#

Input:
..7..#...
#...8..11
2....5...
..5...48.
...#...4.
.5...6...
...1.2...
2.....6.8
.7..#....

Output:
OOOOO####
##OOOO#OO
O#OOOO###
OOO#OOOOO
OO##O##O#
#O##OOOOO
#O#O#O#OO
OO#OOOOOO
OOO###O#O

Input:
5.3..33..
...4...23
.6.6.34..
...3#....
....5..4.
.5....3..
7.98.6#.3
.5.6..2..
..6...2..

Output:
OOOOO####
##OOOO#OO
O#OOOO###
OOO#OOOOO
OO##O##O#
#O##OOOOO
#O#O#O#OO
OO#OOOOOO
OOO###O#O

¡Gracias a @PeterTaylor y @apsillers por toda su ayuda en el sandbox!


Hice una edición muy pequeña del título porque "an" suena mejor si la siguiente palabra comienza con una vocal: no espero que los hablantes no nativos de inglés o incluso los hablantes nativos se molesten con eso, pero es gramatical.
gato

Respuestas:


2

Haskell, 224 bytes

No completamente probado, porque es muy lento (al menos O(n*2^n^2)).

t=1<2
x!p|p<0=0|t=mod(div x$2^p)2
l#x=[[sum$map(p&)[-1,1,l+1,-l-1]|p<-[q..q+l]]|q<-[0,l..l*l],let i&v|x!i<1=0|t=x!(i+v)+(i+v)&v]
b%v|b<1=t|t=b==v
s b|l<-length b-1=[l#x|x<-[0..2^l^2],and.map and$zipWith(zipWith(%))b(l#x)]!!0

Explicación:

La idea básica es representar un tablero de Red, Bluepiezas como una lista de listas de 0, 1, donde la lista de listas se empaqueta en un solo entero para una enumeración más fácil. Todos estos enteros para el tamaño del tablero se generan y se convierten en un formulario con recuentos de vecinos. Se devuelve la primera placa de este tipo que es una solución válida de la entrada.

-- integer x at position p with out of bounds defined to be 0 (so no bounds checking)
(!) :: (Integral b, Integral r) => r -> b -> r
x ! p | p < 0     = 0 
      | otherwise = mod (div x (2^p)) 2


-- Sum of values from position p along vector v (x is implicit)
-- Note that a cartesian vector (x,y) in this representation is (l*x + y)
(&) :: (Integral a, Integral b) => b -> b -> a
p & v | x ! p == 0 = 0
      | otherwise  = x ! (p+v)  +  (p+v) & v


-- Value of board at position p (implicit x, l)
value :: Integral a => a -> a
value p = sum $ map (p&) [-1, 1, l+1, -l-1]


-- Integer to board, where l is length, x is input integer
(#) :: (Integral t, Integral a) => a -> t -> [[t]]
l # x = [[sum $ map (p&) [-1,1,l+1,-l-1] | p <- [q..q+l-1]] | q <- [0,l..l*l]]


-- Comparison operator, to see whether a solved board is a solution of the input
(%) :: (Num a, Ord a) => a -> a -> Bool
b % v | b == 0    = True
      | otherwise = b == v


-- Check one possible solution
check :: Integral a => [[a]] -> Int -> [[a]] -> Bool
check b l x = (and . (map and)) zipWith(zipWith (%)) b (l # x)

-- Solver
solve :: Integral t => [[t]] -> [[t]]
solve b = [l # x | x <- [0..2^l^2], check b l x]
  where
    l = length b

La parte que probablemente podría ser más golfed es: and.map and$zipWith(zipWith(%)). De lo contrario, detecté algunos errores fuera de uno que agregaron longitud y probablemente podrían jugar más.

Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.