Tipps zum Golfen in Underload


11

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)


Ich mag es, dass die einzige Form des Kontrollflusses ein evalBefehl ist. Ich habe noch nie eine solche Sprache gesehen.
ETHproductions

Antworten:


3

Zur *Ausgabe verwenden

Da 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 auszugeben S. Angenommen, Ihre Herausforderung bestand darin, "einen String zu nehmen und ein Leerzeichen anzuhängen". Der Weg, dies mit der Ausgabe zu tun, wäre:

S( )S

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.


2

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.


Ich würde verrückt werden, lange bevor ich ein Programm in Underload bekam, das groß genug war, dass dies zu einem Problem wurde: P
Esolanging Fruit

Ich habe einmal einige Beispiele auf der Esolangs-Seite geschrieben, wie man Wörterbücher mit meiner bevorzugten ^!!!!^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.
Ørjan Johansen

2

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.


Früher habe ich (!)und (~!)für Boolesche Werte verwendet, aber dein Weg scheint besser zu sein.
Esolanging Fruit

2

"Schmutziges" Dekrement

Die funktional reine Methode zum Dekrementieren einer Kirchenzahl ist die Verwendung der Lambda-Kalkül-Vorgängerfunktion:

\n.n(\p.\z.z($(pT))(pT))(\z.z0[whatever you define the predecessor of 0 to be])

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 Reihe n, :ⁿ!!()()*ⁿ(wo cⁿwird cwiederholt nmal) 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.


Das bricht aber bei n = 0. Wenn Sie das brauchen, um zu funktionieren, (()~(:))~:(^!!())*~(*)~^** ist es immer noch 3 Bytes kürzer.
Ørjan Johansen

@ ØrjanJohansen Im Allgemeinen hätten Sie einen Sonderfall für n = 0, da es bei Underloads Zahlen ohnehin keinen Sinn macht, 0 zu dekrementieren.
Esolanging Fruit

1

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:

a~a~*~a*^*~

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:

a(*)~*^

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.


1
Sie können es auch als schreiben (*)~a*^, was meiner Meinung nach etwas komponierbarer ist. Im Wesentlichen ~a*^ist der dipBefehl von Joy.
Ørjan Johansen
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.