Es ist Zeit, sich auf eine gefährliche Suche zu begeben, um den britischen Geheimdienst zu besiegen. Ziel dieser Herausforderung ist es, den kürzesten Code zu schreiben, der ein Nonogramm löst.
Was ist ein Nonogramm?
Die Regeln sind einfach. Sie haben ein Quadratraster, das entweder schwarz ausgefüllt oder leer gelassen werden muss. Neben jeder Zeile des Rasters sind die Längen der schwarzen Quadrate in dieser Zeile aufgeführt. Über jeder Spalte sind die Längen der schwarzen Quadrate in dieser Spalte aufgeführt. Ihr Ziel ist es, alle schwarzen Quadrate zu finden. In diesem Puzzletyp sind die Zahlen eine Form der diskreten Tomographie, die misst, wie viele ungebrochene Linien von ausgefüllten Quadraten sich in einer bestimmten Zeile oder Spalte befinden. Zum Beispiel würde ein Hinweis von "4 8 3" bedeuten, dass es Sätze von vier, acht und drei gefüllten Quadraten in dieser Reihenfolge gibt, wobei mindestens ein leeres Quadrat zwischen aufeinanderfolgenden Gruppen liegt. [ 1 ] [ 2 ]
Die Lösung für das obige Nonogramm wäre also:
Implementierungsdetails
Sie können das Nonogramm so darstellen, wie Sie möchten, und es als Eingabe verwenden, wie Sie es für Ihre Sprache für geeignet halten. Gleiches gilt für die Ausgabe. Das Ziel dieser Herausforderung ist es, den Job buchstäblich nur zu erledigen. Wenn Sie das Nonogramm mit der Ausgabe Ihres Programms lösen können, ist dies gültig. Eine Einschränkung ist, dass Sie keinen Online-Löser verwenden können :)
Dieses Problem ist algorithmisch sehr herausfordernd (np-complete), da es keine vollständig effiziente Lösung dafür gibt und Sie daher nicht dafür bestraft werden, dass Sie größere Probleme nicht lösen können, obwohl Ihre Antwort in diesem Fall sehr belohnt wird in der Lage, große Fälle zu behandeln (siehe Bonus). Als Benchmark funktioniert meine Lösung innerhalb von 5-10 Sekunden für bis zu 25x25. Um die Flexibilität zwischen verschiedenen Sprachen zu gewährleisten, sind Lösungen, die für ein 25x25-Nonogramm weniger als 5 Minuten dauern, ausreichend.
Sie können ein Puzzle in immer einem quadratischen NxN-Nonogramm annehmen.
Sie können diesen Online-Nonogram Puzzle Maker verwenden, um Ihre Lösungen zu testen.
Wertung
Selbstverständlich können Sie jede gewünschte Sprache verwenden. Da es sich um Codegolf handelt, werden die Einträge in der Reihenfolge sortiert: accuracy -> length of code -> speed.
Lassen Sie sich jedoch nicht von Codegolf-Sprachen entmutigen. Antworten in allen Sprachen, die Golfversuche anzeigen auf interessante weise wird upvoted!
Bonus
Tatsächlich habe ich Nonogramme von einer kryptografischen Weihnachtskarte erfahren, die der britische Geheimdienst hier herausgebracht hat . Der erste Teil war im Grunde ein massives 25x25 Nonogramm. Wenn Ihre Lösung dies lösen kann, erhalten Sie ein großes Lob :)
Um Ihnen die Dateneingabe zu erleichtern, habe ich angegeben, wie ich die Daten für dieses spezielle Puzzle zur freien Verwendung dargestellt habe. Die ersten 25 Zeilen sind die Zeilenhinweise, gefolgt von einer '-' Trennlinie, gefolgt von 25 Zeilen der Spaltenhinweise, gefolgt von einer '#' Trennlinie und einer Darstellung des Gitters mit den ausgefüllten quadratischen Hinweisen.
7 3 1 1 7
1 1 2 2 1 1
1 3 1 3 1 1 3 1
1 3 1 1 6 1 3 1
1 3 1 5 2 1 3 1
1 1 2 1 1
7 1 1 1 1 1 7
3 3
1 2 3 1 1 3 1 1 2
1 1 3 2 1 1
4 1 4 2 1 2
1 1 1 1 1 4 1 3
2 1 1 1 2 5
3 2 2 6 3 1
1 9 1 1 2 1
2 1 2 2 3 1
3 1 1 1 1 5 1
1 2 2 5
7 1 2 1 1 1 3
1 1 2 1 2 2 1
1 3 1 4 5 1
1 3 1 3 10 2
1 3 1 1 6 6
1 1 2 1 1 2
7 2 1 2 5
-
7 2 1 1 7
1 1 2 2 1 1
1 3 1 3 1 3 1 3 1
1 3 1 1 5 1 3 1
1 3 1 1 4 1 3 1
1 1 1 2 1 1
7 1 1 1 1 1 7
1 1 3
2 1 2 1 8 2 1
2 2 1 2 1 1 1 2
1 7 3 2 1
1 2 3 1 1 1 1 1
4 1 1 2 6
3 3 1 1 1 3 1
1 2 5 2 2
2 2 1 1 1 1 1 2 1
1 3 3 2 1 8 1
6 2 1
7 1 4 1 1 3
1 1 1 1 4
1 3 1 3 7 1
1 3 1 1 1 2 1 1 4
1 3 1 4 3 3
1 1 2 2 2 6 1
7 1 3 2 1 1
#
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 1 1 0 0 0 0 0 0 0 1 1 0 0 0 0 0 0 0 1 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 1 1 0 0 1 0 0 0 1 1 0 0 1 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 1 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 1 1 0 0 0 0 1 1 0 0 0 0 1 0 0 0 0 1 1 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
Und hier ist eine etwas andere Version für Ihre Bequemlichkeit; Ein durch Kommas getrenntes Tupel (Zeile, Spalte), in dem jedes Element eine Liste von Listen ist.
([[7, 3, 1, 1, 7],
[1, 1, 2, 2, 1, 1],
[1, 3, 1, 3, 1, 1, 3, 1],
[1, 3, 1, 1, 6, 1, 3, 1],
[1, 3, 1, 5, 2, 1, 3, 1],
[1, 1, 2, 1, 1],
[7, 1, 1, 1, 1, 1, 7],
[3, 3],
[1, 2, 3, 1, 1, 3, 1, 1, 2],
[1, 1, 3, 2, 1, 1],
[4, 1, 4, 2, 1, 2],
[1, 1, 1, 1, 1, 4, 1, 3],
[2, 1, 1, 1, 2, 5],
[3, 2, 2, 6, 3, 1],
[1, 9, 1, 1, 2, 1],
[2, 1, 2, 2, 3, 1],
[3, 1, 1, 1, 1, 5, 1],
[1, 2, 2, 5],
[7, 1, 2, 1, 1, 1, 3],
[1, 1, 2, 1, 2, 2, 1],
[1, 3, 1, 4, 5, 1],
[1, 3, 1, 3, 10, 2],
[1, 3, 1, 1, 6, 6],
[1, 1, 2, 1, 1, 2],
[7, 2, 1, 2, 5]],
[[7, 2, 1, 1, 7],
[1, 1, 2, 2, 1, 1],
[1, 3, 1, 3, 1, 3, 1, 3, 1],
[1, 3, 1, 1, 5, 1, 3, 1],
[1, 3, 1, 1, 4, 1, 3, 1],
[1, 1, 1, 2, 1, 1],
[7, 1, 1, 1, 1, 1, 7],
[1, 1, 3],
[2, 1, 2, 1, 8, 2, 1],
[2, 2, 1, 2, 1, 1, 1, 2],
[1, 7, 3, 2, 1],
[1, 2, 3, 1, 1, 1, 1, 1],
[4, 1, 1, 2, 6],
[3, 3, 1, 1, 1, 3, 1],
[1, 2, 5, 2, 2],
[2, 2, 1, 1, 1, 1, 1, 2, 1],
[1, 3, 3, 2, 1, 8, 1],
[6, 2, 1],
[7, 1, 4, 1, 1, 3],
[1, 1, 1, 1, 4],
[1, 3, 1, 3, 7, 1],
[1, 3, 1, 1, 1, 2, 1, 1, 4],
[1, 3, 1, 4, 3, 3],
[1, 1, 2, 2, 2, 6, 1],
[7, 1, 3, 2, 1, 1]])
quelle
s=[].fill([].fill(0,0,25),0,25);s[3][3]=s[3][4]=s3[3][12]=s3[3][13]=s3[3][21]=s[8][6]=s[8][7]=s[8][10]=s[8][14]=s[8][15]=s[8][18]=s[16][6]=s[16][11]=s[16][16]=s[16][20]=s[21][3]=s[21][4]=s[21][9]=s[21][10]=s[21][15]=s[21][20]=s[21][21]=1;
Antworten:
Brachylog ,
7069 BytesDies nimmt eine Liste von zwei Listen (zuerst die Zeilenindikatoren, dann die Spaltenindikatoren). Jeder Indikator ist selbst eine Liste (für Situationen wie
[3,1]
in einer Zeile).Diese Version benötigt ca. 3 Minuten, um das 5-mal-5-Beispiel der Herausforderung zu lösen.
Viel effizientere Version, 91 Bytes
Probieren Sie es online!
Dies ist keine vollständige rohe Gewalt: Der einzige Unterschied besteht darin, dass die Werte der Zellen durch diese Einschränkung so festgelegt werden, dass die Anzahl der Einsen in jeder Zeile und Spalte mit den als Indikatoren in der Eingabe angegebenen Zahlen übereinstimmt. Der einzige Brute-Force-Teil besteht dann darin, das eine Gitter mit den Einschränkungen zu finden, für die die "Blöcke" von 1s mit dem übereinstimmen, was als Indikation angegeben ist.
Dieser Vorgang dauert in dem 5 x 5-Beispiel der Herausforderung ungefähr 0,05 Sekunden. Dies ist für den Bonusfall immer noch viel zu langsam, da ich keine Ahnung habe, wie man die durch eine oder mehrere Nullen getrennten Einsenblöcke in Bezug auf Einschränkungen ausdrückt.
Erläuterung
Ich werde im Folgenden die 93-Byte-Version erklären. Der einzige Unterschied zwischen den beiden ist der Aufruf von Prädikat 3, der in der 70-Byte-Version nicht existiert, und die Nummerierung der Prädikate (da es eins weniger gibt).
Hauptprädikat:
Prädikat 1: Erzwingt, dass die Zeilen eine bestimmte Länge haben und dass jede Zelle 0 oder 1 ist.
Prädikat 2: Beschränken Sie eine Variable auf 0 oder 1
Prädikat 3: Die Summe der Einsen in einer Liste muss gleich der Summe der Indikatoren sein (z. B. wenn der Indikator [3: 1] ist, muss die Liste die Summe 4 haben)
Prädikat 4: Überprüfen Sie, ob die Einsenblöcke mit dem Indikator übereinstimmen
Prädikat 5: Wahr für Einsenblöcke, sonst falsch
quelle
Haskell,
242 230 201 199 177 163 160 149131 BytesSchließlich unter 200 Bytes, schreiben Sie @Bergi gut. Vielen Dank an @nimi für die fast halbierte Größe.
Wow. Fast halb so groß, teilweise wegen mir, aber hauptsächlich wegen @nimi.
Die magische Funktion ist
(#)
. Es werden alle Lösungen eines gegebenen Nonogramms gefunden.Dies ist in der Lage, alle Fälle zu lösen, kann aber sehr langsam sein, da es um die Komplexität geht
O(2^(len a * len b))
. Ein schneller Benchmark ergab, dass 86 GB für ein 5 x 5-Nonogramm reserviert waren.Unterhaltsame Tatsache: Es funktioniert für alle Nonogramme, nicht nur für quadratische.
Wie es funktioniert:
a#b
: Erzeuge alle Gitter aus Listen mit ganzen Zahlen, die die Anzahl der Quadrate repräsentieren (map(chunk$length b).mapM id$a>>b>>[[0,1]]
) und filtern Sie die Ergebnisse, um nur die gültigen zu behalten.g
: Bei einem gegebenen potentiellen Nonogramm summiert es die Läufe von Einsen horizontal.quelle
m(chunk$l b)
undreplicate(l$a>>b)
import Data.Lists
ist genug, weil es sowohlData.List
als auch wieder exportiertData.List.Split
.Pyth,
917271 BytesEin Programm, das eine Liste der Formulare eingibt, in der
[size, [horizontal clues], [vertical clues]]
jeder Hinweis eine Liste ganzer Zahlen ist (leere Hinweise sind die leere Liste[]
), und jede Lösung in Form eines binären Rasters mit den1
schattierten und0
ist nicht schattieren .Das ist eine rohe Kraft, ungefähr so
O(2^n^2)
. Bei größeren Puzzles dauert es sehr lange, löst aber bei ausreichender Zeit jede beliebige Größe.Probieren Sie es online aus
Wie es funktioniert
Das Programm generiert jedes mögliche Layout, indem es das wiederholte kartesische Produkt
[0, 1]
mit einer Länge von gleich verwendetsize^2
. Dies wird dann in Blöcke aufgeteilt, wobei für jede horizontale Linie eine Liste erstellt wird. Jede Zeile ist lauflängencodiert, nach Vorhandensein gefiltert1
und abgeflacht, so dass der Hinweis für diese Zeile erhalten bleibt . Dies wird dann gegen die Eingabe geprüft. Der obige Vorgang wird für die Transponierung der Chunks wiederholt, wobei die vertikalen Linien überprüft werden. Bei einem Treffer wird jeder Block verkettet, und die verketteten Blöcke werden in Zeilenumbrüchen zusammengefügt und implizit mit einem nachgestellten Zeilenumbruch gedruckt.Danke an @ Pietu1998 für ein paar Tipps
quelle
=ZhZ
ist gleich=hZ
undFN
ist gleichV
.Javascript (ES6),
401386333 BytesDies ist ein früher Versuch. Es ist nicht sehr effizient, aber ich war neugierig, eine Lösung mit regulären Ausdrücken für die binäre Darstellung der Zeilen und Spalten zu testen.
Beispielsweise wird der Hinweis
[3,1]
in den folgenden regulären Ausdruck übersetzt:Im Moment berücksichtigt diese Version keine viereckigen Hinweise. Ich werde dies wahrscheinlich später hinzufügen.
Code
Ausgabe
Die Lösung wird im Binärformat angezeigt. Sowie:
Prüfung
Dies ist ein einfacher Test für das Beispielgitter.
quelle
Haskell, 109 Bytes
Haftungsausschluss: Dies ergibt sich aus der Antwort von @ ThreeFx . Ich habe ihm geholfen, seine Antwort aufzuschlüsseln, aber er scheint das Interesse verloren zu haben, meine letzten wesentlichen Verbesserungen einzubeziehen, also poste ich sie als neue Antwort.
Anwendungsbeispiel:
[[2],[3],[3],[3,1],[1]] # [[2],[3],[4],[2],[2]]
->[[" ## "," ### ","### ","### #"," #"]]
.Rohe Gewalt. Probieren Sie alle Kombinationen von
und aus
#
, teilen Sie int-Stücke von#
, zählen Sie die Längen und vergleichen Sie sie mit der Eingabe.quelle
PHP,
751833 (720)753724726710691680682 BytesIch wollte unbedingt ein spezielles Sequenzinkrement erstellen und meinen kartesischen Generator erneut testen.
aber ließ die kartesische zugunsten von Backtracking, um das große Rätsel schneller zu lösen.
$r
für Zeilenhinweise,$c
für Spaltenhinweise und$s
für quadratische Hinweise.invalid argument supplied for foreach
wenn es keine Lösung findet.\n
und entfernen Sie die anderen zwei Zeilenumbrüche , um die richtige Byte-Anzahl zu erhalten .Beschreibung
1)
Generieren Sie aus Zeilenhinweisen mögliche Zeilen, die den quadratischen Hinweisen entsprechen,
und merken Sie sich deren Anzahl für jeden Zeilenindex.
2) Zurückverfolgen der Zeilenkombinationen:
Wenn die Kombination den Spaltenhinweisen entspricht, suchen Sie eine tiefere oder geben Sie eine erfolgreiche Kombination zurück.
andernfalls versuchen Sie die nächste Möglichkeit für diese Zeile
3) Drucklösung
Das letzte Golfen hatte schwerwiegende Auswirkungen auf die Leistung;
Ich habe jedoch die Profilzuweisungen für die endgültigen Benchmarks entfernt.
Ersetzen Sie
$n=$n*($f=($p[$y][$i[$y]]>>$x&1)==$v)+$k=$f?:($v=!$v)||$n==$h[$z++];
mit
if(($p[$y][$i[$y]]>>$x&1)-$v){$k=($v=!$v)||$n==$h[$z++];$n=1;}else$n++;
, um den letzten Golfschritt rückgängig zu machen.
Beispiele
Verwenden Sie für das kleine Beispiel (
17 bis 21um12876.75.3 ms)für das Weihnachtspuzzle:
5037,845,5um 36 SekundenFüge die Daten aus der Frage in eine Datei ein
christmas.nonogram
und benutze diesen Code zum Importieren:Nervenzusammenbruch
quelle
$d
muss in der richtigen Reihenfolge sein fürforeach