Im Spiel Tetris gibt es 7 Arten von Ziegeln oder Tetr i Minoes , die als mathematisch bekannt sind tetr o Minoes , weil sie alle gemacht mit 4 quadratischen Segmenten sind:
Sie haben die Namen I, J, L, O, S, T und Z, die ihren ungefähren Formen entsprechen. Bei 90 ° -Drehungen gibt es insgesamt 19 einzigartige Formen:
I
I
I
I
IIII
J
J
JJ
JJJ
J
JJ
J
J
J
JJJ
L
L
LL
L
LLL
LL
L
L
LLL
L
OO
OO
SS
SS
S
SS
S
TTT
T
T
TT
T
T
TTT
T
TT
T
ZZ
ZZ
Z
ZZ
Z
Herausforderung
Schreiben Sie einen rechteckigen Codeblock, der als Basissegment fungiert, aus dem diese 19 Formen bestehen. Wenn dieser Code in einer der Formen angeordnet ist, sollte ein Programm erstellt werden, das den einzelnen Großbuchstaben ausgibt, der dieser Form zugeordnet ist. Dies muss für alle 19 Formen funktionieren.
Die führenden leeren Bereiche in einigen der 19 Formen sind vollständig mit Leerzeichen ausgefüllt ( ). Die nachgestellten leeren Bereiche werden mit nichts gefüllt (daher sind die Programme nicht immer genau rechteckig).
Beispiel
Angenommen, dies wäre Ihr Codeblock:
ABC
123
Dann wäre jede Anordnung des Blocks in dem S-Tetris-Stück ein Programm, das Folgendes ausgibt S
:
ABCABC
123123
ABCABC
123123
ABC
123
ABCABC
123123
ABC
123
(Beachten Sie, dass alle führenden Leerzeichen mit Leerzeichen gefüllt sind und dass keine Zeilen nachgestellte Leerzeichen enthalten.)
Die gleiche Idee gilt für alle 6 anderen Teile und ihre jeweiligen Rotationen.
Anmerkungen
- Alle 19 endgültigen Programme müssen in derselben Programmiersprache ausgeführt werden.
- Falls gewünscht, können Sie allen Programmen (nicht nur einigen, allen oder keinen) eine einzige nachgestellte Zeile hinzufügen .
- Ihr Codeblock kann beliebige Zeichen (einschließlich Leerzeichen) enthalten, die keine Zeilenabschlusszeichen sind .
- Geben Sie den Brief mit einem optionalen Zeilenumbruch an stdout (oder an die nächstgelegene Alternative Ihrer Sprache) aus.
Wertung
Die Einreichung, deren Codeblock die kleinste Fläche (Breite mal Höhe) hat, gewinnt. Dies bedeutet im Wesentlichen, dass der kürzeste Code gewinnt, weshalb dies als Code-Golf gekennzeichnet ist . Tiebreaker geht zu der am höchsten bewerteten Antwort.
Das ABC\n123
Beispiel hat die Fläche 3 × 2 = 6.
Ausschnitt
Mit diesem Codeblock werden alle 19 Programme generiert:
<script>function drawShape(X,n,v){for(var t="",e=0;e<v.length;e++)for(var l=0;l<n.length;l++){for(var r=0;r<v[e].length;r++)t+="X"===v[e][r]?n[l]:X[l];t+="\n"}return t}function go(){var X=document.getElementById("input").value;if(0!=X.length){var n=X.replace(/./g," ").split("\n");X=X.split("\n");for(var v="I (v1):|I (v2):|J (v1):|J (v2):|J (v3):|J (v4):|L (v1):|L (v2):|L (v3):|L (v4):|O:|S (v1):|S (v2):|T (v1):|T (v2):|T (v3):|T (v4):|Z (v1):|Z (v2):".split("|"),t="X\nX\nX\nX|XXXX| X\n X\nXX|XXX\n X|XX\nX\nX|X\nXXX|X\nX\nXX| X\nXXX|XX\n X\n X|XXX\nX|XX\nXX| XX\nXX|X\nXX\n X|XXX\n X|X\nXX\nX| X\nXXX| X\nXX\n X|XX\n XX| X\nXX\nX".split("|"),e="",l=0;l<v.length;l++)e+=v[l]+"\n\n"+drawShape(n,X,t[l].split("\n"))+"\n";e=e.substring(0,e.length-2),document.getElementById("output").value=e}}</script><style>html *{font-family: monospace;}</style>Code Block:<br><textarea id='input' rows='8' cols='64'>ABC
123</textarea><br><button type='button' onclick='go()'>Go</button><br><br>All 19 Programs:<br><textarea id='output' rows='24' cols='64'></textarea>
quelle
Antworten:
<> <(Fisch) - 12 * 32 = 384
Ich hatte vor, eine elegantere Lösung zu finden, aber irgendwie kam ich zu dem Ergebnis, das ziemlich brachial ist:
Es ist ziemlich einfach, es überprüft den Code in einem 3x3-Quadrat auf Text und verwendet die Ergebnisse, um festzustellen, welches Tetrimino der Form des Codes entspricht. Ich habe mir noch nicht viel Mühe gegeben, um Golf zu spielen.
Probieren Sie den Code hier aus (nachdem Sie das Snippet verwendet haben, um es wie ein Tetrimino zu formen)
Beispielcode in Form Z (v1) hier
quelle
C (gcc) ,
26×20 = 520,25×19 = 475,23×17 = 391Kürzlich wurde ich über die Funktionsattribute von GNU informiert, und am interessantesten über das
constructor
Attribut, das eine knappe Implementierung dessen ermöglicht, was ich in meiner früheren Herangehensweise an dieses Problem auf rundere Weise getan habe.Der Grundgedanke ist derselbe wie zuvor: Erstellen Sie eine Zeichenfolge und suchen Sie danach in einer Liste, um zu ermitteln, als welcher Tetris-Block der Code ausgelegt ist. Dies geschieht durch Aufrufen von Funktionen, von denen jede der Zeichenfolge ein Zeichen hinzufügt. Die Komplikation war und ist, dass die Anzahl der Funktionen variiert.
Wenn Sie eine Funktion mit definieren,
attribute((constructor(x)))
wird sie somain()
eingegeben, dass die Funktion ausgeführt wird, bevor sie eingegeben wird,x
wobei die Priorität optional ist (niedriger bedeutet, dass sie früher ausgeführt wird). Dadurch werden keine Funktionszeiger mehr benötigt, sodass wir ein Makro, einige Deklarationen und die Aufrufkette löschen können.Die Verwendung
__LINE__
für die Priorität ist fraglich, da die Prioritätsstufen 0-100 reserviert sind. Dies führt jedoch nicht zu Fehlern, sondern nur zu Warnungen. Diese sind beim Golfen in Hülle und Fülle vorhanden. Was gibt es also noch mehr?Es hätte geholfen, eine andere Spalte davon abzuhalten, Prioritäten überhaupt nicht zu verwenden, aber die Ausführungsreihenfolge scheint nicht definiert zu sein. (In diesem Fall sind sie umgekehrt, andere Tests sind jedoch nicht schlüssig.)
Beispiel für L v2 hier
Älterer, portablerer Ansatz
Eines meiner Lieblingsprobleme, das ich auf dieser Site gelöst habe.
Ich begann damit, dass jeder Block irgendwie seine eigenen Koordinaten erraten würde. Mit Zeilen ist es einfach
__LINE__
, und die Anzahl horizontal benachbarter Blöcke lässt sich mit der Länge eines String-Literals wie folgt ermitteln:Nehmen Sie die Länge der resultierenden Zeichenfolge und dividieren Sie durch eine richtige Zahl und Sie haben die Breite. Leider ist jeder leere Raum vor dem Block durch diese Methode unsichtbar. Ich immer noch im Verdacht Strings wäre die Lösung, da Leerzeichen nur außerhalb von Strings ist sehr selten Sinn, in Dingen wie
a+++b
vs.a+ ++b
. Ich habe kurz über so etwas nachgedacht, konnte mir aber nichts Sinnvolles einfallen lassen. Eine andere Möglichkeit wäre gewesen, Identifikatoren dort "zusammenkleben" zu lassen, wo sich Blöcke treffen:Es würde mich nicht wundern, wenn dies noch zu einer interessanten Lösung führen könnte.
Trotz seiner Einfachheit habe ich einige Zeit gebraucht, um die String-Lösung zu finden, die auf diesem Blockfragment basiert:
Wenn das Fragment keine horizontalen Nachbarn hat, wird die neue Zeile in der zweiten Zeile durch den Backslash maskiert, wodurch eine Zeichenfolge der Länge 2 erstellt wird. Wenn es jedoch einen Nachbarn hat, wird der Backslash stattdessen am Zeilenanfang durch das Anführungszeichen maskiert 2 des nächsten Blocks:
Dadurch wird die Zeichenfolge "\" "mit der Länge 5 erstellt.
Dies ermöglicht insbesondere auch die Erkennung von Leerstellen vor dem Block:
Wiederum wird die neue Zeile maskiert und das Leerzeichen des leeren Blocks links in die resultierende Zeichenfolge "" der Länge 6 eingefügt.
Insgesamt gibt es sieben verschiedene Konfigurationen von Blöcken in einer Reihe, über die wir uns Gedanken machen müssen, und alle bilden Zeichenfolgen mit einer einzigartigen Länge:
Die endgültigen Blöcke werden natürlich nicht so kurz sein, aber das Prinzip ist das gleiche, unabhängig von der Blockgröße. Dies hat auch den Vorteil, dass ein separater Mechanismus zum Erfassen der Breite nicht erforderlich ist. Durch Hinzufügen eines Zeichens, das der Länge dieser Zeichenfolge entspricht, zu einer Ergebniszeichenfolge ergibt jede der 19 Konfigurationen eine eindeutige Zeichenfolge, die erst dann mit einer geeigneten Liste verglichen werden muss, wenn alle Blöcke ausgeführt wurden.
Sobald dies geklärt war, bestand das nächste große Problem darin, jede Reihe von Blöcken zu "besuchen". In C beschränken wir uns sehr auf das, was außerhalb von Funktionen möglich ist. Wir müssen
main()
auch erscheinen, aber nur einmal. Letzteres ist für manche leicht zu erreichen#define
, aber wenn der Code nachfolgender Blöcke innerhalb von sein sollmain()
, stellt sich die Frage, wann die letzte schließende geschweifte Klammer zu setzen ist. Schließlich wissen wir nicht, wie viele Blockreihen tatsächlich verwendet werden. Wir müssen alsomain()
statisch und den Rest irgendwie dynamisch sein.Wenn die anderen Blockzeilen in sich geschlossen sein sollen, müssen sie Funktionen sein, aber wir müssen sicherstellen, dass jede Funktion einen eindeutigen Namen hat und gleichzeitig vorhersehbar genug ist, um von dort aufgerufen werden zu können
main()
. Wir brauchen auch einen Mechanismus, um zu wissen, welche Funktionen tatsächlich aufgerufen werden müssen. Das Generieren eindeutiger Namen wird durch Hilfsmakros gelöst:Durch Anrufen
F
wird eine Kennung erstellt, deren Name mit einem f beginnt und mit der Zeilennummer endet.A
tut das gleiche, aber mit einem als Präfix, das für den zweiten Teil der Lösung verwendet wird, der Funktionszeiger ist. Wir deklarieren vier solche Zeiger:Da diese als globale Variablen deklariert sind, werden sie zweckmäßigerweise auf NULL gesetzt. Später hat jede Blockzeile den folgenden Code:
Dies deklariert zuerst eine Funktion, definiert den entsprechenden Funktionszeiger, der auf diese Funktion verweist (wir können nur einmal Globale definieren, aber die frühere Deklaration zählte nicht als Definition, auch wenn sie auf NULL initialisiert wurde) und definiert dann die tatsächliche Funktion. Auf diese Weise können Sie
main()
jeden Funktionszeiger aufrufen, der nicht NULL ist (a17 wird niemals NULL sein):Auf diese Weise wird die Zeichenfolge erstellt
r
, die dann in der Tabelle der Zeichenfolgen gesucht wird. Wenn sie gefunden wird, wird der entsprechende Buchstabe ausgegeben.Der einzige verbleibende Trick besteht darin, dass die Liste der zu vergleichenden Zeichenfolgen immer dann gekürzt wurde, wenn Mehrdeutigkeiten vermieden oder überlappende Zeichenfolgen zusammengeführt werden konnten.
Beispiel für L v2 hier
quelle
x86-Opcode (.com),
8682 BytePrüfer:
Quelle:
Führen Sie in win7dos wo init AX = 0, SI = 100, BX = 0 Referenzen
quelle
mov bx, 100h
am Anfang löschen .