GolfScript geht viel zu oft seinen eigenen Weg und ich bin der Meinung, dass eine Sammlung nützlicher Tipps zum Golfen in J im Kampf gegen das böse Imperium hilfreich sein könnte. Welche Tipps haben Sie, um diese bereits knappe Sprache zu verkürzen?
Für diejenigen, die J lernen möchten, ist der offensichtliche Einstieg die jsoftware- Site und insbesondere das Vokabular , das Learning J- Handbuch und das J for C-Programmierhandbuch .
GolfScript gets its own way far too often
im Jahr 2019 hat etwas Lustiges .Antworten:
Es gibt eine Reihe von Feinheiten, um die letzten Zeichen in J herauszuholen. Für das Folgende wird angenommen, dass jeder Großbuchstabe ein primitives Verb ist (dh, ich entferne die Leerzeichen, die ansonsten zur Begrenzung von Namen erforderlich wären).
Wenn Sie einen Zug gehen, und Sie müssen eine Funktion auf einer anderen teilweise durch, anzuwenden
([:FLGR)
und(LF@:GR)
die gleiche Anzahl von Zeichen, aber(LF@GR)
man spart. Wenn der Rahmen von G größer oder gleich dem Monadenrang von F ist, ist dies eine gültige Transformation. Insbesondere haben alle Züge einen unendlichen Rang, ebenso wie die, ,. ,: ~. /: \: [ ]
meisten Verwendungen von#
und|.
.Wenn Sie Zeichenfolgen aus einer Liste auswählen müssen und diese Zeichenfolgen keine Leerzeichen enthalten, verwenden Sie
>i{ab`cd`ef
. Es ist schmutzig, aber es speichert Zeichen für jede neue Zeichenfolge, mit der Sie sich befassen müssen, es sei denn, Sie ziehen nur einzelne Zeichen und selbst dann muss die Zeichenliste die Länge 4 haben, um kürzer zu sein. Was passiert, ist, dass undefinierte Namen als Verweise auf Verben behandelt werden, und wenn Sie die Gerundien dieser Verben nehmen, erhalten Sie eine geschachtelte Zeichenfolge des Namens. Alle Namen, für die bereits der Typ Nomen, Adverb oder Konjunktion definiert ist, können auf diese Weise nicht verwendet werden, da diese Namen zuvor aufgelöst`
wurden.Wenn Sie das Glück haben, einen Ausdruck zu haben, mit dem Sie arbeiten können, und nicht nur ein stillschweigendes Verb, lohnt es sich fast immer, alle Bits, die Sie wiederverwenden, Variablen zuzuweisen, seien es Substantive, Verben oder Adverbien. Die Parens zahlen sich manchmal aus, indem sie sich genau an die Stelle einfügen, an der Sie zuvor Leerzeichen hatten, und die meisten dieser Definitionen sind es wert, wenn sie noch einmal verwendet werden.
Konjunktionen wie
(FGH)^:(u`v`w)
können umgeschrieben werdenu`v`w(FGH^:)
. Dies funktioniert für jede Zuglänge, auch für 1, obwohl Sie nur dann etwas speichern, wenn dieser Trick die Parens aus dem richtigen Argument entfernt. Dieser Trick funktioniert nur, wenn Sie den linken Operanden vorladen. (Haben Sie keine Ahnung, was gerade passiert ist? Suchen Sie nach "stillschweigenden Adverbien" und lesen Sie den Abschnitt zum Parsen und Ausführen des J-Wörterbuchs.)Nicht benutzen
a.&i.
, benutzenu:
!{&a.
und3&u:
sind jedoch in der Länge äquivalent, und die erstere kann in einer Konjunktion (abhängig von der Konjunktion) nützlicher sein.Dinge wie
(2%~F)
und(F%2:)
sind gleich lang. Dies ist nützlich, da Sie manchmal, je nachdem, wie der Rest Ihres Zuges aussieht, ihn umstrukturieren können@
den im ersten Punkt beschriebenen Tricks , um einige verzweifelte Charaktere zu retten. (Und natürlich, wennF
es sich bei]
dem Zug um eine Monade handelt und%&2
ein Char verwendet wird, duh.)Hakenförmige Züge mit
]
oder[
als linkes Verb, z(]FGH)
.]
Mit dieser Option können Sie eine dyadische Anwendung auflösen und nur das richtige Argument verwenden. (Nach links tauschen mit(]FGH)~
, bei einer Strafe von mindestens 1 Zeichen, vielleicht mehr.) Speichert einen Buchstaben um(FGH)@]
und ist in Gerundien sehr praktisch![
Mit einem Hook, der monadisch angewendet wird, können Sie etwas für die Nebenwirkungen auf der rechten Seite tun und dann das Argument erneut zurückgeben. Die häufigste Verwendung ist mit1!:2
, möglicherweise mit Formatierungsmüll.I / O saugt. Beschleunigen Sie den Prozess, indem Sie aus allem, was Sie können, Loops erstellen.
1!:1
hat Rang0
, und beide1!:2 3
haben Rang_ 0
, verwenden Sie dies also, indem Sie Arrays von 1s erstellen und1!:1
direkt über sie laufen . Beachten Sie, dass".
auch Rang 1 hat, sodass Sie diesen normalerweise direkt danach setzen können1!:1
@
nachstellen können und ihn nicht über Shenanigans oder Ranglisten anhängen müssen.Es ist nicht leicht, Orte zu finden, an denen dies möglich ist, aber es
::
kann nützlich sein.::]^:_
ist beispielsweise eine besonders leistungsfähige Kombination, mit der Sie etwas Gefährliches tun können, bis Sie es nicht mehr können. (Vorbehaltlich der üblichen^:_
Vorbehalte.)Auf diese Weise können Sie auch
{
Listen verwenden, die nicht über den gewünschten Index verfügen, da in diesem Fall ein Domänenfehler auftritt. Nützlich, um zB nur dann den Kopf einer Liste zu übernehmen, wenn er existiert (versuchen Sie::]
, die leere Liste oder::_1:
einen Fehlercode zurückzugeben usw.).]`($:@u)@.v
kann in der Regel kürzer gemacht werden alsu^:v^:_
, insbesondere auf Definitionen vonu
und mitv
denen herumgespielt werden kann. Ein ähnlicher Fall gilt für die bedingte ähnlicheu^:(1-v)
vs.]`[email protected]
. Betrachten Sie Ihre Optionen, insbesondere wenn Sie viele benannte Verben haben, die sich im Umlauf befinden. Es ist auch etwas flexibler, aber denken Sie daran,$:
dass es bei der Verwendung eine Rekursionstiefe gibt, der Sie leicht begegnen können. (Normalerweise so etwas wie 1800 Iterationen?)quelle
%&2
spart einen char, duh." Und-:
rettet einen anderen!Das Wichtigste beim Golfspielen in J ist, das Problem nicht nur zu verstehen, sondern es auf eine Reihe von Array-Transformationen zu reduzieren. Sie müssen diese Denkweise verstehen, um mit J-Code erfolgreich zu sein.
Beispielsweise wurde kürzlich eine Herausforderung gestellt, um das größte Subarray-Problem zu lösen . Der Bestandsalgorithmus zur Lösung dieses Problems ist Kadanes Algorithmus mit der folgenden informellen Beschreibung:
Eine Übersetzung in imperativen Code ist unkompliziert:
Dieser Algorithmus scheint für J auf den ersten Blick kompliziert zu sein, da es eine explizite Schleife gibt, die auf den ersten Blick nicht nach einer Reduktion aussieht. Wenn Sie erkennen, was der Algorithmus tut, können Sie die einzelnen Schritte entwirren und feststellen, dass er tatsächlich zwei einfache Array-Operationen ausführt:
Nun sind diese beiden Schritte in J sehr einfach zu implementieren.
(0 >. +)/\. y , 0
- Dieser Schritt wird am anderen Ende des Arrays ausgeführt, um dem Paradigma von J besser zu entsprechen.0 >. +
ist stillschweigend0 >. x + y
.>./ y
Zusammen ergibt sich eine sehr knappe Implementierung des Algorithmus:
Wenn Sie diese Herangehensweise an die Implementierung von Algorithmen erlernen, sind Ihre Lösungen so knapp wie dieser Code.
Hier sind einige Tricks, die ich im Laufe der Zeit gesammelt habe. Diese Liste wird erweitert, sobald ich mehr Kenntnisse im J-Golf-Bereich habe.
=
anfangs seltsam, aber sehr nützlich bei ASCII-Kunstherausforderungen.&
in stillschweigenden Kontexten, wenn Sie eine Machtverbindung wünschen. Das Vokabular schlägtu@[&0
als stillschweigende Ersetzung vor,4 : 'u^:x y
und ich auch.[:
oder@:
eine Sequenz vermeiden,u@v
indem Sie eine Varianteu
mit einem linken Argument auswählen . Wenn Sie beispielsweise das erste Element des Ergebnisses vonv
löschen1}.v
möchten , verwenden Sie anstelle von,[:}.v
wenn}.@v
dies aus irgendeinem Grund nicht möglich ist.] v
ist oft kürzer, alsv@]
wenn Sie monadischv
in einem dyadischen Kontext verwenden möchten . Dies ist besonders dann nützlich, wennv
es sich um einen langen Zug von Verben handelt.m (n v w) y
statt schreiben(n v m&w) y
. Auf diese Weise können Leerzeichen und Klammern vermieden werden.#\
statt>:@i.@#
.u &. v
ist nützlich, wennv
eine Vorderseite hat. Wenn nicht, möchten Sie vielleicht verwenden[: vinv u & v
oderu & (v :. vinv)
verwenden.^:_
ist äußerst nützlich für Algorithmen, bei denen Konvergenz erreicht werden soll, z. B. bei einer Überflutung oder Simulationen.=.
und=:
können überall in eine Phrase eingebettet werden. Verwenden Sie diese Option, um Einzeiler zu erstellen, bei denen die implizite Notation nicht ausreicht.,
beim Reduzieren mehrdimensionaler Arrays statt mehrfacher Reduzierungen.quelle
Seien Sie vorsichtig bei der Verwendung von Schleifen.
Während J Strukturen hat Looping (
for. do. end.
,while. do. end.
und Variationen), wenn Sie sich dort mit finden die Möglichkeit , dass Ihr Algorithmus nicht Golf spielen J Stärken spielt und dass es Charakter Einsparungen gemacht werden.^:
Die Machtverbindung ist dein Freund. So führen Sie ein Verbx
mal aus:Wenn Sie das Ergebnis jeder Iteration in einer Liste benötigen:
Sie können auch
^:
ein Verb mit folgenden Bedingungen ausführen:Verdoppeln Sie,
+:
wenn^:
das Element größer als 3 ist3<]
(das"0
ändert den Rang des Verbs, sodass es jeweils für ein Element gilt).quelle
(i.x)
Beispiel, sind alsof^:(<x)
äquivalent zuf^:(i.x)
.Eingang
1!:1[1
wird eine Eingabezeile dauern, die durch Drücken der Eingabetaste beendet wird.1!:1[3
nimmt eine Reihe von Eingabezeilen (beendet mit Strg-D auf meinem Mac, Strg-C unter Windows).Wenn Sie versuchen, Zahlen einzugeben,
".
wird die Zeichenfolge mit ausgewertet und eine Liste von Zahlen zurückgegeben, die bearbeitet werden können. Wenn Sie eine Zahl eingeben, aber die Ziffern einzeln bearbeiten müssen".,.
(dank des Kommentars von Jan Dvorak) oder"."0
die Zeichenfolge in separate Ziffern aufteilen möchten:Wenn Sie Zeichenfolgen einlesen, ist der kürzeste Weg, eine Box-Liste mit separaten Zeichenfolgen zu erhalten, die Verwendung
;:
. Dies funktioniert am besten für durch Leerzeichen getrennte Zeichenfolgen:quelle
1!:1[2
sich als (wenn überhaupt) herausstellen?1!:
Seite erfassen kann (ich bin kein J-Experte), ist 2 der Bildschirm, sodass Eingaben über den Bildschirm nicht viel Sinn ergeben.2
es nicht gültig ist? Ich habe meinen J-Computer momentan nicht zum Ausprobieren. Wo ich sehe2
, knapp unter den Notizen über1!:1
, ist es für1!:2
.".
Rang 1-xx ist und,.
immer ein 2D-Array erzeugt, kann".,' ',.
(Stich mit Leerzeichen, Ravel und Evaluieren; 8 Zeichen) durch nur".,.
(Ravel-Elemente und Evaluieren; 4 Zeichen) ersetzt werden.Verwenden der Iteration zum Berechnen von Sequenzen
Normalerweise müssen Sie zum Lösen einer OEIS-Sequenzanforderung eine der auf der Seite angegebenen Formeln verwenden. Einige passen gut zu J, andere weniger. Rekursive Formeln sind unkompliziert, die Iteration ist jedoch möglicherweise nicht einfach. Ein Muster, mit dem ich angefangen habe, ist
Dabei
s
ist Wobei der erste Wert in der Sequenzf
ist, ein Verb, das den nächsten Term berechnet, wenn der vorherige Term angegeben ist, undn
der auf Null basierende Index des Terms, den Sie berechnen möchten. Diese Methode beruht auf der Tatsache, dass bei der Berechnung der Potenz einer Dyade die LHS an die Dyade gebunden wird, um eine neue Monade zu bilden, und diese Monade auf dem Anfangswert verschachtelt ist. Die dem Power-Adverb zugewiesene Dyade ist ein Hook, bei(]f)
dem der Indexn
für die LHS und der Wert eines Terms in der Sequenz angegeben werdens
. Der Haken giltf
aufs
als Monade, und dann ignoriertn
das Ergebnis zurückf s
.Standardbibliothek
Manchmal werden Sie vielleicht feststellen, dass J ein Verb in seiner Standardbibliothek unterstützt . Beispielsweise sind die meisten bitweisen Ganzzahloperationen an Namen gebunden, die kürzer sind als die Verwendung des primitiven Aufrufs.
Datums- und Zeitangaben sind ebenfalls verfügbar.
Bereiche
Wenn Sie eine Reihe von Werten haben
[a, b, c]
und einen Bereich basierend auf dem Produkt bilden möchten[0, 1, 2, ..., a*b*c-1]
, besteht der typische Ansatz darin, das Produkt zu finden und dann einen Bereich zu bilden, der möglicherweise[:i.*/
6 Byte kostet. Ein kürzerer Weg ist,@i.
für 4 Bytes, dai.
mehrdimensionale Arrays gebildet werden können, während immer noch hochgezählt wird, und durch Reduzieren wird ein gleichwertiger Bereich erzeugt.Fortlaufend drucken
Eine stillschweigende Möglichkeit, einen Wert auszudrucken und ihn ohne explizite Schleife weiter zu verwenden, ist
([echo)
für einen monadischen Fall.echo
ist ein Verb in der Standardbibliothek, das seinen Inhaltstdout
in dem Format ausgibt, das im Interpreter verwendet wird. Der Hook gibt dann den gleichen Eingabewert mit dem linken[
Verb aus.Basis 10 Stellen einer ganzen Zahl
Die Standardmethode zum Erfassen der 10-stelligen Basis einer Ganzzahl ist,
10#.inv]
dass 8 Byte zu viel kosten! Eine Alternative besteht darin, es in eine Zeichenfolge zu konvertieren und bei Rang 0 zu analysieren,"."0@":
wodurch ein Byte gespeichert wird. Eine noch bessere Möglichkeit ist,.&.":
, ein weiteres Byte zu speichern, wodurch die endgültigen Kosten 6 Bytes anstelle von 8 Bytes betragen.quelle
Verwenden Sie eine explizite Definition, anstatt ein implizites Verb zu schreiben. sicher,
3 :'
und'
kosten 5 Bytes, aber Sie können viel sparen@
,@:
und[:
das auf diese Weise.quelle
Einige (ziemlich) häufige Tricks, die ich gesehen habe
Ich teile ein paar Dinge, die sich für mich als nützlich erwiesen haben. Grundsätzlich sind dies alles Tipps, die ich selbst erhalten habe, aber für die meisten habe ich keine Credits.
Summe eines Arrays des ersten Ranges
Anstatt zu
+/@:(FGH)
benutzen(1#.FGH)
. Dies bedeutet eine Verschlechterung auf Basis 1, was effektiv ein Aufsummieren eines Arrays bedeutet. Obwohl es länger als ist+/
, erfordert es keine Kappe oder Komposition, was es oft viel kürzer macht als die Verwendung+/
.Hinterwahrheiten zählen
Wenn Sie eine Boolesche Liste haben und die Anzahl der nachgestellten Wahrheiten zählen möchten, verwenden Sie
#.~
. Sehen Sie hier . Die APL-Antwort bietet eine gute Erklärung dafür, wie dies funktioniert. Zugegeben, das war nur zweimal hilfreich für mich, aber ich dachte, ich würde es trotzdem teilen.Unter (&.)
Kein bestimmter Trick, sondern nur ein allgemeiner Vorschlag: das Adverb
&.
-under führt oft zu eleganten und (was noch wichtiger ist) kurzen Lösungen. Denken Sie daran, wenn Sie Golf spielen.Oft ist es nützlich für binäre und andere Basisumwandlungsprobleme, z. B. diesen Code, der das höchstwertige Bit aus einer Zahl entfernt:
}.&.#:
(In eine Liste von Binärziffern umwandeln, die erste Ziffer entfernen, dann die Umwandlung in eine Liste von Binärziffern rückgängig machen und umwandeln zurück zur Dezimalzahl). Die einfache Lösung ist zwei Bytes:#.@}.@#:
.Unter ist auch hilfreich bei Herausforderungen, bei denen Sie mit Dezimalstellen arbeiten müssen, da Sie diese verwenden können
u&.":
. Zum Beispiel gibt der kurze Weg Meilen zum Aufteilen auf Dezimalstellen unter:,.&.":
.Ein letztes Beispiel ist das Ermitteln der Größe eines Vektors:
+/&.:*:
Beachten Sie, dass Sie alle Ergebnisse von*:
-square mit -under erfassen müssen,&.:
da*:
-square den Rang Null hat.quelle
Kürzere Wege, sich mit Rängen zu messen
Manchmal haben Sie Code wie
<"0 i.3 3
, wo Sie ein Verbv
im Rang anwenden möchtenr
. Wenn Sie jedoch ein Substantiv (wie0
) verwenden, müssen Sie häufig ein Leerzeichen einfügen. Um dies zu vermeiden, können Sie stattdessen ein anderes Verbu
mit gleichem Rang verwendenu"v
. Da zum Beispiel+
rank hat0 0 0
, können wir<"+
statt benutzen<"0
.Hier ist eine Tabelle aller Verben und ihrer Ränge (erhältlich mit
v b. 0
):Um diese Tabelle zu verwenden, finden Sie den gewünschten Rang
r
auf der linken Seite, und wählen Sie dann auf der rechten Seite ein geeignetes Verbv
aus. Wenn ich zum Beispiel ein Verbv
in der Tiefe vektorisieren muss2 _ 2
, finde ich diesen Rang auf der linken Seite und wähle ihn%.
auf der rechten Seite aus. Dann benutze ichv"%.
stattv"2 _ 2
.quelle
strings
Bibliothek: GolftippsDie Zeichenfolgenbibliothek ist äußerst hilfreich, um Zeichenfolgen zu manipulieren. Sicher, es dauert
include'strings'
(was in Anbetracht von J sehr kostspielig ist), aber manchmal können Sie die Vorteile nutzen.stringreplace
Finden Sie sich mit String ersetzen? Beachten Sie, dass dies
A stringreplace B
dasselbe ist wieB rplc A
.In der Tat ist dies so
rplc
implementiert:cuts
Das Verb
cuts
sieht also vor:Es schneidet also wirklich eine Schnur.
quelle
Zahlen von 0 bis 4 erhalten
Wenn die Verwendung von Zahlen in Ihrem Code eingeschränkt ist:
0
%_
: eins geteilt durch unendlich.1
#_
: wie viele Unendlichkeiten?2
#_ _
: zwei Unendlichkeiten.3
verb
: Es gibt eine eingebaute.4
dyad
: ein anderes eingebautes.Zahlen von 10 bis 35 erhalten
Base-inifinity Literale: 11 :
_bb
, 26 :_bq
usw.quelle
Implizite Programmierung
Grundlagen
Dyadisches Verb
Monadisches Verb
Sonstiges
Tricks
(F x) G (H y)
Tacit Lösung:
(G~F)~H
; In Abhängigkeit von den tatsächlichen Verben sollten Sie erwägen, die zu entfernenden Argumente left und right neu anzuordnen~
.Monadisch-dyadischer Ersatz
quelle
(G~F)~H
ist pure sprudelnde Güte!&
ist dein Freund, benutze es mit Bedachtv
ist ein Verb,n
ist ein Substantivx
undy
sind jeweils linke und rechte Argumente.Monade
&
: Stellen Sie sich vor~
Innerhalb der Adverb- / KonjunktionsketteEine Adverb- / Konjunktionskette wird von links ausgewertet. So etwas
_2&+/\&.>
wird nicht funktionieren, weil es analysiert, wie(_2&+)/\&.>
wir wollen_2&(+/\)&.>
. In diesem Fall kann durch Tauschen von links / rechts+/\
ein Byte gespart werden,+/\~&_2&.>
da dieses wie folgt analysiert wird((+/\)~)&_2&.>
. So sehen Sie, warum dies funktioniert:Dyad
&
: Wiederholex
malWissen Sie, dass , wenn Sie ein linkes Argument geben
x
zu&
, gilt die Funktion esx
maly
? Bei einigen Herausforderungen müssen Sie bestimmte Betriebszeitenx
einhalten. Es ist hauptsächlich auf zwei Arten erreichbar:^:
ohne rechten OperandenWenn die Operation ist
v
,v^:
wird sie zu einem Adverbzug, der, wenn ein linker Operand gegeben wird, zu einem monadischen Verb wird. Sov
wird angewendety
,x
mal.&
als äußerste KonjunktionUm dies zu verwenden, müssen Sie eine Konstante
n
und ein dyadisches Verb identifizierenu
, sodass entwedern u y
odery u n
äquivalent zu istv
. Dann können Sie schreibenn&u
oderu&n
die gesamte Aufgabe lösen. Diese Form ist am effektivsten, wenn die Wahl der Konstante offensichtlich ist, z. B. 33 u:
Zoll (Zeichen in ASCII-Werte konvertieren).Wird auch
u&n
etwas vorgezogen,n&u
wenn die äußerste Struktur vonu
eine Konjunktion oder ein Adverb ist (in diesem Falln&u
sollte dies der Fall seinn&(u)
; Sie können diesu~&n
stattdessen tun ).Beachten Sie, dass Sie die Dyade
&
an einer beliebigen Stelle in einem Zug platzieren können, um die Wiederholung einer beliebigen Funktion für ein beliebiges Argument zu erreichen, ähnlich wie bei einer dynamischen^:
.quelle