Démineur est un jeu de puzzle populaire où vous devez découvrir quelles tuiles sont des "mines" sans cliquer sur ces tuiles. Au lieu de cela, vous cliquez sur les tuiles à proximité pour révéler le nombre de mines adjacentes. Un inconvénient du jeu est qu'il est possible de se retrouver dans un scénario où il y a plusieurs réponses valides et que vous ne pouvez que deviner. Par exemple, prenez le tableau suivant:
1110
2*31
3*??
2*4?
112?
Dans ce format, un nombre représente le nombre de mines adjacentes, un *
représente une mine connue et un "?" représente une mine potentielle. Ce qui est regrettable dans ce casse-tête, c'est qu'il existe quatre solutions potentielles distinctes et valides :
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*
Cela signifie que la carte est insoluble . Voici un exemple de panneau soluble :
1121
1??*
12?*
0122
Cette carte est résoluble car il n'y a qu'une seule solution valable possible:
1121
1*4*
12**
0122
Votre tâche consiste à écrire un programme ou une fonction qui prend une carte de dragueur de mines valide et détermine si elle est résoluble ou non. Par "carte de démineur valide", je veux dire que l'entrée sera toujours rectangulaire, aura au moins une solution et ne contiendra aucun caractère invalide.
Votre entrée peut être un tableau de caractères, un tableau de chaînes, une chaîne contenant des sauts de ligne, etc. La sortie doit être une valeur véridique si elle est résoluble et une valeur fausse si elle ne l'est pas. Je ne suis pas extrêmement préoccupé par les performances, mais votre solution doit théoriquement fonctionner pour n'importe quelle entrée de taille.
Comme d'habitude, les failles standard s'appliquent et la solution la plus courte en octets gagne!
Exemples:
Les exemples suivants sont tous résolubles:
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
Les exemples suivants sont tous insolubles:
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
la source
2?
n'a pas de solutions, ce qui signifie qu'il ne peut pas provenir d'un véritable jeu de démineur. Par conséquent, il n'est pas considéré comme un "plateau de démineur" ... oui?)Réponses:
GNU Prolog, 493 octets
Un prédicat supplémentaire qui peut être utile pour les tests (ne fait pas partie de la soumission):
Prolog est certainement le bon langage pour résoudre cette tâche du point de vue pratique. Ce programme énonce à peu près les règles du démineur et permet au solveur de contraintes de GNU Prolog de résoudre le problème à partir de là.
z
eti
sont des fonctions d'utilité (z
fait une sorte d'opération de type pli mais sur des ensembles de trois éléments adjacents plutôt que 2;i
transpose 3 listes de n éléments en une liste de n 3-tuples). Nous stockons en interne une cellule comme , où xx/y
est 1 pour une mine et 0 pour une mine non, et y est le nombre de mines adjacentes;c
exprime cette contrainte au tableau.r
s'appliquec
à chaque rangée du tableau; etz(r,M)
vérifie donc siM
c'est une carte valide.Malheureusement, le format d'entrée requis pour faire ce travail directement est déraisonnable, j'ai donc également dû inclure un analyseur (qui représente probablement plus de code que le moteur de règles réel, et la plupart du temps consacré au débogage; le moteur de règles du démineur fonctionnait à peu près) première fois, mais l'analyseur était plein de thinkos).
q
convertit une seule cellule entre un code de caractère et notre format. convertit une ligne du plateau (en laissant une cellule connue pour ne pas être une mine, mais avec un nombre inconnu de mines voisines, à chaque bord de la ligne comme frontière);x/y
l
p
convertit la carte entière (y compris la bordure inférieure, mais à l'exclusion de la bordure supérieure). Toutes ces fonctions peuvent être exécutées vers l'avant ou vers l'arrière, ce qui permet d'analyser et d'imprimer la carte à la fois. (Il y a des agitations agaçantes avec le troisième argument dep
, qui spécifie la largeur de la carte; c'est parce que Prolog n'a pas de type de matrice, et si je ne contrains pas la carte à être rectangulaire, le programme entrera dans une boucle infinie essayant des bordures progressivement plus larges autour de la planche.)m
est la principale fonction de résolution du démineur. Il analyse la chaîne d'entrée, générant une carte avec une bordure correcte (en utilisant le cas récursif dep
pour convertir la majeure partie de la carte, puis en appelant directement le cas de base pour générer la bordure supérieure, qui a la même structure que la bordure inférieure). Ensuite, il appellez(r,[R|M])
pour exécuter le moteur de règles du démineur, qui (avec ce modèle d'appel) devient un générateur générant uniquement des cartes valides. À ce stade, la carte est toujours exprimée comme un ensemble de contraintes, ce qui est potentiellement gênant pour nous; nous pourrions peut-être avoir un seul ensemble de contraintes qui pourraient représenter plus d'un conseil. De plus, nous n'avons encore spécifié nulle part que chaque carré contient au plus une mine. En tant que tel, nous devons explicitement "réduire la forme d'onde" de chaque carré, en exigeant qu'il s'agisse spécifiquement d'une mine (unique) ou d'une mine non, et la manière la plus simple de le faire est de la faire passer par l'analyseur vers l'arrière (levar(V)
sur leq(63,V)
le boîtier est conçu pour empêcher le?
boîtier de tourner en arrière, et ainsi l'analyse de la carte force à être pleinement connue). Enfin, nous renvoyons la planche analysée dem
;m
devient ainsi un générateur qui prend une carte partiellement inconnue et génère toutes les cartes connues qui lui correspondent.C'est vraiment suffisant pour résoudre le démineur, mais la question demande explicitement de vérifier s'il y a exactement une solution, plutôt que de trouver toutes les solutions. En tant que tel, j'ai écrit un prédicat supplémentaire
s
qui convertit simplement le générateurm
en un ensemble, puis affirme que l'ensemble a exactement un élément. Cela signifie ques
retournera truey (yes
) s'il y a en effet exactement une solution, ou falsey (no
) s'il y en a plus d'une ou moins d'une.d
ne fait pas partie de la solution et n'est pas inclus dans le bytecount; c'est une fonction pour imprimer une liste de chaînes comme s'il s'agissait d'une matrice, ce qui permet d'inspecter les cartes générées parm
(par défaut, GNU Prolog imprime les chaînes comme une liste de codes ASCII, car il traite les deux comme synonymes; ce format est assez difficile à lire). Il est utile lors des tests ou si vous souhaitez l'utiliserm
comme un solveur de démineur pratique (car il utilise un solveur de contraintes, il est très efficace).la source
Haskell,
193169168 octetsExemple d'utilisation:
g "1121 1??* 12?* 0122"
->True
.Comment ça marche: faites la liste de toutes les cartes possibles avec les
?
remplacées par*
ou!
(!
signifie ignorer plus tard). Cela se fait viamapM c
, mais avant de préfixer et d'ajouter un tas d'espaces à la chaîne d'entrée afin que notre indexation ne soit pas hors de portée. Pour chaque vérification du conseil d'administration si elle est une carte valide en boucle sur tous les éléments (indexj
) et si elle est un certain nombre (d>'/'
) aussi par rapport à ses voisins (indicen
,m
), comptez le*
et comparer au nombre. Enfin, vérifiez la longueur de la liste des cartes valides.la source
Mathematica,
214192190 190180176174168165 165 octetsContient U + F4A1 (usage privé). Cette fonction sans nom trouve toutes les combinaisons possibles pour
"?"
(c'est-à-dire remplacer tous les"?"
s par"*"
ou0
) et vérifie s'il n'y a qu'une seule solution valide.Explication
Réglez
b
sur"*"
.Définissez
q
la chaîne"?"
. Vérifiez s'il y en a"?"
dans l'entrée.Si
True
...Remplacez la première occurrence de
q
(="?"
) parb
(="*"
) ou0
(c'est-à-dire deux sorties) et appliquez à nouveau la fonction entière.Si
False
...Remplissez l'entrée avec une couche de
0
.Partitionnez l'entrée en 3 x 3 matrices avec décalage 1. Pour chaque partition, appliquez une fonction telle que si la valeur médiane est
b
(="*"
), la sortie est lab
(="*"
), et si la valeur médiane n'est pasb
(="*"
), la sortie est le nombre deb
(="*"
) dans l'entrée. Cette étape réévalue toutes les cellules numériques.À partir de tous les résultats, trouvez ceux qui correspondent à l'entrée
Vérifiez si l'entrée est de longueur 1.
la source
Perl, 215 octets
213 octets de code +
-p0
drapeaux (2 octets).L'idée du code est de tester toutes les possibilités et de voir s'il y en a une et une seule qui mène à une carte entièrement remplie et valide.
Plus lisible, le code ressemble à:
À propos de l'expression régulière au milieu:
Notez que
[^V]
signifie simplement "n'importe quel caractère, y compris \ n".L'idée est donc: 3 caractères sur une ligne, puis 3 sur la suivante (avec
$i
au milieu), puis 3 sur la suivante. ces 3 groupes de 3 nombres sont alignés, grâce à[^V]{$c}
et le nombre qui nous intéresse est au milieu.Et puis,
"$1$2$3"=~y%*%%
compte le nombre de*
(bombes) parmi ces 9 caractères: si c'est différent de$i
, nous ajoutons une chaîne vide pour correspondre (""
=> correspondance instantanée, l'expression régulière renvoie vrai), sinon, nous forçons un échec en essayant de faire correspondreR
( qui ne peut pas être dans la chaîne).Si les matchs regex, le conseil d' administration n'est pas valide, nous avons donc mis
$r
à0
avec$r&=!/.../
.Et c'est pourquoi nous en ajoutons
A
partout autour de chaque ligne: nous n'avons donc pas à nous soucier des bords des cas de nombres qui sont près des bords de la planche: ils aurontA
comme voisins, qui ne sont pas des mines (bien sûr, à peu près n'importe quel char pourrait avoir du travail, J'ai choisiA
).Vous pouvez exécuter le programme à partir de la ligne de commande comme ça:
La complexité ne pourrait pas être pire: c'est
O(m*9^n)
oùn
est le nombre de?
sur la carte, etm
est le nombre de cellules sur la carte (sans compter la complexité de l'expression régulière au milieu, ce qui est probablement assez mauvais). Sur ma machine, cela fonctionne assez rapidement jusqu'à 4?
, et commence à être plus lent 5, prend quelques minutes pour 6, et je n'ai pas essayé de plus grands nombres.la source
JavaScript (ES6), 221
229Si toutes les entrées sont censées être valides - c'est-à-dire avec au moins 1 solution - alors je peux enregistrer un octet en changeants==1
avecs<2
Moins golfé
Tester
la source
JavaScript (Node.js) , 167 octets
Essayez-le en ligne!
Bien que op dise "l'entrée sera toujours rectangulaire, a au moins une solution", le faux échantillon 3 ne correspond pas, donc j'ai toujours besoin d'une solution, pas <2
la source