Suggerimenti per giocare a golf in Perl 6


16

Quali consigli generali hai per giocare a golf in Perl 6? Sto cercando idee che possano essere applicate ai problemi del codice golf in generale che siano almeno in qualche modo specifiche per Perl 6 (ad esempio "rimuovere i commenti" non è una risposta). Si prega di inviare un suggerimento per risposta.

Si noti che Perl 6 non è Perl 5, quindi questa domanda non è un duplicato. La maggior parte dei suggerimenti per il golf Perl 5 non si applica al Perl 6.

Risposte:


9

Evita i subletterali. In molti casi, puoi semplicemente utilizzare {}per i blocchi di codice. Ad esempio, non scrivere il seguente codice.

sub ($a){$a*2}

Utilizzare invece la sintassi dei blocchi. Ciò consente anche di utilizzare $_, @_e %_variabili segnaposto, se è necessaria una sola variabile. Se avete bisogno di più, è possibile utilizzare $^a, $^ble variabili, e così via.

{$_*2}

Inoltre, in alcuni rari casi, è possibile utilizzare qualsiasi codice (soprattutto quando si hanno espressioni semplici). Il *sostituisce l'argomento segnaposto.

* *2

8

Perl 6 ha una caratteristica davvero bizzarra in cui consente a tutti i caratteri Unicode nelle categorie Nd , NlNo di essere usati come letterali numeri razionali. Alcuni di questi sono più brevi rispetto alla scrittura dei loro valori numerici in ASCII:

  • ¼(2 byte) è più breve di .25o 1/4(3 byte).
  • ¾(2 byte) è più breve di .75o 3/4(3 byte).
  • (3 byte) è più breve di 1/16(4 byte).
  • 𐦼(4 byte) è inferiore a 11/12(5 byte).
  • 𒐲(4 byte) è inferiore a 216e3(5 byte).
  • 𒐳 (4 byte) è inferiore a 432e3(5 byte).

Come follow-up per questo, puoi anche usare esponenti Unicode, anche con più cifre e / o meno: say (3² + 4², 2²⁰, 5⁻²)==> (25 1048576 0.04). L'elenco completo di Unicode che puoi abusare in questo modo è qui: docs.perl6.org/language/unicode_texas .
Ramillies,

8

Impara le funzioni per leggere l'input. Perl 6 ha molte funzioni interessanti che possono facilmente leggere l'input da ARGV o STDIN (se non è stato specificato nulla su ARGV), che può accorciare il codice se usato correttamente. Se li chiami come metodi di filehandle, puoi forzarli a lavorare su un particolare filehandle (utile se ad esempio leggi daSTDIN , ma devi leggere argomenti su ARGV).

get

Questa funzione ottiene una sola riga e la riduce automaticamente, quindi non è necessario. Questo è utile se devi leggere solo una riga.

lines

Questa funzione ottiene tutte le righe dal file o STDIN. È un elenco pigro, quindi se lo usi con for, leggerà solo ciò di cui hai bisogno. Per esempio.

say "<$_>"for lines

slurp

Questo leggerà l'intero file o STDIN e restituirà il risultato come una singola stringa.


Il bug è stato corretto - non so quando, ma say "<$_>" for linesfunziona ora
cat

5

Avvertenza : muro di testo in avvicinamento. Sono molti i piccoli trucchi che ho raccolto nel tempo.

Scrivi le tue soluzioni come blocchi anonimi

Questo è già stato menzionato, ma vorrei ribadirlo. In TIO, è possibile scrivere my $f =nell'intestazione, il blocco nel codice corretto e avviare il piè di pagina con a; . Questo sembra essere di gran lunga il modo più breve per portare a termine il lavoro (poiché non devi preoccuparti di leggere alcun input, ti viene dato negli argomenti).

Un altro modo carino è usare il -no il-p , ma non ho trovato un modo per farlo funzionare in TIO.

Utilizzare la sintassi dei due punti per passare argomenti

Cioè, invece di thing.method(foo,bar), puoi farething.method:foo,bar e salvare 1 carattere. Sfortunatamente, non puoi chiamare un altro metodo sul risultato per ovvi motivi, quindi ha senso usare solo l'ultimo metodo in un blocco.

Uso $_ il più possibile

A volte è meglio prendere un singolo argomento dell'elenco piuttosto che diversi argomenti separati per questo motivo. Quando si accede $_, è possibile chiamare metodi su di esso solo iniziando con un punto: eg .sortè uguale a$_.sort .

Tuttavia, tieni presente che ogni blocco ottiene il suo $_, quindi i parametri del blocco esterno non si propagheranno in quelli interni. Se è necessario accedere ai parametri della funzione principale da un blocco interno, ...

Usa le ^variabili se non puoi usarle$_

Inserire una ^tra il sigillo e il nome della variabile, in questo modo: $^a. Funzionano solo all'interno di un blocco. Il compilatore conta prima quanti di questi hai nel blocco, li ordina lessicograficamente e quindi assegna il primo argomento al primo, il secondo al secondo e così via. Le ^esigenze da utilizzare solo nella prima occorrenza della variabile. Quindi {$^a - $^b}prende 2 scalari e li sottrae. L'unica cosa che conta è l'ordine alfabetico, così {-$^b + $^a}fa la stessa cosa.

Se hai mai voglia di usare la sintassi del blocco appuntito (come ->$a,$b {$a.map:{$_+$b}}), è molto meglio scrivere un'istruzione fasulla all'inizio del blocco usando il ^per ogni argomento che non userai nel blocco principale (come {$^b;$^a.map:{$_+$b}}) (Nota questo è il modo migliore per giocare a golf {$^a.map(*+$^b)}. Volevo solo mostrare il concetto.)

Leggere attentamente i documenti dell'operatore

Gli operatori sono molto potenti e spesso sono il modo più breve per fare le cose. Soprattutto i meta-operatori (operatori che prendono gli operatori come argomento) [], [\], X, <</ >>e Zsono valore della vostra attenzione. Non dimenticare che una meta-op può prendere un'altra meta-op come argomento (come una che XZ%%sono riuscito a usare qui ). Puoi anche usarlo >>per una chiamata di metodo, che può essere molto più economica di una mappa ( @list>>.methodinvece di @list.map(*.method), ma attenzione, non sono uguali! ). E, infine, prima di usare un binario << >>, tieni presente che Zspesso farà la stessa cosa in molti meno personaggi.

Se si accumulano molte meta-op l'una sull'altra, è possibile specificare la precedenza utilizzando parentesi quadre []. Ciò ti salverà quando accumuli così tanti operatori che confonde il compilatore. (Ciò non accade molto spesso.)

Infine, se avete bisogno di cose costringere a Bool, Int o Str, non si utilizzano i metodi .Bool, .Inte .Str, quanto piuttosto gli operatori ?, +e ~. O ancora meglio, basta metterli in un'espressione aritmetica per forzarli in Int e così via. Il modo più breve per ottenere la lunghezza di un elenco è +@list. Se vuoi calcolare 2 in base alla potenza della lunghezza di un elenco, dì solo 2**@listche farà la cosa giusta.

Utilizzare le variabili di stato libero $, @e%

In ogni blocco, ogni occorrenza di $(o @o %) si riferisce a una nuova brillante variabile di stato scalare (o array o hash) (una variabile il cui valore persiste attraverso le chiamate al blocco). Se hai bisogno di una variabile di stato a cui devi fare riferimento una sola volta nel codice sorgente, questi tre sono i tuoi grandi amici. (Molto spesso il $.) Ad esempio, nella sfida Reverse Math Cycles , potrebbe essere usato per scegliere ciclicamente gli operatori da un array, che è stato indicizzato da $++%6.

Usa i sottoformi di map, grepet al.

Ciò significa: fare piuttosto map {my block},listche list.map({my block}). Anche se riesci a usare list.map:{my block}, questi due approcci escono allo stesso numero di byte. E spesso, è necessario racchiudere tra parentesi l'elenco quando si chiama un metodo, ma non quando si chiama un sub. Quindi l'approccio secondario risulta sempre migliore o almeno uguale a quello del metodo.

L'unica eccezione qui è quando l'oggetto che deve essere mapped, grepped e così via, è dentro $_. Quindi .map:{}ovviamente batte map {},$_.

Utilizzare giunzioni ( &e |) anziché &&e ||.

Ovviamente, sono più brevi di 1 byte. D'altra parte, devono essere collassati per essere costretti in un contesto booleano. Questo può essere sempre fatto con a ?. Qui dovresti essere consapevole di una meta-op !opche forza il contesto bool, usa ope nega il risultato.

Se hai un elenco e vuoi trasformarlo in un incrocio, non usare [&]e [|]. Invece usa .anye .all. C'è anche .noneche non può essere così facilmente imitato dalle operazioni di giunzione.


1
Penso &&e ||sono ancora utili per il corto circuito?
ASCII

@ Solo ASCII: Sì, certamente lo sono.
Ramillies,

4

Ridurre lo spazio utilizzato per le variabili

Ci sono alcune parti in questo.

Rimuovi gli spazi bianchi

Le variabili dichiarate usando di mysolito possono essere dichiarate senza lo spazio tra mye il nome della variabile. my @aè equivalente a my@a.

Usa variabili senza sigillo

Puoi dichiarare le variabili usando una barra rovesciata per rimuovere il sigillo prima del nome della variabile, in questo modo:

my \a=1;

(sfortunatamente non puoi rimuovere lo spazio :()

Questo è utile in quanto puoi quindi fare riferimento a loro come solo il nome della variabile nuda in seguito.

 a=5;
 a.say

Fondamentalmente questo consente di risparmiare byte se si utilizza la variabile più di una volta altrove nel codice. Il rovescio della medaglia è che la variabile deve essere inizializzata.

Usa $!e$/

Queste variabili pre-dichiarate vengono generalmente utilizzate rispettivamente per le eccezioni e le corrispondenze regex, ma non è necessario definirle utilizzando my.

$!=1;
$/=5;

Particolarmente utile è usare $/come array e usare le scorciatoie $seguite da un numero per accedere a quell'elemento $/dell'array;

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

2

Usa ...invece difirst

In genere, se si desidera trovare il primo numero che corrisponde a una condizione &f, è possibile rappresentarlo come:

first &f,1..*

Tuttavia, invece è possibile utilizzare l' ...operatore:

+(1...&f)

Se devi iniziare da 0, puoi avere -1dopo invece di +.

Se si desidera l'indice del primo elemento in un elenco @acon condizioni &f, normalmente si fa:

first &f,@a,:k

Anziché:

(@a...&f)-1

(o viceversa se si desidera 0 indicizzato). Allo stesso modo, puoi ottenere tutti gli elementi fino al primo che supera la condizione.

L'aspetto negativo di questo è che la lista deve passare la condizione ad un certo punto, altrimenti l' ...operatore proverà a estrapolare la fine della lista e molto probabilmente lancerà un errore. Inoltre, non puoi utilizzare qualunque codice nella parte sinistra, poiché verrebbe interpretato come parte della sequenza.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.