Wskazówki dotyczące gry w golfa w Ruby

62

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ź.

grokus
źródło
Ktoś musi napisać język o nazwie Rub, który używa jednego znaku Unicode dla każdego tokena Ruby, trochę jak Jelly i Pyth :)
Mark Thomas

Odpowiedzi:

46
  • Liczby 100 do 126 można zapisać ?dsię ?~na 1,8.
  • Podobnie, jeśli potrzebujesz ciągu o jednym znaku w 1.9? X jest krótszy niż „x”.
  • Jeśli chcesz wydrukować ciąg bez dodawania nowego wiersza, $><<"string"jest on krótszy niż print"string".
  • Jeśli chcesz przeczytać wiele wierszy wprowadzania, $<.map{|l|...}jest krótszy niż while l=gets;...;end. Możesz także użyć, $<.readaby przeczytać wszystko na raz.
  • Jeśli powinieneś czytać z pliku, $<i getsczyta z pliku zamiast standardowego wejścia, jeśli nazwa pliku jest w pliku ARGV. Więc golfiest sposobem reimplement catbędzie: $><<$<.read.
sepp2k
źródło
1
? x generuje kod ascii ogólnie, dzięki czemu można realistycznie uzyskać wszystkie drukowalne cyfry za pomocą dwóch znaków. 1.9 jest inny, „a” .ord zwraca liczbę ascii, ale jest o cztery bajty dłuższy niż wersja dziesiętna.
Hiato,
8
Jeszcze bardziej golfistycznym sposobem na implementację catjest pozostawienie pliku ruby ​​całkowicie pustego (0 bajtów) i naleganie, aby uruchomić go z linii poleceń z -pflagą.
daniero
1
lub, z własnej odpowiedzi @ daniero ,puts *$<
Nie że Charles
1
Więc w 1.8 wszystko, co muszę zrobić, to iść? ~ I zwróci 126?
Po prostu piękna sztuka
5
Możesz wyjść poza 126, używając myśli takich jak lub , lub jeśli jesteś wystarczająco szalony:?﷽.ord=65021
Po prostu piękna sztuka
32

Użyj operatora ikony, aby uzyskać ogon i głowę tablicy:

head, *tail = [1,2,3]
head => 1
tail => [2,3]

Działa to również w drugą stronę:

*head, tail = [1,2,3]
head => [1,2]
tail => 3

Użyj *metody z łańcuchem na tablicy, aby połączyć elementy:

[1,2,3]*?,
=> "1,2,3"
Arnaud Le Blanc
źródło
27
  • Użyj, abortaby zakończyć program i wydrukować ciąg do STDERR - krótszy niż putspo nimexit
  • Jeśli czytasz linię za pomocą gets, możesz użyć jej ~/$/do znalezienia jej długości (nie liczy się końcowy znak nowej linii, jeśli istnieje)
  • Służy []do sprawdzania, czy łańcuch zawiera inny:'foo'['f'] #=> 'f'
  • Użyj trzamiast gsubzastępowania znakowego:'01011'.tr('01','AB') #=> 'ABABB'
  • Jeśli chcesz usunąć końcowe znaki nowej linii, użyj chopzamiastchomp
Lowjacker
źródło
2
+1 za aborti~/$/
J -_- L
Wyjaśnij, jak używać~/$/
Mathieu CAROFF,
@MathieuCAROFF za każdym razem, gdy dzwonisz gets, jego wynik jest zapisywany w $_zmiennej. /regex/ ~= stringzwraca indeks pierwszego dopasowania. Wywołanie ~wyrażenia regularnego jest równoważne z /regex/ ~= $_. Byłoby więc coś w stylus=gets;l= ~/$/
Cyoce
20

Zakończ swoje end.

Spróbuj usunąć endze swojego kodu.

Nie używaj def...enddo 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ę.

# 28 characters
def c n
/(\d)\1/=~n.to_s
end

# 23 characters, saves 5
c=->n{/(\d)\1/=~n.to_s}

Wywołania metod to c nlub c(n). Połączenia z Lambda są c[n]. Zmiana każdej c nz nich c[n]kosztuje 1 znak, więc jeśli możesz użyć c nwięcej niż 5 razy, zachowaj metodę.

Wszystkie metody pobierające do...endbloki 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ć.

# 48 characters
(?a..?m).zip (1..5).cycle do|a|puts a.join','end

# WRONG: passes block to cycle, not zip
(?a..?m).zip (1..5).cycle{|a|puts a.join','}

# 45 characters, saves 3
(?a..?m).zip((1..5).cycle){|a|puts a.join','}

Wymienić if...else...endz operatorem trójskładnikowego ?: . Jeśli gałąź ma dwie lub więcej instrukcji, zawiń je w nawiasy.

# 67 characters
if a<b
puts'statement 1'
puts'statement 2'else
puts'statement 3'end

# 62 characters, saves 5
a<b ?(puts'statement 1'
puts'statement 2'):(puts'statement 3')

Prawdopodobnie nie masz pętli whilelub until, ale jeśli tak, to napisz je w postaci modyfikatora.

(a+=1
b-=1)while a<b
kernigh
źródło
Czy nawiasy wokół są puts'statement 3'konieczne?
Cyoce,
15

Dodatek do w0lf

Podczas pracy z tablicami .compactmożna je zastąpić, -[nil]aby zapisać 2 znaki.

W połączeniu z powyższym -> możesz go jeszcze skrócić, -[p]aby zapisać kolejne 2 znaki.

villu164
źródło
14

W miarę możliwości używaj krótkich predefiniowanych zmiennych, np. $*Zamiast ARGV. Jest to dobra lista z nich tutaj , wraz z wieloma innymi przydatnymi informacjami.

Nemo157
źródło
12

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 $_, $&, $1itp:

puts "this program has read #$. lines of input"

Dlatego też, jeśli chcesz wydrukować zmienną częściej niż użyjesz jej w inny sposób, możesz zapisać niektóre bajty.

a=42; puts "here is a: #{a}"; puts "here is a again: #{a}"
$b=43; puts "here is b: #$b"; puts "here is b again: #$b"
daniero
źródło
11

Jeśli chcesz sprawdzić, czy dany element eznajduje się w zasięgu r, możesz użyć

r===e

zamiast dłuższego:

r.cover?(e) # only works if `r.exclude_end?` is false

lub

r.member?(e)

lub

r.include?(e)
Cristian Lupascu
źródło
3
Nie jest r===ejeszcze krótszy?
akuhn
@akuhn Tak, to prawda. Znacznie krótszy. Dzięki za zwrócenie na to uwagi pomogło mi skrócić mój kod o 10 znaków, co jest ogromne: codegolf.stackexchange.com/a/6125/3527
Cristian Lupascu
1
Nie ma za co. ===Zaimplementowano wszystko, co może być użyte w instrukcji switch .
akuhn
10

$_ jest ostatnim czytanym wierszem.

  • print - jeżeli nie podano argumentu treść wydruku $_
  • ~/regexp/ - skrót od $_=~/regexp/

W Ruby 1.8 masz cztery metody, Kernelktóre działają na $_:

  • chop
  • chomp
  • sub
  • gsub

W Ruby 1.9 te cztery metody istnieją tylko wtedy, gdy skrypt używa -nlub -p.

Jeśli chcesz często drukować jakieś zmienne, użyj trace_var(:var_name){|a|p a}

Hauleth
źródło
2
Są one dostępne tylko po uruchomieniu Ruby z opcją -plub -n. Odniesienie.
Darren Stone,
1
Wygląda na to, że trace_vardziała tylko z globalnymi zmiennymi $
daniero
10

Użyj interpolacji ciągów!

  1. Aby wymienić to_s. Jeśli potrzebujesz nawiasów wokół tego, co chcesz przekształcić w ciąg, to_sjest on o dwa bajty dłuższy niż interpolacja ciągu:

    (n+10**i).to_s
    "#{n+10**i}"
    
  2. Aby zastąpić konkatenację. Jeśli połączysz coś otoczonego dwoma innymi łańcuchami, interpolacja może zaoszczędzić jeden bajt:

    "foo"+c+"bar"
    "foo#{c}bar"
    

    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):

    "foo"+c+d+e+"bar"
    "foo#{c+d+e}bar"
    
Martin Ender
źródło
10

Unikaj lengthwif a.length<n

lengthma 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, otrzymasz nilwartość falsey.

Możesz więc zmienić:

if a.length<5się if !a[4]do -5 bajtów

lub

if a.length>5do if a[5]-6 bajtów

lub

if a.length<ndo if !a[n-1]-3 bajtów

lub

if a.length>ndo if a[n]-6 bajtów

Uwaga : działa tylko z tablicą wszystkich prawdziwych wartości. posiadanie nillub falsewewnątrz tablicy może powodować problemy.

MegaTom
źródło
4
Zawsze używam size… Ale to zdecydowanie lepsze. BTW, też działa String.
manatwork
10

Nie używaj słów kluczowych truei false.

Posługiwać się:

  • !pza true(dzięki, histocrat!)
  • !0dla false. Jeśli wszystko, czego potrzebujesz, to wartość fałszowania, możesz po prostu użyć p(która zwraca nil).

aby zaoszczędzić trochę znaków.

Cristian Lupascu
źródło
1
O ile nie potrzebujesz true(tj. Jeśli prawda jest wystarczająca, jak w przypadku warunku if), nawet nie potrzebujesz !!.
Martin Ender,
4
I podobnie p(która ocenia nil) jest krótszą wartością falsey. Co oznacza, że ​​najkrótszą drogą truejest !p.
histocrat
@histocrat dobry punkt! Zredagowałem swoją odpowiedź.
Cristian Lupascu,
9

Twórz tablice za pomocą, a=i,*aaby uzyskać je w odwrotnej kolejności. Nie musisz nawet inicjować a, a jeśli to zrobisz , nie musi to być tablica .

histocrat
źródło
9

Jeśli kiedykolwiek potrzeba, aby uzyskać numer z ARGV, getlub coś podobnego zrobić coś, co wiele razy, zamiast dzwonić to_ina 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 zamiast x.to_i.times{}pozwoli Ci zaoszczędzić 2 znaki.

Możesz także ponownie napisać rzeczy takie jak p 1 while 1lub p 1 if 1jako p 1while 1lubp 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,=czapisze dwa znaki w przeciwieństwie doa=c[0]

Addison
źródło
9

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ć, nilale chcesz połączyć dodatkowe wywołania metody, jeśli tak nie jest, marnujesz bajty na obsługę nilsprawy:

arr = ["zero", "one", "two"]
x = arr[5].size
# => NoMethodError: undefined method `size' for nil:NilClass

x = arr[5].size rescue 0
# => 0

„Operator bezpiecznej nawigacji” zatrzymuje łańcuch wywołań metod, jeśli jeden zwraca nili zwraca nilcałe wyrażenie:

x = arr[5]&.size || 0
# => 0

Array#dig I Hash#dig

Głęboki dostęp do zagnieżdżonych elementów o ładnej krótkiej nazwie:

o = { foo: [{ bar: ["baz", "qux"] }] }
o.dig(:foo, 0, :bar, 1) # => "qux"

Zwraca, niljeśli trafi w ślepy zaułek:

o.dig(:foo, 99, :bar, 1) # => nil

Enumerable#grep_v

Odwrotność — Enumerable#grepzwraca wszystkie elementy, które nie pasują do podanego argumentu (w porównaniu z ===). Na przykład grep, jeśli podano blok, jego wynik jest zwracany.

(1..10).grep_v 2..5 # => [1, 6, 7, 8, 9, 10]
(1..10).grep_v(2..5){|v|v*2} # => [2, 12, 14, 16, 18, 20]

Hash#to_proc

Zwraca Proc, który zwraca wartość dla danego klucza, co może być bardzo przydatne:

h = { N: 0, E: 1, S: 2, W: 3 }
%i[N N E S E S W].map(&h)
# => [0, 0, 1, 2, 1, 2, 3]

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:

[[1, 10], [2, 20], [3, 30]].sum {|a,b| a + b }
# => 66

Integer#digits

Zwraca tablicę cyfr liczby w kolejności od najmniejszego do największego znaczenia:

123.digits # => [3, 2, 1]

W porównaniu, powiedzmy, 123.to_s.chars.map(&:to_i).reversejest to całkiem miłe.

Jako bonus wymaga opcjonalnego argumentu Radix:

a = 0x7b.digits(16) # => [11, 7]
a.map{|d|"%x"%d} # => ["b", "7"]

Comparable#clamp

Czy to, co jest napisane na puszce:

v = 15
v.clamp(10, 20) # => 15
v.clamp(0, 10) # => 10
v.clamp(20, 30) # => 20

Ponieważ jest porównywalny, możesz go używać z dowolną klasą zawierającą porównywalne, np .:

?~.clamp(?A, ?Z) # => "Z"

String#unpack1

2-bajtowe oszczędności w porównaniu z .unpack(...)[0]:

"👻💩".unpack(?U)    # => [128123]
"👻💩".unpack(?U)[0] # => 128123
"👻💩".unpack1(?U)   # => 128123

Argument dokładność Numeric#ceil, floororaztruncate

Math::E.ceil(1) # => 2.8
Math::E.floor(1) # => 2.7
(-Math::E).truncate(1) # => -2.7

Wielokrotne przypisanie warunków warunkowych

To powoduje błąd we wcześniejszych wersjach Ruby, ale jest dozwolone w 2.4.

(a,b=1,2) ? "yes" : "no" # => "yes"
(a,b=nil) ? "yes" : "no" # => "no"
Jordania
źródło
Golf Math::E.ceil(1)do Math::E.ceil 1, a także dla floori truncate.
Po prostu piękna sztuka,
1
@SimplyBeautifulArt Spodziewam się, że ktoś gra w Ruby w golfa, będzie mógł sam to zrobić.
Jordan
Na Enumerable#sum, .flatten.sumjest krótszy niż 2 bajty.sum{|a,b|a+b}
asone Tuhid
(-Math::E).truncate(1)jest równoznaczne z -Math::E.truncate(1)których jest 1 bajt krótszy
asone Tuhid
1
&.może być używany z takim indeksowaniem jak ten a&.[]i(1 bajt krótszy niż a&.at i). Chociaż, jeśli wymagane są nawiasy a||a[i]a&.[](i)a&.at(i)
kwadratowe
7

Notacja naukowa może być często używana do golenia znaku lub dwóch znaków:

x=1000
#versus
x=1e3
anonimowy tchórz
źródło
9
Uwaga: Zwróci to wartość zmiennoprzecinkową (1000,0) zamiast liczby całkowitej, co może powodować niedokładne wyniki przy dużych liczbach.
Dogbert
4
Ach, fajnie 1e2jest lepiej niż 100.0wtedy, gdy potrzebny jest procent.
Phrogz
Podobnie do tej zasady, 1.0*jest o 1 char krótszy niż.to_f
Unihedron
7

Użyj metod operatora zamiast nawiasów

Powiedzmy, że chcesz wyrazić a*(b+c). Z powodu pierwszeństwa a*b+cnie zadziała (oczywiście). Na ratunek przychodzi fajny sposób, w jaki Ruby stosuje operatorów jako metody! Możesz użyć, a.*b+caby ustawić priorytet na *niższy niż +.

a*(b+c) # too long
a*b+c   # wrong
a.*b+c  # 1 byte saved!

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 .@)

(~x).to_s # too long
~x.to_s   # error
x.~.to_s  # 1 byte saved!
Cyoce
źródło
6

Użyj ||zamiast ori &&zamiast and.

Oprócz jednej postaci andmożesz zaoszczędzić miejsca (i być może nawias klamrowy) wokół operatora.

p true and false ? 'yes' :'no'   #-> true (wrong result)
p (true and false) ? 'yes' :'no' #-> 'no'
p true&&false ? 'yes' :'no'      #-> 'no', saved 5 characters


p true or false ? 'yes' :'no'   #-> true (wrong result)
p (true or false) ? 'yes' :'no' #-> 'yes'
p true||false ? 'yes' :'no'      #-> 'yes', saved 4 characters

Jeśli zapętlisz tablicę, której zwykle używasz each. Ale mapzapętla się również nad tablicą i jest ona o jeden znak krótsza.

knut
źródło
6

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

describe PigLatin do
  describe '.translate' do
    it 'translates "cat" to "atcay"' do
      expect(PigLatin.translate('cat')).to eq('atcay')
    end
    # And similar examples for .translate
  end
end

Ze względu na kod-golfa nie trzeba tworzyć modułu ani klasy.

Zamiast

module PigLatin def self.translate s;'some code'end;end

można zrobić

def(PigLatin=p).translate s;'some code'end

Zapisuje 13 znaków!

S Shah
źródło
7
Ha, bardzo dokładny. Nie tylko dodać niezbędną do zachowania PigLatin, ale także @pig_latin, $pig_latini 'pig'['latin'].
histocrat
@histocrat: Teraz rozumiem. To dlatego, translateże został zdefiniowany w dniu nil.
Eric Duminil,
6

Jądro # p jest zabawną metodą.

Użyj p varzamiast puts 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 pzwraca argument po wydrukowaniu.

Używany z wieloma argumentami pzwraca argumenty w tablicy.

Użyj p(bez argumentów) zamiast nil.

Fábio Perez
źródło
10
Niestety p 'some string'grafiki "some string"i nie tylko some stringto, co jest często krytykowane przez innych.
Patrick Oscity
1
Zasadniczo p sjest taki sam puts s.inspect, ale powracas
Cyoce
6

Nie używaj #each. Możesz dobrze zapętlić wszystkie elementy za pomocą #map. Więc zamiast

ARGV.each{|x|puts x}

możesz zrobić to samo w mniejszej liczbie bajtów.

ARGV.map{|x|puts x}

Oczywiście w tym przypadku puts $*byłby jeszcze krótszy.


Istnieją literały dla liczb wymiernych i zespolonych:

puts 3/11r == Rational(3,11)
puts 3.3r == Rational(66,20)
puts 1-1.i == Complex(1,-1)

=> true
true
true

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:

(0..10).to_a.join'
'

 => "0\n1\n2\n3\n4\n5\n6\n7\n8\n9\n10"

Możesz użyć ?\ni ?\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:

A=C+B=7+C=9

=> A=17, B=16, C=9

To jest krótszy niż C=9;B=16;A=17lub C=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:

loop{break if'
'==f(gets)}

while'
'!=f(gets);end

Więcej sztuczek gsub / regexp. Użyj specjalnych '\1'znaków zmiany znaczenia zamiast bloku:

"golf=great short=awesome".gsub(/(\w+)=(\w+)/,'(\1~>\2)')

"golf=great short=awesome".gsub(/(\w+)=(\w+)/){"(#{$1}~>#{$2})")

Oraz specjalne zmienne $1itp., Jeśli chcesz wykonać operacje. Pamiętaj, że są zdefiniowane nie tylko wewnątrz bloku:

"A code-golf challenge." =~ /(\w+)-(\w+)/
p [$1,$2,$`,$']

=> ["code", "golf", "A ", " challenge."] 

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 ...

x+=1if$*<<A==????::??==??
blutorange
źródło
„Opublikuj jedną wskazówkę na odpowiedź”. ?\nJest także przyjemny, ale nie krótszy niż wstawianie znaku nowej linii do cudzysłowów. (to samo dla karty)
Martin Ender
I puts$*jest jeszcze krótszy.
Cyoce,
Wiem, że x+=1;$*<<A
starałeś
6

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:

a=[0]
*a=0

Przy wielu wartościach nie potrzebujesz nawet operatora splat (dzięki histocratowi za poprawienie mnie na tym):

a=[1,2]
a=1,2
Martin Ender
źródło
Ten drugi przypadek tak naprawdę nie potrzebuje ikony.
histocrat
@histocrat O rany, myślałem, że w takim przypadku druga wartość zostanie po prostu odrzucona.
Martin Ender
1
Nie mogę uwierzyć, że nie znałem ich przez cały czas, gdy grałem w golfa w Ruby.
Klamka
6

Gdy wyzwanie wymaga wypisania wielu wierszy, nie musisz zapętlać wyników, aby wydrukować każdy wiersz np. Tablicy. putsMetoda spłaszczyć tablicy i wydrukowania każdego elementu w osobnej linii.

> a = %w(testing one two three)
> puts a
testing
one
two
three

Łącząc z sobą operatora splat #p, możesz uczynić go jeszcze krótszym:

p *a

Operator splat (technicznie *@wydaje mi się, że metoda) również rzutuje twoje tablice niepoliczalne na tablice:

> p a.lazy.map{|x|x*2}
#<Enumerator::Lazy: #<Enumerator::Lazy: [1, 2, 3]>:map>

vs

> p *a.lazy.map{|x|x*2}
2
4
6
daniero
źródło
1
*@nie jest metodą, ikona jest cukrem syntaktycznym
Asone Tuhid
6

Zapisz niektóre bajty podczas usuwania powtarzających się elementów tablicy

a.uniq # before
a|[]   # after
    ^^

Jeśli będziesz używał pustej tablicy []w zmiennej, możesz zapisać jeszcze więcej bajtów:

a.uniq;b=[] # before
a|b=[]      # after
      ^^^^^
Cyoce
źródło
2
W pierwszym przypadku a&ajest o 1 bajt krótszy
Asone Tuhid
5

Użyj Goruby zamiast Ruby, co jest jak skrócona wersja Ruby. Możesz zainstalować go za pomocą rvm przez

rvm install goruby

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:

shortest_abbreviation :puts
#=> "pts"

Array.new.shortest_abbreviation :map
#=> "m"

String.new.shortest_abbreviation :capitalize
#=> "cp"

Array.new.shortest_abbreviation :join
#=> "j"

Również bardzo przydatny jest aliasem saydla putsktórych sama może być skrócona z s. Więc zamiast

puts [*?a..?z].map(&:capitalize).join

możesz teraz pisać

s [*?a..?z].m(&:cp).j

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 hmetody ;-)

Patrick Oscity
źródło
Ponad 2 lata później i w końcu zorientowałem się, co ta odpowiedź przypomina mi ...
metro
5

Aby dołączyć do tablicy, zamiast tego

[...].join

Zrób to

[...]*''

co oszczędza 2 bajty. Aby dołączyć za pomocą separatora, użyj

[...]*?,
Markus
źródło
5

Indeksowanie numerów!

Właśnie to odkryłem wczoraj. n[i]zwraca nbit na i-tej pozycji. Przykład:

irb(main):001:0> n = 0b11010010
=> 210
irb(main):002:0> n[0]
=> 0
irb(main):003:0> n[1]
=> 1
irb(main):004:0> n[2]
=> 0
irb(main):005:0> n[3]
=> 0
irb(main):006:0> n[4]
=> 1
irb(main):007:0> n[5]
=> 0
Cyoce
źródło
A teraz możesz użyć więcej argumentów, takich jakn[0..3]
Simply Beautiful Art
4

Możesz być w stanie zapisać 2 znaki i użyć

[*(...)]

zamiast

(...).to_a

Załóżmy na przykład, że mamy zakres, który chcemy jako tablicę:

(1..2000).to_a

Po prostu zrób to w ten sposób:

[*1..2000]  #  Parentheses around the (ran..ge) is not needed!

A teraz masz swój zasięg jako tablicę.

Justin
źródło
5
Myślę też, że [*1..2000]działa?
Lynn
4

<< sztuczka

a.push x

można skrócić do:

a<<x

dla -4 bajtów.

MegaTom
źródło
2
Uwaga: działa to również dla Strings
Cyoce
4

Array#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żyj Array#assoc:

a = [[0,"foo"],[0,"bar"],[1,"baz"],[0,"qux"]]
a.find{|x,|x==1} # => [1,"baz"]
a.assoc(1) # => [1,"baz"]

Jest to również dobry zamiennik Enumerable#any?w niektórych sytuacjach.

Array#rassoc robi to samo, ale sprawdza ostatni element pod-tablic:

a = [[123,"good"],[456,"good"]]
a.any?{|*,x|x=="bad"} # => false
a.rassoc("bad") # => nil
Jordania
źródło
Dla a.any?linii na rassoc przykład, co ma |x,|zrobić? Czym się różni |x|?
Cyoce,
@Cyoce bloku parametrów rozpad następuje te same zasady jak destructuring assignment, tak jak to jest x=[1,2]kontra x,=[1,2]. Korzystając z mojego przykładu powyżej, z |x|, w pierwszej iteracji xbędzie [0,"foo"]. Dzięki |x,y|, xbędzie 0i ybędzie "foo". Podobnie, z |x,|, xbędzie 0. Innymi słowy, napisano: „włóż pierwszy element xi wyrzuć resztę.
Jordan
Zauważ, że to nie działa w odwrotnej kolejności, np. |,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).
Jordan