Golftipps in Röda


12

Röda ist eine Stream-basierte Skriptsprache, die von fergusq erstellt wurde .

Welche allgemeinen Tipps haben Sie zum Golfen in Röda? Ich bin auf der Suche nach Ideen, die sich auf Code-Golf-Probleme anwenden lassen und die zumindest etwas spezifisch für Röda sind (z. B. "Kommentare entfernen" ist keine Antwort).

Bitte posten Sie einen Tipp pro Antwort.


Versuchen Sie, Tipps zu bekommen, um mich im Golf zu schlagen? : P (Ich sollte wahrscheinlich auf die Tipps für Python Seite schauen)
HyperNeutrino

Wow, eine Frage von PCG.SE, die in die Hot Network Questions eingegangen ist und kein Programmierpuzzle / Herausforderung ist! :)
Pedro A

1
@HyperNeutrino Shhh .... :)
Kritixi Lithos

Antworten:


7

Verwenden Sie Unterstriche

Dies ist wahrscheinlich der wichtigste Tipp. Nahezu jedes Golf-Röda-Programm verwendet Unterstriche.

Die Unterstreichungssyntax ist syntaktischer Zucker für forSchleifen. Die folgenden Codezeilen sind äquivalent:

ls""|fileLength x for x|sort|pull
ls""|fileLength _|sort|pull

Jeder Unterstrich fügt einer unsichtbaren forSchleife, die die Anweisung umgibt, eine neue Variable hinzu . Die Schleife zieht für jede Variable / jeden Unterstrich einen Wert aus dem Stream und wiederholt diesen, bis keine Werte mehr übrig sind.

Unterstriche können überall in Anweisungen verwendet werden:

a[x:y+1]=[1]*(1+y-x) /* Sets range x..y (inclusive) */
seq x,y|a[_]=1       /* 6 bytes less */

Wenn Sie mehrmals auf denselben Unterstrich verweisen müssen oder die Werte in umgekehrter Reihenfolge verwenden, können Sie nach dem Unterstrich eine Zahl einfügen:

a|[_^_1]  /* maps x to x^x */
a|[_2-_1] /* maps each pair (x,y) to y-x, eg. [1,2,4,8] -> [1, 4] */

3

Einige Semikolons / Zeilenumbrüche sind optional

Beim Schreiben von Röda-Code wird generell empfohlen, Zeilenumbrüche oder Semikolons zu verwenden, um alle Anweisungen zu trennen. Beim Golfen ist es jedoch wichtig zu wissen, dass nicht alle Semikolons wirklich benötigt werden.

Hier ist eine unvollständige Liste von Stellen, an denen Semikolons / Zeilenumbrüche optional sind . Die meisten von ihnen gelten nicht , wenn die folgende Anweisung mit einem Operator beginnt ( (, [, +, etc.).

  • Nach Aufträgen
  • Nach Funktionsaufrufen, wenn mindestens ein Argument vorhanden ist (z. B. f x) oder wenn Klammern verwendet werden (z. B. f())
  • Überall dort, wenn die nächste Zeile / Anweisung beginnen würde , mit |, ), ]oder}

Wenn die nächste Anweisung mit einem Operator beginnt, ist das Semikolon / die neue Zeile optional, wenn

  • Die Anweisung ist ein Funktionsaufruf und Klammern werden verwendet, z . B. {f(x)[y]}wie {f(x);[y]}. Dies funktioniert nur im Anweisungskontext, nicht wenn der Funktionsaufruf ein Ausdruck ist.
  • Die Anweisung ist eine Zuweisung und Klammern werden verwendet, z. B. x=(y)[z]ist dieselbe wie x=(y);[z](das ist nicht dieselbe wie x=((y)[z])).

Und hier sind einige Stellen, an denen die Zeilenumbrüche leider erforderlich sind :

  • Nach ++und --.
  • Nach [...].

Es ist oft möglich, Bytes zu speichern, indem Zuordnungen neu organisiert werden. Beispielsweise:

a=0;b=""c=[""]
b=""c=[b]a=0

x=f()y=i;z=a[0]
x=f()z=a[0]y=i

1

Verwenden Sie Suffix-Kontrollstrukturen

Es ist fast nie optimal, keine Suffix-Anweisungen zu verwenden, wie Sie sie {...}anstelle von verwenden können do...end.

Einige Beispiele:

x|unless[not(_ in y)]do[0]else[1]done
x|[0]unless[not(_ in y)]else[1]

if[p<0]do c+=p;a-=p done
{c+=p;a-=p}if[p<0]

Können Sie if[_ in y]stattdessen tun ?
Kritixi Lithos

@KritixiLithos Nein, weil ich möchte, dass die Bedingung ODER ist, nicht UND. Gegenwärtig wird geprüft, ob mindestens ein Wert xdarin enthalten ist y, aber Ihre Bedingung prüft, ob alle Werte darin enthalten xsind y. (Das Beispiel wurde von hier kopiert ).
Fergusq

1

Verwenden Sie den Stream für die Eingabe

In Fällen, in denen die Eingabe eine Liste von Elementen ist, kann es hilfreich sein, die Werte aus dem Stream abzurufen, anstatt sie als Array abzurufen.

In den meisten Fällen werden die Array-Elemente iteriert, indem sie in den Stream verschoben und anschließend mit einer forSchleife (oder einem Unterstrich) iteriert werden . Da die Elemente ohnehin aus dem Stream iteriert werden, definieren Sie , dass sie von Anfang an vorhanden sein sollen.

So berechnen Sie beispielsweise die Summe der Quadrate der eingegebenen Zahlen:

{|a|a|[_^2]|sum} /* Removing a redundant argument */
{[_^2]|sum}      /* saves 5 bytes */

1

Die Klammern sind im Anweisungskontext optional. Dies gilt auch dann, wenn das Argument mit einem Operator beginnt. Zum Beispiel [a()|sqrt-_]ist kürzer als [a()|sqrt(-_)]. Die Klammern nach asind obligatorisch, wie aim Ausdruckskontext, nicht im Anweisungskontext.

Allerdings Schreiben [a()|sqrt(_+1)*2]ist nicht möglich , und zusätzliche Klammern nötig sind , um den Parser zu helfen: [a()|sqrt((_+1)*2)]. Oft ist es möglich, einen solchen Ausdruck so umzuschreiben, dass er nicht mit einer Klammer beginnt:[a()|sqrt 2*(_+1)]


Ist es auch möglich, mehrere Parameter an Funktionen zu übergeben, ohne dass Klammern erforderlich sind?
Kritixi Lithos

@KritixiLithos Ja. Z.B. [a()|atan2 _,_]wäre erlaubt.
Fergusq

1

Verwenden Sie ,anstelle von ..in []/ pushAnweisungen

Verwandte: Verwenden Sie ,anstelle vonand

Die pushFunktion (wie auch die printFunktion) kann eine beliebige Anzahl von Argumenten annehmen und gibt jedes von ihnen ohne Begrenzer aus.

Das heißt also so etwas

["a"..b]        /*8 bytes (string "a" concatenated with variable b)*/

kann in gerade gekürzt werden

["a",b]         /*7 bytes*/

Einsparung von 1 Byte.


1

[]/ push>print

Verwenden Sie niemals printAnweisungen. []Push-Anweisungen sind immer Golfspieler. Der Unterschied zwischen printund pushbesteht darin, dass die erste Zeile eine nachgestellte Zeile ausgibt, während die zweite Zeile keine Zeile ausgibt. Dies kann jedoch umgangen werden.

print"a"              /* 8 bytes */
["a                   /* 6 bytes; uses a literal newline */
"]

print"a",b            /* 10 bytes */
[`a$b                 /* 8 bytes; uses a literal newline and `` strings */
`]

1

Mit ``Strings

In ""Strings müssen Sie bestimmte Zeichen mit einem Escapezeichen versehen, um sie verwenden zu können. Um beispielsweise den umgekehrten Schrägstrich auszudrucken, müssten Sie eine Zeichenfolge wie haben "\\". Es gibt ein zusätzliches Byte, um den Backslash zu umgehen. Wenn Sie jedoch verwenden ``, müssen Sie dieses Zeichen nicht maskieren und können ein Byte speichern.

print"\\"     /* 9 bytes */
print`\`      /* 8 bytes */

Darüber hinaus können Sie Variablen und Ausdrücke in ``Zeichenfolgen mit $variableNameoder codieren ${expression}, einer Funktion, die in ""Zeichenfolgen nicht vorhanden ist .

In diesen Beispielen wird die "a"mit dem Wert der Variablen verkettete Zeichenfolge bmit einer nachgestellten Zeile ausgegeben.

["a",b,"      /* 11
"]               bytes   */
[`a$b         /* 8
`]               bytes; encodes b in the string using $b */

1

Verwenden Sie ,anstelle vonand

Bedingungen in Röda sind Ströme und können aus mehreren Werten bestehen. Diese Werte werden mit auf einen Booleschen Wert reduziert and.

Dies bedeutet , dass Sie ersetzen können andmit ,den Bedingungen mehrere Werte in den Stream zu drücken:

x if[a and b]
x if[a,b]

Leerer Zustand ist wahr

Es ist auch möglich, eine Bedingung zu haben, die keine Werte enthält, was wahr ist.

x while true
x while[]

1

Schreibe Ersatzlisten in Form *"...;..."/";"

Die replaceFunktion verwendet normalerweise eine Liste von Zeichenfolgen als Argumente. Wenn die Liste jedoch sehr lang ist, ist es vorteilhaft, die Regex / Ersatz-Paare einfach in einer Zeichenfolge zu speichern, die Zeichenfolge dann zu teilen und den Stern-Operator zu verwenden:

replace"a","b","c","d"
replace*"a;b;c;d"/";"
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.