Das Spiel BattleBlock Theatre enthält gelegentlich ein Puzzle, das eine verallgemeinerte Version von Lights Out ist . Sie haben drei benachbarte Blöcke, von denen jeder eine Stufe zwischen 1 und 4 einschließlich mit Balken anzeigt, z.
|
||||
||
Wenn Sie einen Block berühren, erhöht dieser Block sowie ein beliebiger benachbarter Block seinen Pegel (von 4 auf 1). Das Rätsel ist gelöst, wenn alle drei Blöcke dasselbe Level aufweisen (egal welches Level). Da die Reihenfolge, in der Sie die Blöcke berühren, keine Rolle spielt, geben wir an, wie oft jeder Block berührt wird. Die optimale Lösung für die obigen Eingaben wäre 201
:
| --> || --> ||| |||
|||| | || |||
|| || || --> |||
Das Spiel verallgemeinert sehr leicht eine beliebige Anzahl von Blöcken, obwohl für einige Zahlen nicht alle Konfigurationen lösbar sind.
Die Herausforderung
Geben Sie bei einer vorgegebenen Folge von Blockebenen an, wie oft jeder Block berührt werden muss, um das Rätsel zu lösen. ZB würde das obige Beispiel als gegeben 142
und könnte 201
als Ergebnis ergeben. Wenn es keine Lösung gibt, geben Sie eine konsistente Ausgabe Ihrer Wahl zurück, die von allen möglichen Lösungen unterscheidbar ist, z. B. -1
oder eine leere Zeichenfolge.
Sie können eine Funktion oder ein Programm schreiben, Eingaben über STDIN, Befehlszeilenargument oder Funktionsargument in einem beliebigen geeigneten Listen- oder Zeichenfolgenformat vornehmen und auf ähnliche Weise über einen Rückgabewert oder durch Drucken an STDOUT ausgeben.
Ihr Code sollte innerhalb einer Minute auf einem vernünftigen Computer für alle Testfälle korrekte Ergebnisse liefern. (Dies ist kein striktes Limit. Wenn Ihre Lösung also eine Minute und zehn Sekunden dauert, ist das in Ordnung. Wenn es jedoch drei Minuten dauert, ist dies nicht der Fall. Ein guter Algorithmus kann sie problemlos in Sekunden lösen.)
Dies ist Codegolf, daher gewinnt die kürzeste Antwort (in Bytes).
Beispiele
Die Lösungen sind nicht eindeutig, daher erhalten Sie möglicherweise unterschiedliche Ergebnisse.
Input Output
1 0
11 00
12 No solution
142 201
434 101
222 000
4113 0230
32444 No solution
23432 10301
421232 212301
3442223221221422412334 0330130000130202221111
22231244334432131322442 No solution
111111111111111111111222 000000000000000000000030
111111111111111111111234 100100100100100100100133
412224131444114441432434 113013201011001101012133
Soweit ich weiß, gibt es genau 4 Lösungen für jeden Eingang, bei denen die Anzahl der Blöcke 0 bis 3 oder 1 bis 3 beträgt, und es gibt 0 oder 16 Lösungen, bei denen es 2 bis 3 beträgt.
quelle
Antworten:
Python 2, 115 Bytes
Dies ist die Golfversion des Programms, das ich geschrieben habe, als ich das Problem mit Martin besprochen habe.
Eingabe ist eine Liste über STDIN. Die Ausgabe ist eine Liste, die die zuletzt gefundene Lösung darstellt, wenn es eine Lösung gibt, oder Null, wenn es keine gibt. Beispielsweise:
Pyth,
3229 BytesDer obligatorische Hafen. Vielen Dank an @Jakube für die 3-Byte-Speicherung.
Die Eingabemethode ist dieselbe wie oben. Versuchen Sie es online .
Erklärung (lang und voller Logik!)
Erstens zwei grundlegende Beobachtungen:
Beobachtung 1: Es spielt keine Rolle, in welcher Reihenfolge Sie die Blöcke berühren
Beobachtung 2: Wenn Sie einen Block viermal berühren, entspricht dies einer einmaligen Berührung
Mit anderen Worten, wenn es eine Lösung gibt, dann gibt es eine Lösung, bei der die Anzahl der Berührungen zwischen 0 und einschließlich 3 liegt.
Da Modulo 4 so schön ist, machen wir das auch mit den Blöcken. Für den Rest dieser Erklärung entspricht die Blockstufe 0 der Blockstufe 4.
Bezeichnen
a[k]
wir nun die aktuelle Blockstufek
undx[k]
die Häufigkeit, mit der wir einen Blockk
in einer Lösung berühren . Geben Sien
auch die Gesamtzahl der Blöcke an. Wie @Jakube festgestellt hat, muss eine Lösung Folgendes erfüllen:wo
C
ist das letzte Level, auf dem alle Blöcke enden, zwischen 0 und einschließlich 3 (denken Sie daran, wir behandeln Level 4 als Level 0) und alle obigen Gleichungen sind wirklich Kongruenzen Modulo 4.Hier ist der lustige Teil:
0 <= C <= 3
.Es gibt drei Fälle, basierend auf der Anzahl der Blöcke modulo 3. Die Erklärung für jeden von ihnen ist die gleiche - für jede Anzahl von Blöcken gibt es eine Teilmenge von Blöcken, die, wenn Sie jeden von ihnen einmal berühren, alle Blockebenen um erhöht genau 1.
Dies erklärt, warum es 4 Lösungen für
0 mod 3
und1 mod 3
und normalerweise 16 Lösungen für gibt2 mod 3
. Wenn Sie bereits eine Lösung haben und die Blöcke wie oben berühren, erhalten Sie eine andere Lösung, die auf einer höheren Blockebene endet (umwickelt).Also, was bedeutet das? Wir können jede
C
gewünschte letzte Blockstufe auswählen ! Lassen Sie uns wählenC = 0
, weil dies Bytes spart.Nun werden unsere Gleichungen:
Und neu anordnen:
Was wir also sehen können, ist, wenn wir haben
x[0]
, dann können wir alle Gleichungen außer der letzten verwenden, um jede andere herauszufindenx[k]
. Die letzte Gleichung ist eine zusätzliche Bedingung, die wir überprüfen müssen.Dies gibt uns einen Algorithmus:
x[0]
x[k]
Das ergibt die obige Lösung.
Warum bekommen wir manchmal keine Lösung dafür
2 mod 3
? Werfen wir noch einmal einen Blick auf diese beiden Muster:Betrachten Sie nun die Gleichungen an diesen Positionen, dh für die erste:
Addiere sie:
Für den zweiten:
Addiere sie noch einmal:
Wenn also
(a[1] + a[4] + a[7] + a[10])
und(a[0] + a[3] + a[6] + a[9])
nicht gleich sind, dann haben wir keine Lösung. Wenn sie jedoch gleich sind, erhalten wir 16 Lösungen. Dies war für denn = 11
Fall, aber dies verallgemeinert sich natürlich auf eine beliebige Zahl2 mod 3
- nimm die Summe jedes dritten Elements ab dem zweiten und vergleiche mit der Summe jedes dritten Elements ab dem ersten.Ist es nun endlich möglich, herauszufinden, was sein
x[0]
muss, anstatt alle Möglichkeiten auszuprobieren? Da wir unser ZiellevelC
auf 0 begrenzt haben, gibt es nur ein einziges,x[0]
das eine Lösung in dem Fall0 mod 3
oder1 mod 3
(as4 solutions / 4 final levels = 1 solution for a specific final level
) gibt.Die Antwort ist ja! Wir können dies tun für
0 mod 3
:Was bedeutet:
Subtrahieren ergibt:
Ähnlich
1 mod 3
können wir für dieses Muster tun:Welches gibt:
Diese verallgemeinern sich natürlich, indem die Indizes in Schritten von 3 erweitert werden.
Für
2 mod 3
, da wir zwei Untergruppen haben , die jeden Block abdecken, können wir holen eigentlich jederx[0]
. Tatsächlich gilt dies fürx[0], x[1], x[3], x[4], x[6], x[7], ...
(im Grunde genommen für jeden Index, der nicht kongruent ist2 mod 3
, da sie von keiner Teilmenge abgedeckt werden).Wir haben also eine Möglichkeit
x[0]
, alle Möglichkeiten zu wählen, anstatt sie zu versuchen ...... aber die schlechte Nachricht ist, dass dies nicht an Bytes (124 Bytes) spart:
quelle
J
anstelle vonH
und 2 Zeichen verwenden, wenn Sie das letzte Element platzieren,PJ
anstatt es aufzuteilen.<J_1
.V4J]NVQaJ%_+s>J_2@QN4)I!eJPJB
Pyth,
727673663938 Zeichenedit 4: Es wurde erkannt, dass die Berechnungen
Q[N]-Q[N+1]+solution[-3]
undQ[-2]-Q[-1]+solution[-3]
ident sind. Deshalb überberechne ich die Lösung um 1 und filtere die Lösungen, wobei der letzte Eintrag 0 ist. Dann füge ich den letzten Eintrag ein. Glücklicherweise benötigen die Sonderfälle bei diesem Ansatz keine zusätzliche Behandlung. -27 Zeichenedit 3: Einige Golftricks von FryAmTheEggman anwenden: -7 Charakter
edit 2: Mit Filter verkleinern und mappen: -3 Zeichen
edit 1: In meiner ersten Version habe ich nichts gedruckt, wenn es keine Lösung gab. Ich denke das ist nicht erlaubt, daher +4 Zeichen.
Erwartet eine Liste von Ganzzahlen als Eingabe
[1,4,2]
und gibt eine gültige Lösung aus,[2,0,1]
falls vorhanden, andernfalls eine leere Liste[]
.Erläuterung:
Sei
Q
die Liste der 5 Ebenen undY
die Liste der Lösung. Die folgenden Gleichungen müssen gelten:Deshalb , wenn wir jede verwenden
Y0
undY1
können wir berechnenY2
,Y3
undY4
in der folgenden Weise.Dann sind alle Ebenen außer der letzten gleich (weil wir die Gleichung nicht verwendet haben)
= Q4 + Y3 + Y4
. Um zu überprüfen, ob diese auch den anderen Ebenen entspricht, können wir einfach prüfen, ob(Q3 - Q4 + Y2) mod 4 == 0
. Beachten Sie, dass der linke Teil der Wert istY5
Wenn ich den 6. Teil der Lösung berechne, kann ich einfach prüfen, ob es Null ist.In meinem Ansatz iteriere ich einfach über alle möglichen Starts (
[0,0]
, bis[3,3]
) und berechne die Länge (Eingabe) -1 weiterer Einträge und filtere alle Lösungen, die mit einer Null enden.Im Grunde ist es das Folgende:
dann filtere ich diese möglichen Lösungen nach gültigen:
Zu dieser Liste von Lösungen füge ich eine leere Liste hinzu, so dass mindestens ein Element darin enthalten ist
Nehmen Sie die erste Lösung
h
, platzieren Sie das letzte Elementp
und drucken Sie es ausBeachten Sie, dass dies auch funktioniert, wenn nur ein Block vorhanden ist. Bei meiner Annäherung erhalte ich die Startposition [0,0] und verlängere sie nicht. Da der letzte Eintrag 0 ist, wird die Lösung [0] gedruckt.
Der zweite Sonderfall (2 Blöcke) ist doch nicht so besonders. Ich bin mir nicht sicher, warum ich die Dinge früher überkompliziert habe.
quelle
?**lQ]0qhQeQ<lQ3h+f!%-+ePQ@T_3eQ4mu+G]%+&H@G_3-@QH@QhH4UttQd^UT2]Y
ist 66 Bytes. Die Leistung hat ein bisschen nachgelassen, aber es ist für mich immer noch der größte Testfall seit <1s. Pingen Sie mich an, wenn Sie Erklärungen zu einigen der Golfplätze wünschen. in diesem Kommentar ist nicht genug Platz;) Ich hoffe, Sie genießen die Verwendung von Pyth: D+<list><int>
hat den gleichen Effekt wie+<list>]<int>
, so dass Sie die erste entfernen können]
. Auch sehr schöne Lösung.~
? Es schien nicht so zu sein, als ich es versuchte~
durcha
-~<list>]<int>
entsprichta<list><int>
.~
is+=
, whilea
is.append()
Ruby,
320313 ZeichenKann definitiv mehr golfen werden. Gibt nichts für unlösbare Rätsel aus.
Ungolfed-Version:
Okay, das hat Spaß gemacht. Hier ist der grundlegende Algorithmus mit der
{n}
Darstellung von n "Berührungen" auf der Zahl übern
, wie an einem der Beispiele gezeigt:Ich war hier ein bisschen ratlos. Wie kann ich aus
111...1110
einer Reihe gleicher Zahlen eine Serie machen? Also habe ich meine Lösung und die richtige Lösung verglichen (Anmerkung: Die "Touch" -Zahlen sind alle um eins höher als sie sein sollten, da die Eingabe 1-indiziert ist, während die Ausgabe 0-indiziert ist):Mir ist aufgefallen, dass jede Nummer eine andere als die richtige
mod 4
ist. Deshalb habe ich sie mit+
s,-
s und=
s markiert :Das hat eine Weile geklappt, bis ich merkte, dass manchmal das Endergebnis
111...11112
oder war11...1113
auch! Glücklicherweise hat das wiederholte Anwenden der magischen Formel, die keinen Sinn macht, aber auch funktioniert, diese aussortiert.Also, da hast du es. Ein Programm, das zunächst Sinn ergibt, sich aber mit der Zeit immer hässlicher macht. Typisch für eine Code-Golf-Lösung, denke ich. :)
quelle
exit if (r+=1)>5
zu(r+=1)>5&&exit
. Auch die(code)while cond
Syntax ist kürzer alswhile cond \n code \n end
.Python 2,
294,289,285,281,273 BytesDEMO
Ich bin sicher, dass dies weiter golfen werden kann ..
Hier sind die Ergebnisse aus den Testfällen:
Der Algorithmus stellt zunächst sicher, dass die Werte aller Blöcke mit Ausnahme des letzten Blocks gleich sind (indem er alle Blöcke mit Ausnahme der ersten 2 durchläuft und zu den "Berührungszahlen" addiert). Wenn die Anzahl der Blöcke dies zulässt (
(num_of_blocks - 1) % 3 != 1
), wird zurückgegangen und sichergestellt, dass die Werte der übrigen Blöcke mit dem letzten Block übereinstimmen. Druckt,x
wenn es keine Lösung gibt.quelle