Underload ist ein stapelbasiertes, halbfunktionales Tarpit, das von ais523 erstellt wurde . Ich habe kürzlich versucht, darin Golf zu spielen, da es eine überraschend elegante Sprache ist.
Welche Tipps haben Sie zum Golfen in Underload? (Ein Tipp pro Antwort)
eval
Befehl ist. Ich habe noch nie eine solche Sprache gesehen.Antworten:
Zur
*
Ausgabe verwendenDa Sie ausgeben können, indem Sie eine Zeichenfolge auf dem Stapel belassen , kann es nützlich sein, die Zeichenfolge mithilfe von zu akkumulieren,
*
anstatt sie mit auszugebenS
. Angenommen, Ihre Herausforderung bestand darin, "einen String zu nehmen und ein Leerzeichen anzuhängen". Der Weg, dies mit der Ausgabe zu tun, wäre:Der Weg dazu
*
ist dagegen ein Byte kürzer:Das Problem ist, dass die Verarbeitung des Ausgabeelements auf dem Stapel Bytes kosten kann, wenn Ihre Ausgabe viel Akkumulation aufweist.
quelle
Verwenden Sie ein Wörterbuch mit wiederholt wiederverwendeten Funktionen
Wenn Sie häufig Code verwenden müssen, ist es sinnvoll, diesen Code auf dem Stapel zu speichern und ab und zu zu duplizieren und auszuwerten. Bisher ist das nur normale Unterlastprogrammierung. Leider ist es schwierig, einen Wert für eine lange Zeit auf dem Stapel zu halten, und dies führt dazu, dass Ihr Code ausführlich wird. Dies gilt auch dann, wenn der Wert eher eine Funktion als Daten ist. Dies wird viel schlimmer, wenn Sie mehrere Funktionen haben, die wiederholt wiederverwendet werden müssen.
Bei größeren Programmen, die möglicherweise von mehreren wiederverwendeten Funktionen profitieren, können Sie stattdessen eine große Funktion erstellen, die je nach Aufruf einen ihrer Zwecke erfüllt (entweder basierend auf dem, was sich darunter auf dem Stapel befindet). oder über längere mit der Aufrufsequenzen als nur
^
, eine sorgfältig geschriebene Funktion kann unterscheiden^^
von^:^
aus^*^
aus^~^
, Sie vier verschiedene, recht kurze Sequenzen) zu geben. Sie können in diesem "Wörterbuch" auch andere nützliche Dinge speichern, z. B. Zeichenfolgen, die Sie mehrmals verwenden. Beachten Sie, dass es bei starker Verwendung des Wörterbuchs möglicherweise sinnvoll ist, es zu einer Art Quine zu machen und eine Kopie von sich selbst wieder auf den Stapel zu schieben, damit Sie es nicht manuell kopieren müssen:
in der Lage zu sein, es zu benutzen, ohne die Fähigkeit zu verlieren, es in Zukunft zu benutzen.quelle
^!!!!^
Stilsuche erstellt (die ich auch in mehreren anderen Beispielen auf der Seite verwendet habe, insbesondere im Minimierungsabschnitt). Obwohl dies möglicherweise nicht die kürzeste Suche ergibt.Wählen Sie Datenformate, die auf die Vorgänge spezialisiert sind, die das Problem benötigt
Als einfaches Beispiel ist die am häufigsten verwendete Implementierung von Booleschen Werten
!()
für false (dh Ganzzahl 0) und die Nullzeichenfolge für true (dh Ganzzahl 1). Wenn Sie jedoch ein Problem haben, das stark auf logischem XOR basiert, kann dies zu mehr führen Es ist sinnvoll, die Nullzeichenfolge für false und~
für true zu verwenden (dieses Datenformat kann mithilfe von in jedes andere boolesche Format konvertiert werden(false)~(true)~^!
und ermöglicht die sehr knappe Implementierung*
für XOR.Es ist möglich, dieses allgemeine Prinzip noch weiter zu verfolgen und Funktionen zu verwenden, die Ihr Programm später als Teil Ihrer Datenwerte benötigt. Das erspart das separate Speichern der Funktionen und Daten auf dem Stapel. Dies kann den Kontrollfluss etwas verwirrender machen, aber beim Golfen muss die Wartbarkeit oft in den Hintergrund treten, und es ist nicht so, dass Unterlast sowieso alles ist, was verwendet werden kann.
quelle
(!)
und(~!)
für Boolesche Werte verwendet, aber dein Weg scheint besser zu sein."Schmutziges" Dekrement
Die funktional reine Methode zum Dekrementieren einer Kirchenzahl ist die Verwendung der Lambda-Kalkül-Vorgängerfunktion:
Wobei 0 = \ x. \ Yy, T = \ x. \ Yx und $ der Nachfolger ist.
In Underload umgeschrieben, sind dies 28 Bytes:
Dies ist in Ordnung, aber wir können einige der nützlichen Eigenschaften von Underload ausnutzen, nämlich das
:!
und()*
do sind No-Ops. Dies bedeutet , dass für eine Reihen
,:ⁿ!!()()*ⁿ
(wocⁿ
wirdc
wiederholtn
mal) erhält man n-1. Wenn Sie dies beispielsweise für die Kirchenzahl 3 tun, erhalten Sie Folgendes:Wenn wir No-Op-Paare entfernen, erhalten wir:
Welches ist 2.
Das ist also die neue und kürzere Vorgängeroperation:
Dies ist 7 Bytes kürzer.
quelle
(()~(:))~:(^!!())*~(*)~^**
ist es immer noch 3 Bytes kürzer.Fügen Sie nicht benötigte Stapelwerte in den Programmbereich ein
Unterlast hat tatsächlich zwei Stapel - den Stapel von Zeichenfolgen und den Stapel von Befehlen, aus denen der Quellcode besteht. Mit der
^
Anweisung von Underload können wir Zeichenfolgen vom ersteren Stapel zum letzteren verschieben. Auf diese Weise können wir eine Menge unnötiger Stapelmanipulationen sparen.Angenommen, wir haben
(a)(b)(c)
auf dem Hauptstapel und möchten die beiden unteren Elemente verketten, ignorieren(c)
, um zu erhalten(ab)(c)
. Der naive Weg, dies zu tun, besteht darin, den Stapel zu drehen, um zu erhalten(c)(a)(b)
und dann zu konkantenieren und zurück zu tauschen:Das ist schlecht. Das
a~a~*~a*^
Drehen des Stapels ist äußerst kostspielig und sollte nach Möglichkeit vermieden werden. Durch Einfügen(c)
in den Programmbereich kann dies um vier Bytes verkürzt werden:Die Idee ist, die Anweisungen, die Sie ausführen möchten, zu übernehmen und dann eine Anweisung hinzuzufügen, die
(c)
am Ende zurückgeschoben werden soll, und dann das Ergebnis auszuwerten. Dies bedeutet, dass wir uns keine Sorgen machen müssen,(c)
bis es zurückgeschoben wird, nachdem wir fertig sind.quelle
(*)~a*^
, was meiner Meinung nach etwas komponierbarer ist. Im Wesentlichen~a*^
ist derdip
Befehl von Joy.