Wskazówki do gry w golfa w Perlu 6


16

Jakie masz ogólne wskazówki na temat gry w golfa w Perl 6? Szukam pomysłów, które można zastosować do ogólnych problemów z golfem, które są przynajmniej nieco specyficzne dla Perla 6 (np. „Usuń komentarze” nie jest odpowiedzią). Proszę zamieścić jedną wskazówkę na odpowiedź.

Należy pamiętać, że Perl 6 nie jest Perl 5, więc to pytanie nie jest duplikatem. Większość wskazówek dotyczących golfa w Perlu 5 po prostu nie dotyczy Perla 6.

Odpowiedzi:


9

Unikaj subliterałów. W wielu przypadkach możesz po prostu użyć {}do bloków kodu. Na przykład nie pisz następującego kodu.

sub ($a){$a*2}

Zamiast tego użyj składni bloków. To także pozwala używać $_, @_i %_zmiennych rezerwujących, jeśli trzeba tylko jedną zmienną. Jeśli potrzebujesz więcej, można użyć $^a, $^bzmienne, i tak dalej.

{$_*2}

Ponadto, w niektórych rzadkich przypadkach, można użyć dowolnego kodu (szczególnie gdy masz proste wyrażenia). *Zastępuje argument zastępczy.

* *2

8

Perl 6 ma naprawdę dziwną funkcję, która pozwala wszystkim znakom Unicode w kategoriach Nd , NlNie jako literałów liczb wymiernych. Niektóre z nich są krótsze niż zapisywanie ich wartości liczbowych w ASCII:

  • ¼(2 bajty) jest krótszy niż .25lub1/4 (3 bajty).
  • ¾(2 bajty) jest krótszy niż .75lub3/4 (3 bajty).
  • (3 bajty) jest krótszy niż 1/16 (4 bajty).
  • 𐦼 (4 bajty) jest krótszy niż 11/12(5 bajtów).
  • 𒐲 (4 bajty) jest krótszy niż 216e3(5 bajtów).
  • 𒐳(4 bajty) jest krótszy niż 432e3(5 bajtów).

Jako kontynuację tego możesz również użyć wykładników Unicode, nawet z wieloma cyframi i / lub minusem: say (3² + 4², 2²⁰, 5⁻²)==> (25 1048576 0.04). Pełna lista Unicode, którą możesz nadużywać w ten sposób, znajduje się tutaj: docs.perl6.org/language/unicode_texas .
Ramillies,

8

Naucz się funkcji czytać dane wejściowe. Perl 6 ma wiele interesujących funkcji, które mogą z łatwością odczytać dane wejściowe z ARGV lub STDIN (jeśli nic nie zostało określone w ARGV), które mogą skrócić twój kod, jeśli zostanie użyty poprawnie. Jeśli wywołasz je jako metody uchwytu pliku, możesz zmusić je do działania na konkretnym uchwycie pliku (przydatne, jeśli na przykład czytasz z STDIN, ale musisz czytać argumenty na ARGV).

get

Ta funkcja otrzymuje pojedynczą linię i automatycznie ją łamie, więc nie musisz. Jest to przydatne, jeśli chcesz przeczytać tylko jedną linię.

lines

Ta funkcja pobiera wszystkie linie z pliku lub STDIN. To leniwa lista, więc jeśli z niej korzystasz for, będzie czytać tylko to, czego potrzebujesz. Na przykład.

say "<$_>"for lines

slurp

Spowoduje to odczytanie całego pliku lub STDIN i zwróci wynik jako pojedynczy ciąg.


Ten błąd został naprawiony - nie wiem kiedy, ale say "<$_>" for linesteraz działa
cat

5

Ostrzeżenie : zbliża się ściana tekstu. Z czasem zebrałem wiele małych sztuczek.

Napisz swoje rozwiązania jako anonimowe bloki

Zostało to już wspomniane, ale chciałbym to powtórzyć. W TIO możesz pisać my $f =w nagłówku, blok w odpowiednim kodzie i zaczynać stopkę od; . Wydaje się, że jest to zdecydowanie najkrótszy sposób na wykonanie zadania (ponieważ nie musisz przejmować się czytaniem jakichkolwiek danych wejściowych, są one podawane w argumentach).

Innym fajnym sposobem jest użycie przełącznika -nlub -p, ale nie znalazłem sposobu, aby działał w TIO.

Do przekazywania argumentów używaj składni dwukropka

Oznacza to, thing.method(foo,bar)że możesz zrobić thing.method:foo,bari zapisać 1 postać. Niestety nie można wywołać innej metody z wyniku z oczywistych powodów, dlatego warto używać tylko ostatniej metody w bloku.

Używaj $_jak najwięcej

Czasami lepiej jest z tego powodu wziąć jeden argument listy niż kilka oddzielnych argumentów. Podczas uzyskiwania dostępu $_możesz wywoływać na nim metody, zaczynając od kropki: np. .sortJest równa$_.sort .

Pamiętaj jednak, że każdy blok ma swój własny $_, więc parametry bloku zewnętrznego nie będą się rozchodzić do wewnętrznych. Jeśli chcesz uzyskać dostęp do parametrów funkcji głównej z wewnętrznego bloku, ...

Użyj ^zmiennych, jeśli nie możesz użyć$_

Włóż ^między sigil i nazwy zmiennej, na przykład: $^a. Działają one tylko wewnątrz bloku. Kompilator najpierw zlicza ich liczbę w bloku, sortuje je leksykograficznie, a następnie przypisuje pierwszy argument do pierwszego, drugi do drugiego i tak dalej. The^ z niego korzystać tylko przy pierwszym wystąpieniu zmiennej. Więc {$^a - $^b}bierze 2 skalary i odejmuje je. Liczy się tylko kolejność alfabetyczna, podobnie {-$^b + $^a}jak to samo.

Jeśli kiedykolwiek masz ochotę użyć spiczastej składni bloku (jak ->$a,$b {$a.map:{$_+$b}}), o wiele lepiej jest napisać fałszywą instrukcję na początku bloku, używając ^dla każdego argumentu, którego nie będziesz używać w bloku głównym (jak{$^b;$^a.map:{$_+$b}} ) (Uwaga) jest to lepszy sposób na golfa {$^a.map(*+$^b)}. Chciałem tylko pochwalić się tą koncepcją.)

Przeczytaj dokumenty operatora uważnie

Operatorzy są bardzo potężni i często są najkrótszym sposobem na załatwienie sprawy. Zwłaszcza meta-operatorzy (operatorów, które mają operatorów jako argument) [], [\], X, <</ >>i Zsą warte Twojej uwagi. Nie zapominaj, że meta-op może podjąć inną meta-op jako argument (jak XZ%%udało mi się użyć tutaj ). Możesz także użyć >>wywołania metody, które może być znacznie tańsze niż mapa ( @list>>.methodzamiast @list.map(*.method), ale uwaga, to nie to samo! ). I wreszcie, zanim użyjesz pliku binarnego << >>, pamiętaj o tymZ często robi to samo przy znacznie mniejszej liczbie znaków.

Jeśli nakładasz na siebie wiele metaoperacji, możesz określić pierwszeństwo za pomocą nawiasów kwadratowych [] . Dzięki temu zaoszczędzisz, gdy zgromadzisz tak wiele operatorów, że dezorientuje to kompilator. (To nie zdarza się często.)

W końcu, jeśli trzeba zmusić warte Bool, int lub STR, nie używać metod .Bool, .Inta .Str, ale operatorzy ?, +a ~. Lub jeszcze lepiej, po prostu wprowadź je do wyrażenia arytmetycznego, aby zmusić je do Int i tak dalej. Najkrótszym sposobem na uzyskanie długości listy jest +@list. Jeśli chcesz obliczyć 2 do potęgi długości listy, po prostu powiedz, 2**@lista zrobi to The Right Thing.

Użyj zmiennych stanu swobodnego $,@ i%

W każdym bloku każde wystąpienie $(lub @lub %) odnosi się do nowej błyszczącej zmiennej stanu skalarnego (lub tablicy lub skrótu) (zmiennej, której wartość utrzymuje się podczas wywołań bloku). Jeśli potrzebujesz zmiennej stanu, do której należy odwoływać się tylko raz w kodzie źródłowym, te trzy są twoimi wielkimi przyjaciółmi. (Najczęściej $.) Na przykład w wyzwaniu Odwrotne cykle matematyczne można go użyć do cyklicznego wybierania operatorów z tablicy, która została zindeksowana $++%6.

Skorzystaj z podform map, grepi in.

To znaczy: raczej rób map {my block},listniż list.map({my block}). Nawet jeśli uda ci się użyćlist.map:{my block} , te dwa podejścia mają tę samą liczbę bajtów. I często trzeba wywoływać listę w nawiasie podczas wywoływania metody, ale nie podczas wywoływania podrzędnego. Tak więc podejście podrzędne wychodzi zawsze lepiej lub przynajmniej tak samo jak metoda pierwsza.

Jedynym wyjątkiem jest sytuacja, w której znajduje się obiekt, który ma być mapped, grepped i tak dalej $_. Wtedy .map:{}oczywiście bije map {},$_.

Użyj skrzyżowań ( &i |) zamiast &&i ||.

Oczywiście są one o 1 bajt krótsze. Z drugiej strony należy je zwinąć, zmuszając je do kontekstu logicznego. Można to zawsze zrobić za pomocą ?. Tutaj powinieneś zdawać sobie sprawę z meta-op, !opktóra wymusza kontekst bool, używaop i neguje wynik.

Jeśli masz listę i chcesz zamienić ją w skrzyżowanie, nie używaj [&]i [|]. Zamiast tego użyj .anyi .all. Są też takie, .nonektórych nie da się tak łatwo naśladować w połączeniach.


1
Myślę &&i ||nadal są przydatne w przypadku zwarcia?
Tylko ASCII,

@ Tylko ASCII: Tak, z pewnością są.
Ramillies,

4

Zmniejsz miejsce używane na zmienne

Jest w tym kilka części.

Usuń białe znaki

Zmienne zadeklarowane za pomocą myzwykle można zadeklarować bez spacji między mynazwą zmiennej i. my @ajest równoważne z my@a.

Używaj zmiennych bez pieczęci

Możesz zadeklarować zmienne za pomocą ukośnika odwrotnego, aby usunąć znak przed nazwą zmiennej, na przykład:

my \a=1;

(niestety nie można usunąć spacji :()

Jest to przydatne, ponieważ później można nazywać je tylko samą nazwą zmiennej.

 a=5;
 a.say

Zasadniczo oszczędza to bajty, jeśli używasz zmiennej więcej niż raz w innym miejscu w kodzie. Minusem jest to, że zmienna musi zostać zainicjowana.

Użyj $!i$/

Te wstępnie zadeklarowane zmienne są zwykle używane odpowiednio dla wyjątków i dopasowań wyrażenia regularnego, ale nie trzeba ich definiować za pomocą my.

$!=1;
$/=5;

Szczególnie przydatne jest użycie $/jako tablicy i użycie skrótów, $po których następuje liczba, aby uzyskać dostęp do tego elementu $/tablicy;

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

2

Użyj ...zamiastfirst

Zazwyczaj, jeśli chcesz znaleźć pierwszy numer, który pasuje do jakiegoś warunku &f, możesz go przedstawić w następujący sposób:

first &f,1..*

Zamiast tego możesz użyć ...operatora:

+(1...&f)

Jeśli musisz zacząć 0, możesz -1później +.

Jeśli chcesz indeks pierwszego elementu na liście, @aktóra ma warunek &f, zwykle robisz:

first &f,@a,:k

Zamiast:

(@a...&f)-1

(lub odwrotnie, jeśli chcesz 0 indeksowanych). W ten sam sposób możesz uzyskać wszystkie elementy aż do pierwszego, który spełni warunek.

Wadą tego jest to, że lista musi spełnić warunek w pewnym momencie, w przeciwnym razie ...operator spróbuje ekstrapolować poza koniec listy i najprawdopodobniej wyśle ​​błąd. Nie można również użyć dowolnego kodu po lewej stronie, ponieważ byłby interpretowany jako część sekwencji.

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.