Minesweeper ist ein beliebtes Puzzlespiel, bei dem Sie herausfinden müssen, welche Steine "Minen" sind, ohne auf diese Steine zu klicken. Stattdessen klicken Sie auf benachbarte Kacheln, um die Anzahl benachbarter Minen anzuzeigen. Ein Nachteil des Spiels ist, dass es möglich ist, in ein Szenario zu geraten, in dem es mehrere gültige Antworten gibt und Sie nur raten können. Nehmen Sie zum Beispiel die folgende Tafel:
1110
2*31
3*??
2*4?
112?
In diesem Format steht eine Zahl für die Anzahl benachbarter Minen, *
eine bekannte Mine und ein "?" repräsentiert eine potentielle Mine. Das Unglückliche an diesem speziellen Rätsel ist, dass es vier verschiedene und gültige mögliche Lösungen gibt:
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*
Dies bedeutet, dass die Karte unlösbar ist . Hier ist ein Beispiel für eine lösbare Karte:
1121
1??*
12?*
0122
Diese Karte ist lösbar, da es nur eine mögliche gültige Lösung gibt:
1121
1*4*
12**
0122
Ihre Aufgabe ist es, entweder ein Programm oder eine Funktion zu schreiben, die ein gültiges Minensuchbrett benötigt und feststellt, ob es lösbar ist oder nicht. Mit "gültiges Minensuchbrett" meine ich, dass die Eingabe immer rechteckig ist, mindestens eine Lösung hat und keine ungültigen Zeichen enthält.
Ihre Eingabe kann ein Array von Zeichen, ein Array von Zeichenfolgen, eine Zeichenfolge mit Zeilenumbrüchen usw. sein. Die Ausgabe muss ein wahrer Wert sein, wenn sie lösbar ist, und ein falscher Wert, wenn dies nicht der Fall ist. Ich mache mir keine großen Sorgen um die Leistung, aber Ihre Lösung muss theoretisch für jede Eingabegröße funktionieren.
Wie üblich gelten Standardlücken und die kürzeste Lösung in Bytes gewinnt!
Beispiele:
Die folgenden Beispiele sind alle lösbar:
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
Die folgenden Beispiele sind alle unlösbar:
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
quelle
2?
keine Lösungen, was bedeutet, dass es nicht aus einem tatsächlichen Spiel von Minesweeper stammen kann. Daher wird es nicht als "Minesweeper-Brett" angesehen ... ja?)Antworten:
GNU Prolog, 493 Bytes
Ein zusätzliches Prädikat, das zum Testen nützlich sein kann (nicht Teil der Einreichung):
Prolog ist definitiv die richtige Sprache, um diese Aufgabe aus praktischer Sicht zu lösen. Dieses Programm gibt so ziemlich nur die Regeln von Minesweeper an und lässt GNU Prologs Constraint Solver das Problem von dort aus lösen.
z
undi
sind Utility-Funktionen (z
führt eine Art Fold-ähnliche Operation aus, jedoch mit Mengen von drei benachbarten Elementen anstelle von 2;i
transponiert 3 Listen von n Elementen in eine Liste von n 3-Tupeln). Wir speichern eine Zelle intern als , wobei x 1 für eine Mine und 0 für eine Nichtmine ist und y die Anzahl benachbarter Minen ist; drückt diese Einschränkung an der Tafel aus. gilt für jede Reihe der Tafel; und prüft so , ob es sich um eine gültige Karte handelt.x/y
c
r
c
z(r,M)
M
Leider ist das Eingabeformat, das erforderlich ist, um diese Funktion direkt auszuführen, nicht zumutbar. Daher musste ich auch einen Parser einbinden (der wahrscheinlich mehr Code als die eigentliche Regelengine enthält und die meiste Zeit mit dem Debuggen verbracht hat). Die Minesweeper-Regelengine hat ziemlich gut funktioniert Das erste Mal, aber der Parser war voll von Thinkos.
q
konvertiert eine einzelne Zelle zwischen einem Zeichencode und unserem Format. konvertiert eine Zeile des Spielbretts (wobei eine Zelle, von der bekannt ist, dass sie keine Mine ist, jedoch eine unbekannte Anzahl benachbarter Minen aufweist, an jedem Rand der Zeile als Grenze verbleibt);x/y
l
p
Konvertiert das gesamte Board (einschließlich des unteren Rahmens, jedoch ohne das obere). Alle diese Funktionen können entweder vorwärts oder rückwärts ausgeführt werden, wodurch das Board sowohl analysiert als auch schön gedruckt werden kann. (Es gibt einige nervige Bewegungen mit dem dritten Argument vonp
, das die Breite der Karte angibt. Dies liegt daran, dass Prolog keinen Matrixtyp hat. Wenn ich die Karte nicht auf rechteckig einschränke, wird das Programm ausgeführt eine Endlosschleife, in der immer breitere Ränder um das Brett gezogen werden.)m
ist die Hauptauflösungsfunktion von Minesweeper. Es analysiert die Eingabezeichenfolge und generiert eine Platine mit einem korrekten Rand (indem dasp
meiste der Platine in den rekursiven Fall konvertiert wird und dann der Basisfall direkt aufgerufen wird, um die obere Grenze zu generieren, die dieselbe Struktur wie die untere Grenze hat). Dann ruft esz(r,[R|M])
um die Minesweeper Rules Engine auszuführen, die (mit diesem Aufrufmuster) zu einem Generator wird, der nur gültige Boards generiert. Zu diesem Zeitpunkt wird das Board immer noch als eine Reihe von Einschränkungen ausgedrückt, was für uns möglicherweise umständlich ist. wir könnten vielleicht eine einzige Reihe von Einschränkungen haben, die mehr als ein Board repräsentieren könnten. Außerdem haben wir noch nirgendwo angegeben, dass jedes Quadrat höchstens eine Mine enthält. Als solches müssen wir die Wellenform jedes Quadrats explizit "kollabieren", wobei es spezifisch entweder eine (einzelne) Mine oder eine Nichtmine sein muss, und der einfachste Weg, dies zu tun, besteht darin, es rückwärts durch den Parser zu laufen (dievar(V)
auf derq(63,V)
case soll verhindern, dass das?
Gehäuse nach hinten läuft, und dass das Board durch das Deparsing vollständig erkannt wird). Zum Schluss geben wir das geparste Board abm
;m
Somit wird ein Generator, der eine teilweise unbekannte Karte nimmt und alle bekannten Karten in Übereinstimmung mit ihr erzeugt.Das ist wirklich genug, um Minesweeper zu lösen, aber die Frage lautet ausdrücklich, ob es genau eine Lösung gibt, anstatt alle Lösungen zu finden. Als solches habe ich ein zusätzliches Prädikat geschrieben
s
, das den Generator einfachm
in eine Menge umwandelt und dann behauptet, dass die Menge genau ein Element enthält. Dies bedeutet, dasss
truthy (yes
) zurückgegeben wird, wenn es tatsächlich genau eine Lösung gibt, oder falsey (no
), wenn es mehr als eine oder weniger als eine gibt.d
ist nicht Teil der Lösung und nicht im bytecount enthalten; Es ist eine Funktion zum Drucken einer Liste von Zeichenfolgen, als wäre es eine Matrix, die es ermöglicht, die vonm
(standardmäßig druckt GNU Prolog Zeichenfolgen als Liste von ASCII-Codes, da beide synonym behandelt werden; dieses Format) generierten Karten zu überprüfen ist ziemlich schwer zu lesen). Dies ist nützlich beim Testen oder wenn Siem
einen praktischen Minesweeper-Solver verwenden möchten (da ein Constraint-Solver verwendet wird, ist dieser sehr effizient).quelle
Haskell,
193169168 BytesAnwendungsbeispiel:
g "1121 1??* 12?* 0122"
->True
.So funktioniert es: Liste aller möglichen Boards mit dem
?
Ersetzten von entweder*
oder!
(!
Mittel später ignorieren). Dies geschieht übermapM c
, aber bevor wir dem Eingabe-String eine Reihe von Leerzeichen voranstellen und anhängen, damit unsere Indizierung nicht außerhalb des gültigen Bereichs liegt. Überprüfen Sie für jede dieser Karten, ob es sich um eine gültige Karte handelt, indem Sie alle Elemente (Indexj
) und, wenn es sich um eine Nummer (d>'/'
) handelt, auch die Nachbarn (Indexn
,m
) durchlaufen,*
und vergleichen Sie sie mit der Nummer. Überprüfen Sie abschließend die Länge der Liste der gültigen Karten.quelle
Mathematica,
214192190180176174168165 BytesEnthält U + F4A1 (Privatgebrauch). Diese unbenannte Funktion findet alle möglichen Kombinationen für
"?"
(dh Ersetzen aller"?"
s durch"*"
oder0
) und prüft, ob es nur eine gültige Lösung gibt.Erläuterung
Stellen Sie
b
auf"*"
.Auf
q
den String setzen"?"
. Überprüfen Sie, ob es"?"
in der Eingabe ist.Wenn
True
...Ersetzen Sie das erste Vorkommen von
q
(="?"
) durchb
(="*"
) oder0
(dh zwei Ausgänge) und wenden Sie die gesamte Funktion erneut an.Wenn
False
...Füllen Sie den Eingang mit einer Schicht aus
0
.Partitionieren Sie die Eingabe in 3 x 3 Matrizen mit Versatz 1. Wenden Sie für jede Partition eine Funktion so an, dass bei einem Mittelwert von
b
(="*"
) die Ausgabe dieb
(="*"
) und bei einem Mittelwert nicht dieb
(="*"
) ist output ist die Anzahlb
(="*"
) in der Eingabe. Dieser Schritt wertet alle Nummernzellen neu aus.Suchen Sie aus allen Ergebnissen die Ergebnisse, die der Eingabe entsprechen
Überprüfen Sie, ob die Eingabe die Länge 1 hat.
quelle
Perl, 215 Bytes
213 Byte Code +
-p0
Flags (2 Byte).Die Idee des Codes ist es, jede Möglichkeit zu testen und festzustellen, ob es eine einzige gibt, die zu einer vollständig gefüllten, gültigen Karte führt.
Besser lesbar sieht der Code so aus:
Über den Regex in der Mitte:
Beachten Sie, dass
[^V]
nur für "ein beliebiges Zeichen, einschließlich \ n" steht.Die Idee ist also: 3 Zeichen in einer Zeile, dann 3 in der nächsten (mit
$i
in der Mitte), dann 3 in der nächsten. Diese 3 Gruppen von 3 Zahlen sind dank ausgerichtet[^V]{$c}
und die Zahl, an der wir interessiert sind, befindet sich in der Mitte.Und dann
"$1$2$3"=~y%*%%
zählt die Anzahl der*
(Bomben) unter den 9 Zeichen: wenn es aus anders ist$i
, fügen wir eine leere Zeichenfolge übereinstimmen (""
=> Instant - Matching, die regex true zurück), andernfalls zwingen wir nicht durch anzupassen versuchenR
( was nicht in der Zeichenfolge sein kann).Wenn der reguläre Ausdruck übereinstimmt, ist das Board nicht gültig, also setzen wir
$r
auf0
mit$r&=!/.../
.Und deshalb fügen wir einige hinzu
A
Überall um jede Zeile: Wir müssen uns also nicht um Kanten kümmern. Fälle von Zahlen, die sich in der Nähe der Kanten des Bretts befinden: Sie habenA
Nachbarn, die keine Minen sind (natürlich könnte ungefähr jeder Saibling Arbeit haben). Ich wählteA
).Sie können das Programm folgendermaßen über die Befehlszeile ausführen:
Die Komplexität könnte nicht schlimmer sein:
O(m*9^n)
Hiern
befindet sich die Anzahl der?
auf dem Board befindlichenm
Zellen und die Anzahl der Zellen auf dem Board (ohne die Komplexität des Regex in der Mitte zu berücksichtigen, was wahrscheinlich ziemlich schlimm ist). Auf meinem Computer funktioniert es ziemlich schnell für bis zu 4?
und beginnt langsamer zu werden 5, dauert ein paar Minuten für 6 und ich habe keine größeren Zahlen versucht.quelle
JavaScript (ES6), 221
229Wenn erwartet wird, dass alle Eingaben gültig sind - also mit mindestens 1 Lösung -, kann ich ein Byte speichern, das sichs==1
mit änderts<2
Weniger golfen
Prüfung
quelle
JavaScript (Node.js) , 167 Byte
Probieren Sie es online!
Obwohl "Eingabe immer rechteckig ist, mindestens eine Lösung hat", stimmt die falsche Stichprobe 3 nicht überein, daher benötige ich immer noch 1 Lösung, nicht <2 Lösung
quelle