Es gibt eine Variante des bekannten N-Königinnen-Problems, die Königinnen und Ritter betrifft und als "wesentlich schwieriger" bezeichnet wird 1 . Die Problemstellung lautet wie folgt:
Sie müssen eine gleiche Anzahl von Rittern ♞ und Königinnen ♛ auf ein Schachbrett legen, sodass keine Figur eine andere angreift. Was ist die maximale Anzahl von Stücken, die Sie so auf das Brett legen können, und wie viele verschiedene Arten können Sie es tun?
Bei dieser Code-Golf- Herausforderung erhalten Sie eine Eingabe n zwischen 3 und 32 (so, wie es für Ihre Sprache am besten geeignet ist). Für ein gegebenes n kann es keine oder mehrere Lösungen für das obige Problem geben. Falls es keine Lösung gibt, müssen Sie nichts ausgeben / zurückgeben ( null , leere Zeichenfolge , falsch , ...). Andernfalls müssen Sie zwei Ergebnisse angeben:
- Eine Lösungskarte (siehe unten) für Größe n, bei der es nicht möglich ist, eine Dame oder eine Ritterschachfigur hinzuzufügen, ohne dass eine Figur angegriffen wird. Es muss eine gleiche Anzahl von Königinnen und Rittern geben .
- Die Quelle eines auszuführenden Programms, das keine Eingabe akzeptiert und (i) eine andere Lösung (oder nichts ) für die gleiche Größe n im gleichen Format sowie (ii) ein anderes Programm für die nächste Lösung (und so weiter ) liefert ...).
Beachten Sie, dass:
- Die Programmsequenz darf niemals dieselbe Karte zweimal zurückgeben, muss alle möglichen Lösungen für das Problem der Größe n abdecken und muss schließlich enden (keine Ausgabe produzieren).
- Sie können entweder zwei Werte zurückgeben, einen zurückgeben und den anderen ausdrucken oder die beiden Rückgabewerte ausdrucken.
- Allerdings , wenn Sie sowohl drucken Sie das Brett, und das nächste Programm, muss der Vorstand nicht als Teil des nächsten Programms in Betracht gezogen werden (Ich würde empfehlen , das Brett in Kommentar Drucke oder verwenden sowohl die Standardausgabe und Fehlerströme).
- Der Rückgabewert des Programms muss eine Zeichenfolge sein, kein Abschluss.
Kartenformat
- Eine Tafel ist ein Quadrat der Größe n .
- Eine Brettzelle kann leer sein, eine Königin oder ein Ritter.
- Sie müssen unterschiedliche Werte für jede Art von Zellen auswählen (dh Sie können beim Drucken der Karte andere Symbole als Q, N verwenden).
- Wenn Sie ein Board ohne Zeichenfolge zurückgeben, muss es eine geordnete Sammlung der n 2 -Werte des Boards sein (z. B. Matrix, Vektor oder Liste in Zeilen- / Spalten-Hauptreihenfolge, ...).
Wenn Sie die Tafel drucken, können Sie sie entweder im Quadrat oder als Linie drucken. Zum Beispiel kann eine Lösungskarte der Größe 4 wie folgt gedruckt werden (Leerzeichen nicht erforderlich; Symbole nach Ihrem Ermessen):
Q - - - - - - - - - - - - - N -
Wenn Sie dies wünschen, können Sie auch Folgendes ausgeben:
♛ · · · · · · · · · · · · · ♞ ·
... aber das reicht aus:
Q-------------N-
Es spielt keine Rolle, ob Sie Zellen in einer Zeilen- oder Spaltenfolge durchlaufen, da es symmetrische Lösungen gibt. Zum Beispiel sind die Lösungen für n = 4:
Q------N-------- Q----------N---- Q------------N-- Q-------------N- -Q----------N--- -Q------------N- -Q-------------N --Q---------N--- --Q----------N-- --Q------------N ---QN----------- ---Q----N------- ---Q---------N-- ---Q----------N- ---NQ----------- ----Q------N---- ----Q----------N N------Q-------- -------QN------- -------Q----N--- ---N----Q------- -------NQ------- --------Q------N N----------Q---- ----N------Q---- -----------QN--- -N----------Q--- --N---------Q--- -------N----Q--- -----------NQ--- N------------Q-- --N----------Q-- ---N---------Q-- N-------------Q- -N------------Q- ---N----------Q- -N-------------Q --N------------Q ----N----------Q --------N------Q
Sie können die Lösungen für n = 5 auch als Matrizen betrachten ; die Platten enthalten #
, q
und n
Symbole, die leeren Zellen verschiedener Arten sind (siehe meine Antwort unten). Ich zähle 2836 Boards für n = 6 , wie in Sleafars Antwort (ich habe einen Fehler beim Reduzieren der Byteanzahl eingeführt, aber er ist jetzt behoben).
Vielen Dank an Sleafar, dass sie nicht nur einen, sondern zwei Fehler in meinem Code gefunden haben.
Ergebnis
Kürzester Code in Bytes gewinnen.
Wir messen die Größe des ersten Programms, das n akzeptiert .
1 . Königinnen und Ritter , von Roger KW Hui (Vorsicht! Enthält eine Lösung)
-------------------------N--------Q-
ist ungültig, weil mehr Teile hinzugefügt werden können :)Q--------N---------------N--------Q-
.Antworten:
Groovy, 515 Bytes
Testen
Geben Sie n als Befehlszeilenargument an:
Die erste Zeile der Ausgabe ist immer eine Lösung als Kommentar (0 = leer, 1 = Dame, 2 = Ritter), gefolgt vom Code in der zweiten Zeile:
Das folgende Skript kann für automatisierte Tests verwendet werden (erneut n als Argument angeben):
Da ich versucht habe, die Lösung so klein wie möglich zu halten, ist sie sehr langsam (Einzelheiten siehe unten). Ich habe mit dieser Version nur n = 4 getestet, um zu sehen, ob die Quineifizierung funktioniert.
Ergebnisse
n = 4: 40 Lösungen ( konvertiertes Format )
n = 5: 172 Lösungen ( konvertiertes Format )
n = 6: 2836 Lösungen ( konvertiertes Format )
Algorithmus
Dies ist eine leicht ungolfederte, nicht quine Version der Lösung:
Quineifikation
Ich habe hier einen sehr einfachen Ansatz gewählt, um die Codegröße niedrig zu halten.
Die Variable X enthält den Index der Lösung, die als nächstes gedruckt werden soll. Y enthält eine modifizierte Kopie des obigen Algorithmus, mit der alle Lösungen berechnet und dann nur eine davon ausgewählt werden. Dies ist der Grund dafür, dass der Algorithmus so langsam ist. Der Vorteil dieser Lösung ist, dass nicht viel zusätzlicher Code benötigt wird. Der in Y gespeicherte Code wird mit Hilfe der Eval- Klasse ausgeführt (eine echte Quine ist nicht erforderlich).
Der geänderte Code gibt die Lösung aus, auf die X zeigt , erhöht X und fügt eine Kopie von sich selbst an:
Ich habe auch versucht, alle Lösungen als Code für den zweiten Schritt auszugeben, aber für n = 6 wurde zu viel Code erzeugt, als dass Groovy damit umgehen konnte.
quelle
Common Lisp, 737
Selbstantwort
Beispiel
Fügen Sie das Obige in die REPL ein, die ein Funktionsobjekt zurückgibt:
Nennen Sie es (der Stern ist an den zuletzt zurückgegebenen Wert gebunden):
Dies druckt Folgendes auf die Standardausgabe:
Der von dieser Funktion zurückgegebene Wert ist außerdem:
... das ist ein Array-Literal. Nummer 5 steht für Königinnen, 6 für Ritter und alles andere steht für eine leere Zelle, außer es sind weitere Informationen intern gespeichert. Wenn wir die zurückgegebene Funktion kopieren und in die Replik einfügen, erhalten wir eine neue Funktion.
Und wir können es ohne Argumente nennen:
Dieser Aufruf gibt eine neue Lösung
#(5 0 0 0 0 0 0 2 0 0 0 6 0 0 2 0)
und die Quelle einer anderen Funktion zurück (hier nicht gezeigt). Falls die ursprüngliche oder die zuletzt erzeugte Funktion keine Lösung findet, wird nichts gedruckt und nichts zurückgegeben.Interne Werte
Früher habe ich zu wenige Lösungen generiert. Nun propagiere ich unabhängig voneinander, welche Zelle für eine Königin und einen Ritter sicher ist. Hier ist zum Beispiel eine Ausgabe für n = 5 mit hübschem Ausdruck:
Wenn wir die Königin platzieren
Q
, sind Positionen, die ein Springer von dieser Königin entfernt sind, für Königinnen immer noch sicher und gekennzeichnetq
. Ebenso sind Ritter, die nur von Königinnen erreicht werden können, für andere Ritter sicher. Die Werte sind bitweise und -ed, um die möglichen Bewegungen darzustellen, und einige Zellen sind von keiner Art von Stück erreichbar.Genauer gesagt, hier ist die Reihenfolge der Karten, die zu der folgenden Lösung führt (von links nach rechts), bei der freie Zellen allmählich mit unterschiedlichen Werten eingeschränkt werden:
Non-Quine-Ansatz
Ungolfed, kommentierte Version
Duplikate und Bugs
Meine allererste Lösung gab doppelte Lösungen aus. Um das Problem zu lösen, habe ich zwei Marken für Königinnen und Ritter eingeführt. Der Zähler für Königinnen (bzw. Ritter) verfolgt die erste Position auf dem Brett, an der eine Königin (bzw. ein Ritter) existiert: Ich füge eine Königin (bzw. einen Ritter) nur an Positionen hinzu, die auf diese minimale Position folgen.
Diese Methode hindert mich daran, Lösungen erneut aufzurufen, die bereits in früheren Iterationen gefunden wurden, da ich mit zunehmender Position der Dame (bzw. des Ritters) iteriere.
Sleafar bemerkte jedoch, dass es Lösungen gab, für die Königinnen und Ritter Platz hatten, was gegen die Regeln verstieß. Für eine Weile musste ich jedoch zu einer normalen Suche zurückkehren und alle bekannten Lösungen speichern, um Duplikate zu vermeiden, die sich zu kostspielig anfühlten (sowohl in Bezug auf Bytes als auch auf die Speichernutzung).
Stattdessen mache ich jetzt Folgendes: Wenn ein mögliches Lösungsbrett gefunden wird, versuche ich, genau eine Dame und einen Ritter hinzuzufügen , ohne die Zähler zu berücksichtigen (dh für alle Zellen auf dem Brett). Wenn dies möglich ist, ist die aktuelle Karte ein Duplikat der vorherigen und ich lehne die Lösung ab.
Tests
Quine-ification
Ich hatte verschiedene Ideen, um aufeinanderfolgende Quines herzustellen. Am einfachsten ist es wahrscheinlich, alle Lösungen zuerst als Liste von Zeichenfolgen zu generieren und sequentielle Quines zu schreiben, die bei jeder Generation aus dieser Liste hervorgehen. Dies schien jedoch nicht kürzer zu sein als der derzeitige Ansatz. Alternativ habe ich versucht, den rekursiven Code mit einem benutzerdefinierten Stapel neu zu schreiben und jedes Mal, wenn ich eine Lösung finde, alle Statusvariablen zu sichern. das ziel ist, dass der nächste schritt als fortsetzung des aktuellen schritts abgearbeitet werden kann. Vielleicht ist dies besser für eine stapelbasierte Sprache geeignet. Die aktuelle Version ist recht einfach und basiert auf Common Lisp Reader-Variablen, deren Verwendung immer Spaß macht.
quelle