Buscaminas es un popular juego de rompecabezas en el que debes descubrir qué fichas son "minas" sin hacer clic en esas fichas. En cambio, haces clic en las fichas cercanas para revelar la cantidad de minas adyacentes. Una desventaja del juego es que es posible terminar en un escenario donde hay múltiples respuestas válidas y solo puedes adivinar. Por ejemplo, tome la siguiente tabla:
1110
2*31
3*??
2*4?
112?
En este formato, un número representa el número de minas adyacentes, un *
representa una mina conocida y un "?" representa una mina potencial. Lo desafortunado de este rompecabezas en particular es que hay cuatro soluciones potenciales distintas y válidas :
1110 1110 1110 1110
2*31 2*31 2*31 2*31
3*4* 3*5* 3**2 3**1
2*42 2*4* 2*4* 2*42
112* 1121 1121 112*
Esto significa que el tablero no tiene solución . Aquí hay un ejemplo de una placa solucionable :
1121
1??*
12?*
0122
Esta placa es solucionable porque solo hay una posible solución válida:
1121
1*4*
12**
0122
Su tarea es escribir un programa o función que tome un tablero de buscaminas válido y determine si es solucionable o no. Por "tablero de buscaminas válido", quiero decir que la entrada siempre será rectangular, tendrá al menos una solución y no contendrá ningún carácter no válido.
Su entrada puede ser una matriz de caracteres, una matriz de cadenas, una cadena que contiene nuevas líneas, etc. La salida debe ser un valor verdadero si es solucionable y un valor falso si no lo es. No estoy extremadamente preocupado por el rendimiento, pero su solución debe funcionar teóricamente para cualquier entrada de tamaño.
Como de costumbre, se aplican las lagunas estándar y gana la solución más corta en bytes.
Ejemplos:
Los siguientes ejemplos tienen solución:
1121
1??*
12?*
0122
1110
1???
1110
0000
1110
3???
??20
*310
****
****
****
****
0000
0000
0000
0000
1100
*100
2321
??*2
13*2
1221
1*10
1110
1121
2*??
2*31
2220
1*10
Los siguientes ejemplos son todos irresolubles:
1110
2*31
3*??
2*4?
112?
01??11*211
12??2323*1
1*33*2*210
12?2122321
13?3101**1
1***101221
1***
3*52
2*31
12??
02??
01??
00000111
000012*1
00001*21
22101110
**100111
?31123*1
?311**31
**113*20
fuente
2?
no tiene soluciones, lo que significa que no puede provenir de un juego real de Buscaminas. Por lo tanto, no se considera un "tablero de Buscaminas" ... ¿sí?)Respuestas:
GNU Prolog, 493 bytes
Un predicado adicional que puede ser útil para la prueba (no forma parte del envío):
Prolog es definitivamente el lenguaje correcto para resolver esta tarea desde el punto de vista práctico. Este programa simplemente establece las reglas de Buscaminas y permite que el solucionador de restricciones de GNU Prolog resuelva el problema desde allí.
z
yi
son funciones de utilidad (z
realiza una especie de operación tipo pliegue pero en conjuntos de tres elementos adyacentes en lugar de 2;i
transpone 3 listas de n elementos en una lista de n 3-tuplas). Almacenamos internamente una celda como , donde x es 1 para una mina y 0 para una no mina, e y es el número de minas adyacentes; expresa esta restricción en el tablero. se aplica a cada fila del tablero; y entonces verifica si es un tablero válido.x/y
c
r
c
z(r,M)
M
Desafortunadamente, el formato de entrada requerido para que esto funcione directamente no es razonable, por lo que también tuve que incluir un analizador (que probablemente representa más código que el motor de reglas real, y la mayor parte del tiempo dedicado a la depuración; el motor de reglas del Buscaminas funcionaba bastante bien) primera vez, pero el analizador estaba lleno de thinkos).
q
Convierte una sola celda entre un código de caracteres y nuestro formato. convierte una línea del tablero (dejando una celda que se sabe que no es una mina, pero con un número desconocido de minas vecinas, en cada borde de la línea como borde);x/y
l
p
convierte todo el tablero (incluido el borde inferior, pero excluyendo el superior). Todas estas funciones pueden ejecutarse hacia adelante o hacia atrás, por lo tanto, pueden analizar e imprimir el tablero. (Hay algunas molestias molestas con el tercer argumentop
, que especifica el ancho del tablero; Esto se debe a que Prolog no tiene un tipo de matriz, y si no restrinjo el tablero para que sea rectangular, el programa entrará en un bucle infinito intentando bordes progresivamente más amplios alrededor del tablero).m
es la principal función de resolución de Buscaminas. Analiza la cadena de entrada, genera un tablero con un borde correcto (mediante el uso del caso recursivo dep
para convertir la mayor parte del tablero, luego llama al caso base directamente para generar el borde superior, que tiene la misma estructura que el borde inferior). Entonces llamaz(r,[R|M])
para ejecutar el motor de reglas Buscaminas, que (con este patrón de llamada) se convierte en un generador que genera solo tableros válidos. En este punto, el tablero todavía se expresa como un conjunto de restricciones, lo cual es potencialmente incómodo para nosotros; quizás podríamos tener un solo conjunto de restricciones que podrían representar más de una placa. Además, aún no hemos especificado en ningún lugar que cada cuadrado contenga como máximo una mina. Como tal, tenemos que explícitamente "colapsar la forma de onda" de cada cuadrado, lo que requiere que sea específicamente un (único) mina o un nonmine, y la forma más sencilla de hacerlo es ejecutar a través de las revés analizador (elvar(V)
de laq(63,V)
El estuche está diseñado para evitar que el?
estuche corra hacia atrás y, por lo tanto, el análisis del tablero obliga a que sea completamente conocido). Finalmente, devolvemos el tablero analizado dem
;m
por lo tanto, se convierte en un generador que toma una placa parcialmente desconocida y genera todas las placas conocidas compatibles con ella.Eso es realmente suficiente para resolver el Buscaminas, pero la pregunta explícitamente es verificar si hay exactamente una solución, en lugar de encontrar todas las soluciones. Como tal, escribí un predicado adicional
s
que simplemente convierte el generadorm
en un conjunto y luego afirma que el conjunto tiene exactamente un elemento. Esto significa ques
devolverá verdadero (yes
) si de hecho hay exactamente una solución, o falsey (no
) si hay más de uno o menos de uno.d
no es parte de la solución y no está incluido en el bytecount; es una función para imprimir una lista de cadenas como si fuera una matriz, lo que hace posible inspeccionar las placas generadas porm
(de forma predeterminada, GNU Prolog imprime cadenas como una lista de códigos ASCII, porque trata a los dos como sinónimos; este formato es bastante difícil de leer) Es útil durante las pruebas, o si desea usarlom
como un solucionador de buscaminas práctico (porque usa un solucionador de restricciones, es altamente eficiente).fuente
Haskell,
193169168 bytesEjemplo de uso:
g "1121 1??* 12?* 0122"
->True
.Cómo funciona: haga una lista de todos los tableros posibles con el
?
reemplazado por uno*
o!
(!
significa ignorar más adelante). Esto se hace a través demapM c
, pero antes de anteponer y agregar un montón de espacios a la cadena de entrada para que nuestra indexación no esté fuera de rango. Para cada uno de estos tableros, verifique si es un tablero válido haciendo un bucle sobre todos los elementos (índicej
) y si es un número (d>'/'
) también sobre sus vecinos (índicen
,m
), cuente*
y compare con el número. Finalmente verifique la longitud de la lista de tablas válidas.fuente
Mathematica,
214192190180176174168165 bytesContiene U + F4A1 (uso privado). Esta función sin nombre busca todas las combinaciones posibles para
"?"
(es decir, reemplaza todas las"?"
s con"*"
o0
) y comprueba si solo hay una solución válida.Explicación
Establecer
b
a"*"
.Establecer
q
en la cadena"?"
. Compruebe si hay"?"
en la entrada.Si
True
...Reemplace la primera aparición de
q
(="?"
) conb
(="*"
) o0
(es decir, dos salidas), y aplique de nuevo toda la función.Si
False
...Rellene la entrada con una capa de
0
.Particione la entrada en 3 x 3 matrices con desplazamiento 1. Para cada partición, aplique una función tal que si el valor medio es
b
(="*"
), la salida es elb
(="*"
), y si el valor medio no esb
(="*"
), el salida es el número deb
(="*"
) en la entrada. Este paso vuelve a evaluar todas las celdas numéricas.De todos los resultados, encuentre los que coincidan con la entrada
Compruebe si la entrada es longitud 1.
fuente
Perl, 215 bytes
213 bytes de código +
-p0
banderas (2 bytes).La idea del código es probar todas las posibilidades y ver si hay una y solo una que conduzca a un tablero completamente lleno que sea válido.
Más legible, el código se ve así:
Sobre la expresión regular en el medio:
Tenga en cuenta que
[^V]
solo significa "cualquier carácter, incluyendo \ n".Entonces la idea es: 3 caracteres en una línea, luego 3 en el siguiente (con
$i
en el medio), luego 3 en el siguiente. esos 3 grupos de 3 números están alineados, gracias[^V]{$c}
y el número que nos interesa está en el medio.Y luego,
"$1$2$3"=~y%*%%
cuenta el número de*
(bombas) entre esos 9 caracteres: si es diferente de$i
, agregamos una cadena vacía para que coincida (""
=> coincidencia instantánea, la expresión regular devuelve verdadero), de lo contrario, forzamos una falla al intentar hacer coincidirR
( que no puede estar en la cadena).Si los partidos de expresiones regulares, entonces la tarjeta no es válida, por lo que nos propusimos
$r
a0
con$r&=!/.../
.Y es por eso que agregamos algunos
A
en todas partes alrededor de cada línea: para que no tengamos que preocuparnos por los bordes de los números que están cerca de los bordes del tablero: tendránA
como vecinos, que no son minas (por supuesto, casi cualquier personaje podría tener trabajo, Yo elegíA
)Puede ejecutar el programa desde la línea de comando así:
La complejidad no podría ser peor: es
O(m*9^n)
dónden
está el número de?
en el tablero, ym
es el número de celdas en el tablero (sin contar la complejidad de la expresión regular en el medio, que probablemente sea bastante mala). En mi máquina, funciona bastante rápido hasta 4?
, y comienza a ser más lento 5, toma unos minutos para 6, y no intenté con números más grandes.fuente
JavaScript (ES6), 221
229Si se espera que toda la entrada sea válida, es decir, con al menos 1 solución, entonces puedo guardar un byte cambiandos==1
cons<2
Menos golf
Prueba
fuente
JavaScript (Node.js) , 167 bytes
Pruébalo en línea!
Aunque op dice "la entrada siempre será rectangular, tenga al menos una solución", la muestra falsa 3 no coincide, por lo que todavía necesito 1 solución, no <2 solución
fuente