Jakie ogólne wskazówki możesz dać w golfa w Ruby?
Szukam pomysłów, które można zastosować do ogólnych problemów związanych z golfem, które są specyficzne dla Ruby. (Na przykład „Usuń komentarze” nie byłoby odpowiedzią).
Proszę zamieścić jedną wskazówkę na odpowiedź.
Odpowiedzi:
?d
się?~
na 1,8.$><<"string"
jest on krótszy niżprint"string"
.$<.map{|l|...}
jest krótszy niżwhile l=gets;...;end
. Możesz także użyć,$<.read
aby przeczytać wszystko na raz.$<
igets
czyta z pliku zamiast standardowego wejścia, jeśli nazwa pliku jest w plikuARGV
. Więc golfiest sposobem reimplementcat
będzie:$><<$<.read
.źródło
cat
jest pozostawienie pliku ruby całkowicie pustego (0 bajtów) i naleganie, aby uruchomić go z linii poleceń z-p
flagą.puts *$<
☺
lub♫
, lub jeśli jesteś wystarczająco szalony:?﷽.ord=65021
Użyj operatora ikony, aby uzyskać ogon i głowę tablicy:
Działa to również w drugą stronę:
Użyj
*
metody z łańcuchem na tablicy, aby połączyć elementy:źródło
abort
aby zakończyć program i wydrukować ciąg do STDERR - krótszy niżputs
po nimexit
gets
, możesz użyć jej~/$/
do znalezienia jej długości (nie liczy się końcowy znak nowej linii, jeśli istnieje)[]
do sprawdzania, czy łańcuch zawiera inny:'foo'['f'] #=> 'f'
tr
zamiastgsub
zastępowania znakowego:'01011'.tr('01','AB') #=> 'ABABB'
chop
zamiastchomp
źródło
abort
i~/$/
~/$/
gets
, jego wynik jest zapisywany w$_
zmiennej./regex/ ~= string
zwraca indeks pierwszego dopasowania. Wywołanie~
wyrażenia regularnego jest równoważne z/regex/ ~= $_
. Byłoby więc coś w stylus=gets;l= ~/$/
Zakończ swoje
end
.Spróbuj usunąć
end
ze swojego kodu.Nie używaj
def...end
do definiowania funkcji. Stwórz lambda za pomocą nowego operatora -> w Ruby 1.9. (Operator -> to „stabby lambda” lub „dash rocket” .) Oszczędza to 5 znaków na funkcję.Wywołania metod to
c n
lubc(n)
. Połączenia z Lambda sąc[n]
. Zmiana każdejc n
z nichc[n]
kosztuje 1 znak, więc jeśli możesz użyćc n
więcej niż 5 razy, zachowaj metodę.Wszystkie metody pobierające
do...end
bloki mogą{...}
zamiast tego pobierać bloki. Oszczędza to od 3 do 5 znaków. Jeśli priorytet{...}
jest zbyt wysoki, użyj nawiasów, aby to naprawić.Wymienić
if...else...end
z operatorem trójskładnikowego?:
. Jeśli gałąź ma dwie lub więcej instrukcji, zawiń je w nawiasy.Prawdopodobnie nie masz pętli
while
lubuntil
, ale jeśli tak, to napisz je w postaci modyfikatora.źródło
puts'statement 3'
konieczne?Dodatek do w0lf
W połączeniu z powyższym -> możesz go jeszcze skrócić,
-[p]
aby zapisać kolejne 2 znaki.źródło
W miarę możliwości używaj krótkich predefiniowanych zmiennych, np.
$*
ZamiastARGV
. Jest to dobra lista z nich tutaj , wraz z wieloma innymi przydatnymi informacjami.źródło
Kiedy używasz interpolacji łańcuchów ((tak jak post posta Martina Büttnera )), nie potrzebujesz nawiasów klamrowych, jeśli twój obiekt ma przed sobą sigil (
$
,@
). Przydatne dla zmiennych magicznych, takich jak$_
,$&
,$1
itp:Dlatego też, jeśli chcesz wydrukować zmienną częściej niż użyjesz jej w inny sposób, możesz zapisać niektóre bajty.
źródło
Jeśli chcesz sprawdzić, czy dany element
e
znajduje się w zasięgur
, możesz użyćzamiast dłuższego:
lub
lub
źródło
r===e
jeszcze krótszy?===
Zaimplementowano wszystko, co może być użyte w instrukcji switch .$_
jest ostatnim czytanym wierszem.print
- jeżeli nie podano argumentu treść wydruku$_
~/regexp/
- skrót od$_=~/regexp/
W Ruby 1.8 masz cztery metody,
Kernel
które działają na$_
:chop
chomp
sub
gsub
W Ruby 1.9 te cztery metody istnieją tylko wtedy, gdy skrypt używa
-n
lub-p
.Jeśli chcesz często drukować jakieś zmienne, użyj
trace_var(:var_name){|a|p a}
źródło
-p
lub-n
. Odniesienie.trace_var
działa tylko z globalnymi zmiennymi $Użyj interpolacji ciągów!
Aby wymienić
to_s
. Jeśli potrzebujesz nawiasów wokół tego, co chcesz przekształcić w ciąg,to_s
jest on o dwa bajty dłuższy niż interpolacja ciągu:Aby zastąpić konkatenację. Jeśli połączysz coś otoczonego dwoma innymi łańcuchami, interpolacja może zaoszczędzić jeden bajt:
Działa również, jeśli środkowa rzecz jest sama konkatenowana, jeśli po prostu przenosisz konkatenację wewnątrz interpolacji (zamiast używania wielu interpolacji):
źródło
Unikaj
length
wif a.length<n
length
ma 6 bajtów, co jest nieco kosztowne w golfie kodu. w wielu sytuacjach możesz zamiast tego sprawdzić, czy tablica ma coś w danym punkcie. jeśli przejdziesz obok ostatniego indeksu, otrzymasznil
wartość falsey.Możesz więc zmienić:
if a.length<5
sięif !a[4]
do -5 bajtówlub
if a.length>5
doif a[5]
-6 bajtówlub
if a.length<n
doif !a[n-1]
-3 bajtówlub
if a.length>n
doif a[n]
-6 bajtówUwaga : działa tylko z tablicą wszystkich prawdziwych wartości. posiadanie
nil
lubfalse
wewnątrz tablicy może powodować problemy.źródło
size
… Ale to zdecydowanie lepsze. BTW, też działaString
.Nie używaj słów kluczowych
true
ifalse
.Posługiwać się:
!p
zatrue
(dzięki, histocrat!)!0
dlafalse
. Jeśli wszystko, czego potrzebujesz, to wartość fałszowania, możesz po prostu użyćp
(która zwracanil
).aby zaoszczędzić trochę znaków.
źródło
true
(tj. Jeśli prawda jest wystarczająca, jak w przypadku warunku if), nawet nie potrzebujesz!!
.p
(która ocenianil
) jest krótszą wartością falsey. Co oznacza, że najkrótszą drogątrue
jest!p
.Twórz tablice za pomocą,
a=i,*a
aby uzyskać je w odwrotnej kolejności. Nie musisz nawet inicjowaća
, a jeśli to zrobisz , nie musi to być tablica .źródło
Jeśli kiedykolwiek potrzeba, aby uzyskać numer z
ARGV
,get
lub coś podobnego zrobić coś, co wiele razy, zamiast dzwonićto_i
na nim, można po prostu użyć?1.upto x{do something x times}
gdzie x jest ciągiem.Używanie
?1.upto(a){}
zamiast zamiastx.to_i.times{}
pozwoli Ci zaoszczędzić 2 znaki.Możesz także ponownie napisać rzeczy takie jak
p 1 while 1
lubp 1 if 1
jakop 1while 1
lubp 1if 1
Ten przykład nie jest zbyt przydatny, ale można go wykorzystać do innych celów.
Ponadto, jeśli musisz przypisać pierwszy element tablicy do zmiennej,
a,=c
zapisze dwa znaki w przeciwieństwie doa=c[0]
źródło
Nowe funkcje w Ruby 2.3 i 2.4
Dobrze jest być na bieżąco z nowymi funkcjami językowymi, które pomogą w grze w golfa. W najnowszych Rubinach jest kilka świetnych.
Ruby 2.3
Operator bezpiecznej nawigacji:
&.
Gdy wywołujesz metodę, która może zwrócić,
nil
ale chcesz połączyć dodatkowe wywołania metody, jeśli tak nie jest, marnujesz bajty na obsługęnil
sprawy:„Operator bezpiecznej nawigacji” zatrzymuje łańcuch wywołań metod, jeśli jeden zwraca
nil
i zwracanil
całe wyrażenie:Array#dig
IHash#dig
Głęboki dostęp do zagnieżdżonych elementów o ładnej krótkiej nazwie:
Zwraca,
nil
jeśli trafi w ślepy zaułek:Enumerable#grep_v
Odwrotność —
Enumerable#grep
zwraca wszystkie elementy, które nie pasują do podanego argumentu (w porównaniu z===
). Na przykładgrep
, jeśli podano blok, jego wynik jest zwracany.Hash#to_proc
Zwraca Proc, który zwraca wartość dla danego klucza, co może być bardzo przydatne:
Ruby 2.4
Ruby 2.4 nie jest jeszcze dostępny, ale będzie dostępny wkrótce i będzie miał kilka wspaniałych funkcji. (Po wydaniu zaktualizuję ten post, dodając linki do dokumentów.) O większości z nich dowiedziałem się w tym świetnym wpisie na blogu .
Enumerable#sum
Nie więcej
arr.reduce(:+)
. Możesz teraz po prostu zrobićarr.sum
. Pobiera opcjonalny argument wartości początkowej, który domyślnie wynosi 0 dla elementów numerycznych ([].sum == 0
). W przypadku innych typów musisz podać wartość początkową. Akceptuje również blok, który zostanie zastosowany do każdego elementu przed dodaniem:Integer#digits
Zwraca tablicę cyfr liczby w kolejności od najmniejszego do największego znaczenia:
W porównaniu, powiedzmy,
123.to_s.chars.map(&:to_i).reverse
jest to całkiem miłe.Jako bonus wymaga opcjonalnego argumentu Radix:
Comparable#clamp
Czy to, co jest napisane na puszce:
Ponieważ jest porównywalny, możesz go używać z dowolną klasą zawierającą porównywalne, np .:
String#unpack1
2-bajtowe oszczędności w porównaniu z
.unpack(...)[0]
:Argument dokładność
Numeric#ceil
,floor
oraztruncate
Wielokrotne przypisanie warunków warunkowych
To powoduje błąd we wcześniejszych wersjach Ruby, ale jest dozwolone w 2.4.
źródło
Math::E.ceil(1)
doMath::E.ceil 1
, a także dlafloor
itruncate
.Enumerable#sum
,.flatten.sum
jest krótszy niż 2 bajty.sum{|a,b|a+b}
(-Math::E).truncate(1)
jest równoznaczne z-Math::E.truncate(1)
których jest 1 bajt krótszy&.
może być używany z takim indeksowaniem jak tena&.[]i
(1 bajt krótszy niża&.at i
). Chociaż, jeśli wymagane są nawiasya||a[i]
a&.[](i)
a&.at(i)
Notacja naukowa może być często używana do golenia znaku lub dwóch znaków:
źródło
1e2
jest lepiej niż100.0
wtedy, gdy potrzebny jest procent.1.0*
jest o 1 char krótszy niż.to_f
Użyj metod operatora zamiast nawiasów
Powiedzmy, że chcesz wyrazić
a*(b+c)
. Z powodu pierwszeństwaa*b+c
nie zadziała (oczywiście). Na ratunek przychodzi fajny sposób, w jaki Ruby stosuje operatorów jako metody! Możesz użyć,a.*b+c
aby ustawić priorytet na*
niższy niż+
.Może to również działać z operatorami
!
i~
(rzeczy takie jak unary+
lub unary-
nie działają, ponieważ ich metody są-@
i+@
, zapisywanie,()
ale dodawanie.@
)źródło
Użyj
||
zamiastor
i&&
zamiastand
.Oprócz jednej postaci
and
możesz zaoszczędzić miejsca (i być może nawias klamrowy) wokół operatora.Jeśli zapętlisz tablicę, której zwykle używasz
each
. Alemap
zapętla się również nad tablicą i jest ona o jeden znak krótsza.źródło
Właśnie podjąłem wyzwanie golfowego kodu TDD, tzn. Napisałem najkrótszy kod, żeby specyfikacja się spełniła. Specyfikacje były podobne
Ze względu na kod-golfa nie trzeba tworzyć modułu ani klasy.
Zamiast
można zrobić
Zapisuje 13 znaków!
źródło
PigLatin
, ale także@pig_latin
,$pig_latin
i'pig'['latin']
.translate
że został zdefiniowany w dniunil
.Jądro # p jest zabawną metodą.
Użyj
p var
zamiastputs var
. Działa to doskonale z liczbami całkowitymi i liczbami zmiennoprzecinkowymi, ale nie ze wszystkimi typami. Drukuje cudzysłowy wokół ciągów, co prawdopodobnie nie jest tym, czego chcesz.Używany z jednym argumentem
p
zwraca argument po wydrukowaniu.Używany z wieloma argumentami
p
zwraca argumenty w tablicy.Użyj
p
(bez argumentów) zamiastnil
.źródło
p 'some string'
grafiki"some string"
i nie tylkosome string
to, co jest często krytykowane przez innych.p s
jest taki samputs s.inspect
, ale powracas
Nie używaj #each. Możesz dobrze zapętlić wszystkie elementy za pomocą #map. Więc zamiast
możesz zrobić to samo w mniejszej liczbie bajtów.
Oczywiście w tym przypadku
puts $*
byłby jeszcze krótszy.Istnieją literały dla liczb wymiernych i zespolonych:
Możesz użyć większości bajtów w łańcuchach.
"\x01"
(6 bajtów) można skrócić do""
(3 bajtów). Jeśli potrzebujesz tylko tego jednego bajtu, można go jeszcze bardziej skrócić do?
(2 bajtów).Tym samym możesz uzyskać krótsze wiersze w ten sposób:
Możesz użyć
?\n
i?\t
, który jest o jeden bajt krótszy niż"\n"
i"\t"
. Do zaciemnienia jest też przestrzeń.Używaj stałych zamiast przekazywania argumentów, nawet jeśli musisz je zmienić. Tłumacz daje ostrzeżenia stderrowi , ale kogo to obchodzi. Jeśli musisz zdefiniować więcej powiązanych ze sobą zmiennych, możesz połączyć je w następujący sposób:
To jest krótszy niż
C=9;B=16;A=17
lubC=0;B=C+7;A=C+B
.Jeśli potrzebujesz nieskończonej pętli, użyj
loop{...}
. Pętle o nieznanej długości mogą być krótsze z innymi pętlami:Więcej sztuczek gsub / regexp. Użyj specjalnych
'\1'
znaków zmiany znaczenia zamiast bloku:Oraz specjalne zmienne
$1
itp., Jeśli chcesz wykonać operacje. Pamiętaj, że są zdefiniowane nie tylko wewnątrz bloku:Pozbądź się spacji, znaków nowej linii i nawiasów. W rubinie możesz trochę pominąć. W razie wątpliwości zawsze staraj się, czy działa bez, i pamiętaj, że może to spowodować uszkodzenie podświetlenia składni edytora ...
źródło
?\n
Jest także przyjemny, ale nie krótszy niż wstawianie znaku nowej linii do cudzysłowów. (to samo dla karty)puts$*
jest jeszcze krótszy.x+=1;$*<<A
Jeszcze inny sposób korzystania z operatora splat: jeśli chcesz przypisać pojedynczy literał tablicowy, a
*
po lewej stronie jest krótszy niż nawiasy po prawej stronie:Przy wielu wartościach nie potrzebujesz nawet operatora splat (dzięki histocratowi za poprawienie mnie na tym):
źródło
Gdy wyzwanie wymaga wypisania wielu wierszy, nie musisz zapętlać wyników, aby wydrukować każdy wiersz np. Tablicy.
puts
Metoda spłaszczyć tablicy i wydrukowania każdego elementu w osobnej linii.Łącząc z sobą operatora splat
#p
, możesz uczynić go jeszcze krótszym:Operator splat (technicznie
*@
wydaje mi się, że metoda) również rzutuje twoje tablice niepoliczalne na tablice:vs
źródło
*@
nie jest metodą, ikona jest cukrem syntaktycznymZapisz niektóre bajty podczas usuwania powtarzających się elementów tablicy
Jeśli będziesz używał pustej tablicy
[]
w zmiennej, możesz zapisać jeszcze więcej bajtów:źródło
a&a
jest o 1 bajt krótszyUżyj Goruby zamiast Ruby, co jest jak skrócona wersja Ruby. Możesz zainstalować go za pomocą rvm przez
Goruby pozwala pisać większość kodu tak, jak piszesz w języku Ruby, ale ma wbudowane dodatkowe skróty. Aby znaleźć najkrótszy dostępny skrót dla czegoś, możesz użyć metody pomocnika
shortest_abbreviation
, na przykład:Również bardzo przydatny jest aliasem
say
dlaputs
których sama może być skrócona zs
. Więc zamiastmożesz teraz pisać
drukować alfabet drukowanymi literami (co nie jest dobrym przykładem). Ten post na blogu wyjaśnia więcej rzeczy i niektóre z wewnętrznych działań, jeśli jesteś zainteresowany dalszą lekturą.
PS: nie przegap
h
metody ;-)źródło
Aby dołączyć do tablicy, zamiast tego
Zrób to
co oszczędza 2 bajty. Aby dołączyć za pomocą separatora, użyj
źródło
Indeksowanie numerów!
Właśnie to odkryłem wczoraj.
n[i]
zwracan
bit nai
-tej pozycji. Przykład:źródło
n[0..3]
Możesz być w stanie zapisać 2 znaki i użyć
zamiast
Załóżmy na przykład, że mamy zakres, który chcemy jako tablicę:
Po prostu zrób to w ten sposób:
A teraz masz swój zasięg jako tablicę.
źródło
[*1..2000]
działa?<< sztuczka
można skrócić do:
dla -4 bajtów.
źródło
String
sArray#assoc
/rassoc
Jeśli masz tablicę tablic i chcesz znaleźć pod-tablicę, która zaczyna się od określonej wartości, nie używaj
Enumerable#find
, użyjArray#assoc
:Jest to również dobry zamiennik
Enumerable#any?
w niektórych sytuacjach.Array#rassoc
robi to samo, ale sprawdza ostatni element pod-tablic:źródło
a.any?
linii narassoc
przykład, co ma|x,|
zrobić? Czym się różni|x|
?x=[1,2]
kontrax,=[1,2]
. Korzystając z mojego przykładu powyżej, z|x|
, w pierwszej iteracjix
będzie[0,"foo"]
. Dzięki|x,y|
,x
będzie0
iy
będzie"foo"
. Podobnie, z|x,|
,x
będzie0
. Innymi słowy, napisano: „włóż pierwszy elementx
i wyrzuć resztę.|,y|
Jest składnią błędu, ergo|_,y|
. Ale właśnie zdałem sobie sprawę, że to|*,y|
działa, co jest czystsze niż używanie zmiennej o nazwie_
(ale nie krótszej).