GNU Prolog, 493 bytes
z(_,[_,_]).
z(F,[A,B,C|T]):-call(F,A,B,C),z(F,[B,C|T]).
i([],[],[],[]).
i([H|A],[I|B],[J|C],[H-I-J|T]):-i(A,B,C,T).
c(A/_-B/_-C/_,D/_-_/T-E/_,F/_-G/_-H/_):-T#=A+B+C+D+E+F+G+H.
r(A,B,C):-i(A,B,C,L),z(c,L).
q(63,V):-var(V).
q(42,1/_).
q(X,0/Y):-Y#=X-48.
l([],[0/_]).
l([H|T],[E|U]):-q(H,E),l(T,U).
p([],[[0/_,0/_]],0).
p([],[[0/_|T]],N):-M#=N-1,p([],[T],M).
p([H|T],[[0/_|E]|U],N):-p(T,U,N),l(H,E).
m([H|A],B):-length(H,N),p([],[R],N),p([H|A],M,N),z(r,[R|M]),p(B,M,N).
s(A):-setof(B,m(A,B),[_]).
Un predicado adicional que puede ser útil para la prueba (no forma parte del envío):
d([]).
d([H|T]):-format("~s~n",[H]),d(T).
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
y i
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 de p
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 (el var(V)
de la q(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 generador m
en un conjunto y luego afirma que el conjunto tiene exactamente un elemento. Esto significa que s
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 por m
(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 usarlo m
como un solucionador de buscaminas práctico (porque usa un solucionador de restricciones, es altamente eficiente).
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í?)