TMTOWTDI
To najważniejsza wskazówka golfowa Perla, którą musisz wiedzieć. Ilekroć patrzysz na zbyt długą sekwencję znaków, którą absolutnie musisz mieć, aby wykonać swoje zadanie, zadaj sobie pytanie, czy nie ma innego sposobu na uzyskanie tego samego efektu za pomocą innej funkcji. Zwykle jest. Oto tylko garść:
~~
wymusza kontekst skalarny i jest o 4 znaki krótszy niż scalar
.
y///c
jest o jeden char krótszy niż length
przy uzyskiwaniu długości $_
.
Potrzebujesz iteracji po znakach w $_
? Wymień split//
się /./gs
. (Lub użyć /./g
jeśli chcesz pominąć nowej linii.) To działa z innymi zmiennymi zamienić split//,$x
z $x=~/./gs
.
Każde wbudowane Perl coś zwraca. print
zwraca 1, na przykład, aby wskazać udane We / Wy. Jeśli chcesz na przykład zainicjować $_
wartość prawdziwą, $_=print$foo
pozwala zabić dwa ptaki jednym kamieniem.
Prawie każde zdanie w Perlu może być zapisane jako wyrażenie, co pozwala na użycie go w szerszym zakresie kontekstów. Wiele instrukcji może być wieloma wyrażeniami połączonymi łańcuchami z przecinkami. Testy można wykonywać z operatorami zwarciowymi ?:
&&
||
, a także z and
i or
, które robią to samo, ale z pierwszeństwem niższym niż wszystkie inne operatory (w tym przypisanie). Pętle można wykonywać za pomocą map
lub grep
. Nawet jak słowa kluczowe next
, last
i return
może być stosowany w kontekście wypowiedzi, choć nie wracają! Pamiętając o tego rodzaju transformacjach, możesz zastąpić bloki kodu wyrażeniami, które można upchnąć w szerszej gamie kontekstów.
$_=print""
jest krótszy niż$_=print$foo
.$foo
. W przeciwnym razie$_=1
jest znacznie krótszy niż$_=print""
i ma ten sam efekt.$x
? W przeciwnym razie możesz po prostu zrobić/./gs
i/./g
.Nadużywaj specjalnych zmiennych Perla!
Jak zauważono w poprzedniej odpowiedzi
$/
i$"
są one domyślnie inicjowane odpowiednio na"\n"
i" "
.$,
i$\
oba są ustawioneundef
domyślnie i są o 3 znaki krótsze.Ustawienie
$\
wartości spowoduje dołączenie jej do każdegoprint
. Na przykład:perl -ple '$\="=".hex.$/'
jest przydatnym konwerterem szesnastkowym na dziesiętnym.Jeśli nie czytasz plików z wiersza poleceń, możesz użyć
-i
przełącznika wiersza polecenia jako dodatkowego kanału do wprowadzania ciągu. Jego wartość zostanie zapisana w$^I
.$=
zmusza wszystko, co jest przypisane, do liczby całkowitej. Spróbuj uruchomićperl -ple '$_=$==$_'
i podać różne przeróbki. Podobnie,$-
wymusza, aby jego wartość była nieujemną liczbą całkowitą (tj. Myślnik prowadzący jest traktowany jako znak nienumeryczny).Można użyć
$.
jako flagi logicznej, która jest automatycznie resetowana do wartości true (niezerowej) przy każdej iteracjiwhile(<>)
pętli.źródło
-n
i niedopasowane nawiasy klamroweDobrze wiadomo, że przełącznika wiersza poleceń
-n
można użyć do wykonania skryptu raz dla każdej linii.perl --help
mówi:Nie mówi wprost, że Perl nie zakłada pętli wokół programu; to dosłownie owija
while (<>) { ... }
się wokół niego.W ten sposób następujące polecenia są sobie równe:
-p
i niedopasowane nawiasy klamrowePodobnie jak powyżej,
-p
przełącznik otaczawhile (<>) { ... ; print }
program.Używając niedopasowanych nawiasów klamrowych,
perl -p 'code}{morecode'
wydrukuje się tylko raz po wykonaniucode
dla wszystkich wierszy wprowadzania, a następniemorecode
.Ponieważ
$_
podczasmorecode;print
wykonywania jest niezdefiniowany , separator rekordów wyjściowych$\
może zostać wykorzystany do wydrukowania rzeczywistych wyników.Na przykład
wczytuje z STDIN jedną liczbę w wierszu i wypisuje ich sumę.
źródło
#!perl -n
w pierwszej linii, prawda?-p
i$\
) w jednej z odpowiedzi Perla @primo . Samo czytanie jego odpowiedzi jest dobrą wskazówką dla Perla.}for(...){
się między nawiasami jest często bardzo przydatny, jak również, np codegolf.stackexchange.com/a/25632Służy
$_
do eliminowania odniesień skalarnych. Jest to zmienna specjalna używana domyślnie przez większość funkcji, a pominięcie parametrów jest skrótem do odwołania się do tej zmiennej.Zmieniając
$n
na$_
, możesz zmienić$n=<>;chop$n;print$n
na$_=<>;chop;print
Tutaj
print
funkcja$_
domyślnie drukuje zawartość , achop
także działa na$_
.źródło
$_=<>;
wymagany, nie<>;
czyta wiersza$_
automatycznie?$_=<>;print
i<>;print
. Pierwszy powtarza mi to, co piszę, a drugi nie.print while(<>)
. Nie jestem pewien, czy jest to szczególny przypadek czy istnieje jakaś spójna logika za nim, ani<>
nic w częściperlop
aniwhile
częściąperlsyn
wydają wspomnieć to zachowanie.while(<>)
to szczególny przypadek, udokumentowany w perlsyn, operatory I / O: „Tylko wtedy, gdy symbol wejściowy jest jedyną rzeczą w warunku instrukcji„ while ”(nawet jeśli jest zamaskowany jako„ for (;;) ” pętla), wartość jest automatycznie przypisywana do zmiennej globalnej $ _, niszcząc wszystko, co było wcześniej. ”Używaj specjalnych zmiennych Perla, gdy tylko możesz, np .:
$"
zamiast" "
$/
zamiast"\n"
Mają dodatkową zaletę, że są gwarantowanym jednoznakowym długim identyfikatorem, z pomocą leksykonu. Umożliwia to przyklejenie go do następującego po nim słowa kluczowego, jak w:
print$.for@_
Lista wszystkich zmiennych specjalnych jest dostępna tutaj: Zmienne specjalne
źródło
Nie używać
qw
. To marnotrawstwo dwóch postaci, które można by lepiej wykorzystać. Na przykład nie pisz tego.Zamiast tego używaj prostych słów.
Lub jeśli nie możesz używać słów bez słów, użyj
glob
składni.glob
składnia może być również wykorzystana do uzyskania interesujących efektów.źródło
Użyj modyfikatorów instrukcji zamiast instrukcji złożonych.
Instrukcje złożone zwykle wymagają nawiasów dla argumentu i nawiasów klamrowych dla bloku, podczas gdy modyfikatory instrukcji nie potrzebują tego.
Porównać:
$a++,$b++while$n--
vswhile($n--){$a++;$b++}
chop$,if$c
vsif($c){chop$,}
Zauważ, że ostatni przykład wiąże się z
$c&&chop$,
, ale zaczyna naprawdę świecić w przypadku większości operacji na wielu instrukcjach. Zasadniczo wszystko, co traci pierwszeństwo operatora&&
.źródło
Nie robić
use strict
. (nie cytuj mnie, kontekst PCG.SE ma znaczenie) I, co ważniejsze, nie koduj tak, jakby był ściśle określony. Podejrzani:my
usuwaj zmiennych, jeśli możesz tego uniknąć. Jedyne zmienne, które naprawdę potrzebują,my
to te, które mają zasięg leksykalny. To prawie żaden z nich podczas gry w golfa, gdzie nie potrzebujesz ochrony lunety i masz tendencję do pełnej kontroli rekurencji.źródło
print hello
nie zadziała. W rzeczywistości oznacza toprint hello $_
(drukuj$_
do uchwytu plikuhello
).print
, a teraz nie mogę znaleźć ładnego i krótkiego przykładu)Jestem pewien, że niektóre z nich mają formalne nazwy i po prostu ich nie znam.
print $n++ while ($n < 10)
$var = join('',<>)
print ('X'*10) . "\n";
jest dłuższe niżprint ('X'*10) . $/;
say
Funkcja Perla jest krótsza niżprint
, ale będziesz musiał uruchomić kod-E
zamiast-e
a..z
lub nawetaa..zz
. W razie potrzeby użyj ciągujoin
.$z = 'z'; print ++$z;
wyświetli sięaa
To wszystko, co mogę teraz wymyślić. Mogę dodać trochę później.
źródło
print ('X'*10) . $/;
ma robić? Dla mnie to drukuje0
i nie ma nowej linii. Po pierwsze, nawiasy stają się argumentem wywołania w stylu funkcji doprint
, który wiąże się mocniej niż.
. A miałeś na myślix
zamiast*
czy coś?while
,join'',<>;
działa również bez nich.Używaj znaków innych niż słowa jako nazwy zmiennych
Korzystanie
$%
zamiast$a
może zezwolić, aby umieścić nazwę zmiennej tuż obokif
,for
albowhile
skonstruować na przykład:@r=(1,2,3,4,5);$%=4;
print$_*$%for@r
Można użyć wielu, ale sprawdź dokumentację i odpowiedź @ BreadBox, które mają magiczne efekty!
Użyj mapy, gdy nie możesz użyć modyfikatorów instrukcji
Jeśli nie możesz użyć modyfikatorów instrukcji zgodnie z odpowiedzią @ JB , mapa może zapisać bajt:
for(@c){}
vs.map{}@c;
i jest przydatny, jeśli chcesz wykonywać zagnieżdżone iteracje, ponieważ możesz umieścić w nim
for
pętle Postfiksamap
.Użyj wszystkich magicznych zmiennych wyrażeń regularnych
Perl ma magiczne zmienne dla „tekstu przed dopasowaniem” i „tekstu po dopasowaniu”, więc możliwe jest podzielenie na grupy dwuosobowe o potencjalnie mniejszej liczbie znaków:
Może to również działać dobrze jako zamiennik dla
substr
:Jeśli potrzebujesz zawartości meczu,
$&
możesz użyć np .:Zamień napisy na długie nazwy na krótsze
Jeśli dzwonisz
print
w kodzie powiedz co najmniej cztery razy (to oczywiście różni się w zależności od długości procedury, którą wywołujesz), zastąp go krótszą nazwą podrzędną:vs.
Wymień warunkowe inkrementatory / dekrementory
Jeśli masz kod taki jak:
możesz użyć:
zamiast tego, aby zapisać niektóre bajty.
Konwertuj na liczbę całkowitą
Jeśli nie przypisujesz zmiennej, więc nie możesz użyć końcówki chleba , możesz użyć wyrażenia
0|
:Warto jednak zauważyć, że nie trzeba używać liczby całkowitej, aby uzyskać dostęp do indeksu tablicy:
źródło
redo
dodaje zachowanie pętli do bloku bezfor
lubwhile
.{redo}
jest nieskończoną pętlą.źródło
Nie nawiasuj wywołań funkcji.
Perl pozwala wywoływać znaną (podstawową lub zadeklarowaną) funkcję przy użyciu
NAME LIST
składni. Pozwala to upuścić&
sigil (jeśli nadal go używasz), a także nawiasy.Na przykład:
$v=join'',<>
Pełna dokumentacja
źródło
Spróbuj użyć wartości wyrażenia przypisania, na przykład:
Działa
$n
to, ponieważ w Perlu są 2 znaki. Można zmienić$n
, aby()
bez żadnych kosztów i zapisywać 1 średnik przesuwając zadanie w nawiasach.źródło
Możesz uruchomić wiele różnych instrukcji w zagnieżdżonej logice trójskładnikowej.
Załóżmy, że masz duży
if
-elsif
oświadczenie. Może to być dowolna logika i dowolna liczba instrukcji.Możesz użyć
(cmd1, cmd2, cmd3)
wewnątrz operatora trójskładnikowego, aby uruchomić wszystkie polecenia.Oto fałszywy przykład:
źródło
Użyj
select(undef,undef,undef,$timeout)
zamiastTime::HiRes
(Źródło: https://stackoverflow.com/a/896928/4739548 )
Wiele wyzwań wymaga spania z większą precyzją niż liczby całkowite.
select()
Argument limitu czasu może to zrobić.jest znacznie bardziej wydajny niż:
Pierwszy z nich ma tylko 20 bajtów, podczas gdy drugi zajmuje 39. Jednak pierwszy wymaga, abyś nie używał
$u
i nigdy go nie zdefiniował.Jeśli zamierzasz go używać, importowanie się
Time::HiRes
opłaca, ale jeśli potrzebujesz go tylko raz, użycieselect($u,$u,$u,0.1)
oszczędza 19 bajtów, co jest zdecydowanie poprawą w większości przypadków.źródło
Skróć swoje drukowane wyciągi
O ile wyzwanie nie stanowi inaczej, nie potrzebujesz końcowych znaków nowej linii.
Nasze „wyzwanie” mówi „wypisz losową liczbę od 0 do 9 do STDOUT”. Możemy pobrać ten kod (28 bajtów):
I skróć go do tego (25 bajtów):
po prostu drukując zmienną. Ten ostatni dotyczy tylko tego wyzwania (19 bajtów):
ale działa to tylko wtedy, gdy nie musisz nic robić ze zmienną między przypisaniem a drukowaniem.
źródło
Używaj globów jak literałów łańcuchowych
Czasami (często podczas rozwiązywania problemów z quine lub ograniczonymi źródłami ) bardzo zyskujesz na możliwości zagnieżdżania literałów łańcuchowych. Zwykle zrobiłbyś to za pomocą
q(…)
. Jednak w zależności od potrzebnych znaków w ciągu możesz zapisać bajt i użyć<…>
operatora glob. (Zauważ, że to, co znajduje się w nawiasach kątowych, nie może wyglądać jak uchwyt pliku i nie może wyglądać, jakby miało być rozwinięte do listy nazw plików, co oznacza, że całkiem sporo znaków nie będzie działać poprawnie.)źródło
Użyj wyrażenia regularnego.
Przyzwoitą ilustracją tego jest następujący kod kształtujący sygnał wejściowy w fali sinusoidalnej:
Jak widać, jest to dość kompaktowy sposób iteracji znaków w standardowym wprowadzaniu. Możesz użyć innego wyrażenia regularnego, aby zmienić sposób dopasowania rzeczy.
źródło