Golftipps in Perl 6

16

Welche allgemeinen Tipps haben Sie zum Golfen in Perl 6? Ich bin auf der Suche nach Ideen, die sich auf Code-Golf-Probleme im Allgemeinen anwenden lassen, die zumindest etwas spezifisch für Perl 6 sind (z. B. "Kommentare entfernen" ist keine Antwort). Bitte posten Sie einen Tipp pro Antwort.

Bitte beachten Sie, dass Perl 6 nicht Perl 5 ist, daher handelt es sich bei dieser Frage nicht um ein Duplikat. Die meisten Tipps zum Golfen mit Perl 5 gelten nicht für Perl 6.

Konrad Borowski
quelle

Antworten:

9

Vermeiden Sie subLiterale. In vielen Fällen können Sie sie einfach {}für Codeblöcke verwenden. Schreiben Sie beispielsweise nicht den folgenden Code.

sub ($a){$a*2}

Verwenden Sie stattdessen die Blocksyntax. Auf diese Weise können Sie auch verwenden $_, @_und %_Platzhalter - Variablen, wenn Sie nur eine einzige Variable benötigen. Wenn Sie mehr benötigen, können Sie verwenden $^a, $^bVariablen und so weiter.

{$_*2}

In bestimmten seltenen Fällen ist es auch möglich, beliebigen Code zu verwenden (insbesondere, wenn Sie einfache Ausdrücke haben). Das *ersetzt das Platzhalterargument.

* *2
Konrad Borowski
quelle
8

Perl 6 hat eine wirklich bizarre Funktion, mit der alle Unicode-Zeichen in den Kategorien Nd , Nl und  No als rationale Zahlenliterale verwendet werden können. Einige davon sind kürzer als das Ausschreiben ihrer numerischen Werte in ASCII:

  • ¼(2 Bytes) ist kürzer als .25oder 1/4(3 Bytes).
  • ¾(2 Bytes) ist kürzer als .75oder 3/4(3 Bytes).
  • (3 Bytes) ist kürzer als 1/16(4 Bytes).
  • 𐦼(4 Bytes) ist kürzer als 11/12(5 Bytes).
  • 𒐲(4 Bytes) ist kürzer als 216e3(5 Bytes).
  • 𒐳(4 Bytes) ist kürzer als 432e3(5 Bytes).
Lynn
quelle
Als Folgemaßnahme können Sie auch Unicode-Exponenten verwenden, auch mit mehreren Ziffern und / oder einem Minus: say (3² + 4², 2²⁰, 5⁻²)==> (25 1048576 0.04). Die vollständige Liste von Unicode, die Sie so missbrauchen können, finden Sie hier: docs.perl6.org/language/unicode_texas .
Ramillies
8

Lernen Sie die Funktionen zum Lesen der Eingabe. Perl 6 verfügt über viele interessante Funktionen, mit denen die Eingabe von ARGV oder STDIN (sofern in ARGV nichts angegeben wurde) leicht gelesen werden kann. Bei korrekter Verwendung kann dies Ihren Code verkürzen. Wenn Sie sie als Dateihandle-Methoden aufrufen, können Sie sie zwingen, mit einem bestimmten Dateihandle zu arbeiten (nützlich, wenn Sie beispielsweise aus lesen STDIN, aber Argumente in ARGV lesen müssen).

get

Diese Funktion erhält eine einzelne Zeile und kaut diese automatisch, sodass Sie dies nicht tun müssen. Dies ist nützlich, wenn Sie nur eine Zeile lesen müssen.

lines

Diese Funktion holt alle Zeilen aus der Datei oder STDIN. Es ist eine faule Liste. Wenn Sie sie also mit verwenden for, wird nur das gelesen, was Sie benötigen. Beispielsweise.

say "<$_>"for lines

slurp

Dadurch wird die gesamte Datei oder STDIN gelesen und das Ergebnis als einzelne Zeichenfolge zurückgegeben.

Konrad Borowski
quelle
Dieser Fehler wurde behoben - weiß nicht wann, say "<$_>" for linesfunktioniert aber jetzt
Katze
5

Warnung : Textwand nähert sich. Es sind viele kleine Tricks, die ich im Laufe der Zeit gesammelt habe.

Schreiben Sie Ihre Lösungen als anonyme Blöcke

Dies wurde bereits erwähnt, aber ich möchte es wiederholen. In TIO können Sie my $f =in den Header und den Block in den Code schreiben und die Fußzeile mit einem beginnen ;. Dies scheint bei weitem der kürzeste Weg zu sein, um die Arbeit zu erledigen (da Sie sich nicht um das Lesen von Eingaben kümmern müssen, wird dies in den Argumenten angegeben).

Eine andere gute Möglichkeit ist die Verwendung des Schalters -noder -p, aber ich habe keine Möglichkeit gefunden, ihn in TIO zum Laufen zu bringen.

Verwenden Sie die Doppelpunktsyntax zum Übergeben von Argumenten

Das heißt, stattdessen thing.method(foo,bar)können Sie thing.method:foo,bar1 Zeichen ausführen und speichern. Leider können Sie aus offensichtlichen Gründen keine andere Methode für das Ergebnis aufrufen. Daher ist es sinnvoll, nur die letzte Methode in einem Block zu verwenden.

Verwenden Sie $_so viel wie möglich

Manchmal ist es aus diesem Grund besser, ein einzelnes Listenargument als mehrere separate Argumente zu verwenden. Beim Zugriff $_können Sie Methoden aufrufen, indem Sie mit einem Punkt beginnen: zB .sortist gleich $_.sort.

Bedenken Sie jedoch, dass jeder Block seinen eigenen erhält $_, damit die Parameter des äußeren Blocks nicht in den inneren übertragen werden. Wenn Sie von einem inneren Block aus auf die Parameter der Hauptfunktion zugreifen müssen, ...

Verwenden Sie die ^Variablen, wenn Sie sie nicht verwenden können$_

Legen Sie eine ^zwischen dem Sigil und dem Variablennamen, wie folgt aus : $^a. Diese funktionieren nur innerhalb eines Blocks. Der Compiler zählt zuerst, wie viele davon Sie im Block haben, sortiert sie lexikografisch und weist dann dem ersten das erste Argument zu, dem zweiten das zweite und so weiter. Das ^muss nur beim ersten Auftreten der Variablen verwendet werden. Nimmt also {$^a - $^b}2 Skalare und subtrahiert sie. Das Einzige, was zählt, ist die alphabetische Reihenfolge, {-$^b + $^a}genau wie das Gleiche.

Wenn Sie jemals Lust haben, die Syntax für spitze Blöcke (wie ->$a,$b {$a.map:{$_+$b}}) zu verwenden, ist es weitaus besser, falsche Anweisungen am Anfang des Blocks zu schreiben, indem Sie ^für jedes Argument, das Sie nicht im Hauptblock verwenden möchten (wie {$^b;$^a.map:{$_+$b}}) (Anmerkung Das ist der bessere Weg, Golf zu spielen {$^a.map(*+$^b)}. Ich wollte nur das Konzept vorführen.)

Lesen Sie die Bedienungsanleitungen sorgfältig durch

Die Bediener sind sehr mächtig und oft der kürzeste Weg, um Dinge zu erledigen. Insbesondere die Meta-Operatoren (Operatoren, die Operatoren als Argument nehmen) [],[\] , X, <</ >>und Zist es wert , Ihre Aufmerksamkeit. Vergessen Sie nicht, dass ein Meta-Op ein anderes Meta-Op als Argument verwenden kann (wie XZ%%ich es hier geschafft habe ). Sie können sie auch >>für einen Methodenaufruf verwenden, der viel billiger ist als eine Karte ( @list>>.methodanstatt @list.map(*.method), aber Vorsicht, sie sind nicht gleich! ). Und bevor Sie schließlich eine Binärdatei verwenden << >>, sollten Sie bedenken, dass dies Zhäufig in viel weniger Zeichen der Fall ist.

Wenn Sie viele Meta-Ops aufeinander häufen, können Sie die Priorität in eckigen Klammern angeben []. Das erspart Ihnen, wenn Sie so viele Operatoren anhäufen, dass der Compiler verwirrt wird. (Das kommt nicht sehr oft vor.)

Schließlich, wenn Sie brauchen , um coerce Dinge Bool, Int oder Str, nicht die Methoden verwenden .Bool, .Intund .Str, sondern die Betreiber ?, +und ~. Oder noch besser, setzen Sie sie einfach in einen arithmetischen Ausdruck, um sie in Int und so weiter zu zwingen. Der kürzeste Weg, um die Länge einer Liste zu ermitteln, ist +@list. Wenn Sie 2 hoch der Länge einer Liste berechnen möchten, sagen 2**@listSie einfach und es wird das Richtige tun.

Verwenden Sie die freien Zustandsvariablen $, @und%

In jedem Block jedes Vorkommen von $ bezieht sich (oder @oder %) auf eine glänzende neue skalare (oder Array- oder Hash-) Zustandsvariable (eine Variable, deren Wert bei bleibt). Wenn Sie eine Statusvariable benötigen, auf die nur einmal im Quellcode verwiesen werden muss, sind diese drei Ihre großen Freunde. (Meistens das $.) Zum Beispiel könnte es bei der Challenge Reverse Math Cycles verwendet werden, um die Operatoren zyklisch aus einem Array auszuwählen, das von indexiert wurde $++%6.

Mithilfe der Unterformen map, grepet al.

Das heißt: lieber tun map {my block},listals list.map({my block}). Selbst wenn Sie es schaffen list.map:{my block}, werden diese beiden Ansätze mit der gleichen Anzahl von Bytes ausgegeben. Und häufig müssen Sie die Liste beim Aufrufen einer Methode in Klammern setzen, nicht jedoch beim Aufrufen einer Sub-Methode. So kommt der Unteransatz immer besser heraus oder zumindest genauso wie die Methode eins.

Die einzige Ausnahme ist hier, wann das Objekt sein soll map ped, grepped usw. sein soll, in befindet $_. Dann .map:{}schlägt offensichtlich map {},$_.

Verwenden Sie Junctions ( &und |) anstelle von &&und ||.

Offensichtlich sind sie 1 Byte kürzer. Andererseits müssen sie zusammengebrochen werden, indem sie in einen booleschen Kontext gezwungen werden. Dies kann immer mit a erfolgen ?. Hier sollten Sie auf ein Meta-Op achten!op Ops das den Bool-Kontext erzwingt, opdas Ergebnis verwendet und negiert.

Wenn Sie eine Liste haben und diese in eine Junction verwandeln möchten, verwenden Sie [&]und nicht [|]. Verwenden Sie stattdessen .anyund .all. Es gibt auch .nonesolche, die von den Junction Ops nicht so einfach nachgeahmt werden können.

Ramillies
quelle
1
Ich denke &&und bin ||immer noch nützlich zum Kurzschließen?
Nur ASCII
@ Nur ASCII: Ja, sicher.
Ramillies
4

Reduzieren Sie den für Variablen verwendeten Speicherplatz

Es gibt ein paar Teile dazu.

Leerzeichen entfernen

Mit deklarierte Variablen mykönnen normalerweise ohne das Leerzeichen zwischen myund dem Variablennamen deklariert werden . my @aist äquivalent zu my@a.

Verwenden Sie Variablen ohne Siegel

Sie können Variablen mit einem Backslash deklarieren, um das Siegel vor dem Variablennamen zu entfernen.

my \a=1;

(das Leerzeichen kann leider nicht entfernt werden :()

Dies ist nützlich, da Sie sie später nur als bloßen Variablennamen bezeichnen können.

 a=5;
 a.say

Grundsätzlich werden dadurch Bytes gespart, wenn Sie die Variable mehrmals an einer anderen Stelle im Code verwenden. Der Nachteil ist, dass die Variable initialisiert werden muss.

Verwenden Sie $!und$/

Diese vordeklarierten Variablen werden normalerweise für Ausnahmen bzw. reguläre Ausdrücke verwendet, müssen jedoch nicht mit definiert werden my.

$!=1;
$/=5;

Besonders nützlich ist die Verwendung $/als Array und die Verwendung der Verknüpfungen, $gefolgt von einer Zahl, um auf dieses Element des $/Arrays zuzugreifen .

$/=100..200;
say $5;  #105
say $99; #199
Scherzen
quelle
2

Verwenden Sie ...anstelle vonfirst

In der Regel können Sie die erste Zahl, die einer Bedingung entspricht &f, folgendermaßen darstellen:

first &f,1..*

Sie können jedoch stattdessen die ... Operator verwenden:

+(1...&f)

Wenn Sie anfangen müssen 0, können Sie haben-1 danach statt +.

Wenn Sie den Index des ersten Elements in einer Liste @amit Bedingungen &fanzeigen möchten , gehen Sie normalerweise wie folgt vor:

first &f,@a,:k

Stattdessen:

(@a...&f)-1

(oder umgekehrt, wenn 0 indiziert werden soll). Auf die gleiche Weise können Sie alle Elemente bis zu dem ersten Element abrufen, das die Bedingung erfüllt.

Nachteile hierfür ist , dass die Liste hat den Zustand irgendwann passieren, sonst wird der ...Betreiber versucht , über das Ende der Liste zu extrapolieren, und höchstwahrscheinlich einen Fehler aus. Sie können auch keinen beliebigen Code auf der linken Seite verwenden, da dieser als Teil der Sequenz interpretiert wird.

Scherzen
quelle