Apa tips umum yang bisa Anda berikan untuk bermain golf di Ruby?
Saya mencari ide yang dapat diterapkan pada masalah kode golf secara umum yang khusus untuk Ruby. (Misalnya, "Hapus komentar" tidak akan menjadi jawaban.)
Silakan kirim satu tip per jawaban.
Jawaban:
?d
untuk?~
di 1,8.$><<"string"
lebih pendek dariprint"string"
.$<.map{|l|...}
lebih pendek dariwhile l=gets;...;end
. Anda juga dapat menggunakannya$<.read
untuk membacanya sekaligus.$<
dangets
akan membaca dari sebuah file alih-alih stdin jika nama filenya adaARGV
. Jadi cara golfiest reimplementcat
akan:$><<$<.read
.sumber
cat
adalah membiarkan file ruby benar-benar kosong (0 byte) dan bersikeras bahwa itu harus dijalankan dari baris perintah dengan-p
bendera.puts *$<
☺
atau♫
, atau jika Anda cukup gila:?﷽.ord=65021
Gunakan operator percikan untuk mendapatkan ekor dan kepala array:
Ini juga berfungsi sebaliknya:
Gunakan
*
metode dengan string pada array untuk bergabung dengan elemen:sumber
abort
untuk menghentikan program dan mencetak string ke STDERR - lebih pendek dari yangputs
diikuti olehexit
gets
, Anda dapat menggunakan~/$/
untuk menemukan panjangnya (ini tidak termasuk baris baru jika itu ada)[]
untuk memeriksa apakah string berisi yang lain:'foo'['f'] #=> 'f'
tr
sebagaigsub
pengganti pengganti karakter-bijaksana:'01011'.tr('01','AB') #=> 'ABABB'
chop
sebagai gantichomp
sumber
abort
dan~/$/
~/$/
gets
, hasilnya disimpan dalam$_
variabel./regex/ ~= string
mengembalikan indeks pertandingan pertama. Memanggil~
regex setara dengan/regex/ ~= $_
. Jadi itu akan menjadi sepertis=gets;l= ~/$/
Akhiri
end
.Coba hapus
end
dari kode Anda.Jangan gunakan
def...end
untuk mendefinisikan fungsi. Buat lambda dengan operator baru -> di Ruby 1.9. (Operator -> adalah "lambda stabby", atau "dash rocket" .) Ini menghemat 5 karakter per fungsi.Metode panggilan adalah
c n
atauc(n)
. Panggilan Lambda adalahc[n]
. Mengubah masingc n
- masing kec[n]
biaya 1 karakter, jadi jika Anda dapat menggunakanc n
lebih dari 5 kali, maka simpan metode ini.Semua metode yang mengambil
do...end
blok dapat mengambil{...}
blok sebagai gantinya. Ini menghemat 3 hingga 5 karakter. Jika prioritas{...}
terlalu tinggi, maka gunakan tanda kurung untuk memperbaikinya.Ganti
if...else...end
dengan operator ternary?:
. Jika cabang memiliki dua pernyataan atau lebih, bungkus dalam tanda kurung.Anda mungkin tidak memiliki
while
atauuntil
mengulang, tetapi jika ya, tuliskan dalam bentuk pengubah.sumber
puts'statement 3'
diperlukan?Selain w0lf
Dikombinasikan dengan di atas -> Anda dapat membuatnya lebih pendek dengan
-[p]
menyimpan 2 karakter lainnya.sumber
Gunakan variabel yang telah ditetapkan pendek sedapat mungkin, misalnya
$*
bukanARGV
. Ada daftar yang bagus di sini , bersama dengan banyak informasi berguna lainnya.sumber
Ketika Anda menggunakan interpolasi string, (seperti yang seharusnya Anda lakukan pada posting Martin Büttner ), Anda tidak perlu tanda kurung keriting jika objek Anda memiliki sigil (
$
,@
) di depannya. Berguna untuk variabel magis seperti$_
,$&
,$1
dll:Begitu juga jika Anda perlu mencetak variabel lebih dari yang Anda gunakan, Anda dapat menghemat beberapa byte.
sumber
Jika Anda perlu menemukan jika elemen tertentu
e
berada di dalam rentangr
, Anda bisa menggunakannyabukannya lebih lama:
atau
atau
sumber
r===e
Bahkan tidak lebih pendek?===
diimplementasikan.$_
adalah baris terakhir dibaca.print
- jika tidak ada argumen yang diberikan konten cetak$_
~/regexp/
- kependekan dari$_=~/regexp/
Di Ruby 1.8, Anda memiliki empat metode
Kernel
yang beroperasi pada$_
:chop
chomp
sub
gsub
Di Ruby 1.9, keempat metode ini hanya ada jika skrip Anda menggunakan
-n
atau-p
.Jika Anda ingin mencetak beberapa variabel sering maka gunakan
trace_var(:var_name){|a|p a}
sumber
-p
atau-n
. Referensi.trace_var
hanya bekerja dengan variabel $ globalGunakan interpolasi string!
Untuk mengganti
to_s
. Jika Anda membutuhkan tanda kurung di sekitar apa pun yang ingin Anda ubah menjadi string,to_s
dua byte lebih panjang dari interpolasi string:Untuk mengganti rangkaian. Jika Anda menggabungkan sesuatu yang dikelilingi oleh dua string lainnya, interpolasi dapat menghemat satu byte:
Juga berfungsi jika hal tengah itu sendiri disatukan, jika Anda hanya memindahkan rangkaian di dalam interpolasi (alih-alih menggunakan beberapa interpolasi):
sumber
Hindari
length
masukif a.length<n
length
adalah 6 byte, sedikit mahal dalam kode golf. dalam banyak situasi, Anda dapat memeriksa apakah array memiliki sesuatu pada titik tertentu. jika Anda melewati indeks terakhir yang akan Anda dapatkannil
, nilai falsey.Jadi, Anda dapat Mengubah:
if a.length<5
keif !a[4]
untuk -5 byteatau
if a.length>5
keif a[5]
-6 byteatau
if a.length<n
keif !a[n-1]
-3 byteatau
if a.length>n
keif a[n]
-6 byteCatatan : hanya akan bekerja dengan larik semua nilai kebenaran. memiliki
nil
ataufalse
di dalam array dapat menyebabkan masalah.sumber
size
... Tapi ini jelas lebih baik. BTW, bekerjaString
juga.Jangan gunakan kata kunci
true
danfalse
.Menggunakan:
!p
untuktrue
(terima kasih, histokrat!)!0
untukfalse
. Jika semua yang Anda butuhkan adalah nilai palsu, maka Anda cukup menggunakanp
(yang mengembalikannil
).untuk menyimpan beberapa karakter.
sumber
true
(yaitu jika nilai kebenaran sudah cukup, seperti dalam kondisi if), Anda bahkan tidak perlu!!
.p
(yang mengevaluasinil
) adalah nilai falsey yang lebih pendek. Yang berarti cara terpendek untuk mendapatkannyatrue
adalah!p
.Bangun array yang digunakan
a=i,*a
untuk membuatnya dalam urutan terbalik. Anda bahkan tidak perlu menginisialisasia
, dan jika Anda melakukannya , tidak harus berupa array .sumber
Jika Anda perlu mendapatkan nomor dari
ARGV
,,get
atau sesuatu yang serupa untuk melakukan sesuatu yang berkali-kali, alih-alih memanggilnyato_i
, Anda bisa menggunakan?1.upto x{do something x times}
mana x adalah string.Jadi menggunakan
?1.upto(a){}
bukannyax.to_i.times{}
akan menghemat 2 karakter.Anda juga dapat menulis ulang hal-hal seperti
p 1 while 1
ataup 1 if 1
sebagaip 1while 1
ataup 1if 1
Contoh itu tidak terlalu berguna, tetapi bisa digunakan untuk hal lain.
Selain itu, jika Anda perlu menetapkan elemen pertama array ke variabel,
a,=c
akan menyimpan dua karakter sebagai lawana=c[0]
sumber
Fitur baru di Ruby 2.3 dan 2.4
Ada baiknya untuk tetap mengikuti fitur bahasa baru yang akan membantu permainan golf Anda. Ada beberapa yang hebat di Rubi terbaru.
Ruby 2.3
Operator navigasi yang aman:
&.
Saat Anda memanggil metode yang mungkin kembali
nil
tetapi Anda ingin membuat panggilan metode tambahan jika tidak, Anda membuang byte yang menanganinil
kasus ini:"Operator navigasi aman" menghentikan rantai panggilan metode jika seseorang kembali
nil
dan kembalinil
untuk seluruh ekspresi:Array#dig
&Hash#dig
Akses mendalam ke elemen bersarang, dengan nama pendek yang bagus:
Kembali
nil
jika menyentuh jalan buntu:Enumerable#grep_v
Kebalikan dari -
Enumerable#grep
mengembalikan semua elemen yang tidak cocok dengan argumen yang diberikan (dibandingkan dengan===
). Sepertigrep
, jika sebuah blok diberikan hasilnya dikembalikan sebagai gantinya.Hash#to_proc
Mengembalikan Proc yang menghasilkan nilai untuk kunci yang diberikan, yang bisa sangat berguna:
Ruby 2.4
Ruby 2.4 belum keluar, tetapi akan segera dan memiliki beberapa fitur kecil yang hebat. (Ketika dirilis saya akan memperbarui posting ini dengan beberapa tautan ke dokumen.) Saya belajar tentang sebagian besar dari ini di posting blog besar ini .
Enumerable#sum
Tidak ada lagi
arr.reduce(:+)
. Sekarang Anda bisa melakukannyaarr.sum
. Dibutuhkan argumen nilai awal opsional, yang default ke 0 untuk elemen Numeric ([].sum == 0
). Untuk jenis lain Anda harus memberikan nilai awal. Itu juga menerima blok yang akan diterapkan ke setiap elemen sebelum penambahan:Integer#digits
Ini mengembalikan array angka angka dalam urutan signifikansi terkecil ke terbesar:
Dibandingkan dengan, katakanlah
123.to_s.chars.map(&:to_i).reverse
, ini cukup bagus.Sebagai bonus, dibutuhkan argumen radix opsional:
Comparable#clamp
Lakukan apa yang tertulis di kaleng:
Karena itu dalam Sebanding Anda dapat menggunakannya dengan kelas apa pun yang termasuk Sebanding, misalnya:
String#unpack1
Penghematan 2 byte
.unpack(...)[0]
:Presisi argumen untuk
Numeric#ceil
,floor
, dantruncate
Penugasan berganda dalam kondisi
Ini menimbulkan kesalahan dalam versi Ruby yang lebih lama, tetapi diizinkan di 2.4.
sumber
Math::E.ceil(1)
untukMath::E.ceil 1
, dan juga untukfloor
dantruncate
.Enumerable#sum
,.flatten.sum
2 byte lebih pendek dari.sum{|a,b|a+b}
(-Math::E).truncate(1)
setara dengan-Math::E.truncate(1)
yang 1 byte lebih pendek&.
dapat digunakan dengan berlangganan seperti inia&.[]i
(1 byte lebih pendek daria&.at i
). Meskipun, jika tanda kurung diperlukan,a||a[i]
apakah 1 byte lebih pendek daria&.[](i)
ataua&.at(i)
Notasi ilmiah sering dapat digunakan untuk memotong satu atau dua arang:
sumber
1e2
lebih baik daripada100.0
saat dibutuhkan persentase.1.0*
adalah 1 char lebih pendek dari.to_f
Gunakan metode operator alih-alih tanda kurung
Katakanlah Anda ingin mengekspresikan
a*(b+c)
. Karena diutamakan,a*b+c
tidak akan bekerja (jelas). Cara keren Ruby untuk memiliki operator sebagai metode untuk menyelamatkan! Anda dapat menggunakana.*b+c
untuk membuat prioritas*
lebih rendah dari itu+
.Ini juga dapat bekerja dengan
!
dan~
operator (hal-hal seperti unary+
atau unary-
tidak bekerja karena metode mereka-@
dan+@
, tabungan()
tetapi menambahkan.@
)sumber
Gunakan
||
sebagai gantinyaor
dan&&
sebaliknyaand
.Di samping satu karakter dari
and
Anda dapat menghemat ruang (dan mungkin braket) di sekitar operator.Jika Anda mengulang pada array yang biasanya Anda gunakan
each
. Tetapimap
loop juga melalui array dan itu adalah satu karakter lebih pendek.sumber
Saya baru saja mencoba tantangan kode-golf TDD yaitu Menulis kode terpendek untuk membuat spesifikasi lulus. Spesifikasinya kira-kira seperti itu
Demi kode-golf, seseorang tidak perlu membuat modul atau kelas.
Dari pada
seseorang bisa melakukannya
Menghemat 13 karakter!
sumber
PigLatin
, tetapi juga untuk@pig_latin
,$pig_latin
, dan'pig'['latin']
.translate
telah ditetapkannil
.Kernel # p adalah metode yang menyenangkan.
Gunakan
p var
sebagai gantiputs var
. Ini berfungsi sempurna dengan bilangan bulat dan mengapung, tetapi tidak dengan semua jenis. Ini mencetak tanda kutip di sekitar string, yang mungkin bukan yang Anda inginkan.Digunakan dengan argumen tunggal,
p
mengembalikan argumen setelah mencetaknya.Digunakan dengan banyak argumen,
p
mengembalikan argumen dalam array.Gunakan
p
(tanpa argumen) sebagai gantinil
.sumber
p 'some string'
hasil cetak"some string"
dan bukan hanyasome string
yang sering dikritik oleh orang lain.p s
sama denganputs s.inspect
, tetapi kembalis
Jangan gunakan #each. Anda dapat mengulang semua elemen dengan #map. Jadi, bukannya
Anda dapat melakukan hal yang sama dalam lebih sedikit byte.
Tentu saja, dalam hal ini
puts $*
akan lebih pendek.Ada literal untuk bilangan rasional dan kompleks:
Anda dapat menggunakan sebagian besar byte dalam string.
"\x01"
(6 byte) dapat disingkat menjadi""
(3 byte). Jika Anda hanya membutuhkan satu byte ini, ini dapat dipersingkat lebih jauh menjadi?
(2 byte).Dengan cara yang sama, Anda bisa mendapatkan baris baru lebih pendek seperti ini:
Anda dapat menggunakan
?\n
dan?\t
juga, yang satu byte lebih pendek dari"\n"
dan"\t"
. Untuk kebingungan, ada juga spasi?Gunakan konstanta alih-alih memberikan argumen, bahkan jika Anda perlu mengubahnya. Penerjemah akan memberikan peringatan kepada stderr , tetapi siapa yang peduli. Jika Anda perlu mendefinisikan lebih banyak variabel yang terkait satu sama lain, Anda dapat membuat mereka seperti ini:
Ini lebih pendek dari
C=9;B=16;A=17
atauC=0;B=C+7;A=C+B
.Jika Anda membutuhkan loop tak terbatas, gunakan
loop{...}
. Loop dengan panjang yang tidak diketahui mungkin lebih pendek dengan loop lainnya:Beberapa lagi trik gsub / regexp. Gunakan
'\1'
karakter pelarian khusus alih-alih blok:Dan variabel khusus
$1
dll. Jika Anda perlu melakukan operasi. Perlu diingat bahwa mereka didefinisikan tidak hanya di dalam blok:Singkirkan spasi, baris baru, dan tanda kurung. Anda dapat menghilangkan sedikit ruby. Jika ragu, selalu coba jika berhasil tanpa, dan perlu diingat ini mungkin merusak beberapa sintaks editor yang disorot ...
sumber
?\n
bagus, tetapi tidak terlalu pendek daripada benar-benar menempatkan karakter baris baru di dalam tanda kutip. (sama untuk tab)puts$*
bahkan lebih pendek.x+=1;$*<<A
Namun cara lain untuk menggunakan operator percikan: jika Anda ingin menetapkan literal array tunggal, a
*
di sisi kiri lebih pendek dari tanda kurung di sisi kanan:Dengan beberapa nilai, Anda bahkan tidak memerlukan operator percikan (terima kasih kepada histocrat karena telah mengoreksi saya tentang hal itu):
sumber
Ketika sebuah tantangan mengharuskan Anda menghasilkan beberapa baris, Anda tidak perlu mengulang -ulang hasil Anda untuk mencetak setiap baris misalnya array. The
puts
Metode akan meratakan sebuah array dan mencetak setiap elemen pada baris terpisah.Menggabungkan operator percikan dengan
#p
Anda dapat membuatnya lebih pendek:Operator percikan (secara teknis
*@
metode, saya pikir) juga melemparkan enumerables non-array Anda ke array:vs.
sumber
*@
bukan metode, percikan adalah gula sintaksisSimpan beberapa byte saat menghapus elemen array yang berulang
Jika Anda akan menggunakan array kosong
[]
dalam sebuah variabel, Anda dapat menyimpan lebih banyak byte:sumber
a&a
lebih pendek 1 byteGunakan Goruby alih-alih Ruby, yang mirip dengan Ruby versi singkat. Anda dapat menginstalnya dengan rvm via
Goruby memungkinkan Anda menulis sebagian besar kode Anda seperti menulis Ruby, tetapi memiliki singkatan tambahan. Untuk mengetahui singkatan tersingkat yang tersedia untuk sesuatu, Anda dapat menggunakan metode helper
shortest_abbreviation
, misalnya:Juga sangat berguna adalah alias
say
untukputs
yang itu sendiri dapat disingkat dengans
. Jadi, bukannyaAnda sekarang dapat menulis
untuk mencetak alfabet dalam huruf besar (yang bukan contoh yang sangat bagus). Posting blog ini menjelaskan lebih banyak hal dan beberapa pekerjaan dalam jika Anda tertarik membaca lebih lanjut.
PS: jangan ketinggalan
h
metode ;-)sumber
Untuk bergabung dengan array, alih-alih ini
melakukan hal ini
yang menghemat 2 byte. Untuk bergabung dengan penggunaan pemisah
sumber
Nomor Berlangganan!
Saya baru saja menemukan ini kemarin.
n[i]
mengembalikann
bit padai
posisi ke -. Contoh:sumber
n[0..3]
Anda mungkin dapat menyimpan 2 karakter dan menggunakan
dari pada
Sebagai contoh, misalkan kita memiliki rentang yang kita inginkan sebagai array:
Lakukan saja seperti ini:
Dan sekarang Anda memiliki rentang sebagai array.
sumber
[*1..2000]
berhasil juga?<< trik
dapat disingkat menjadi:
untuk -4 byte.
sumber
String
sArray#assoc
/rassoc
Ketika Anda memiliki array array dan ingin menemukan sub-array yang dimulai dengan nilai tertentu, jangan gunakan
Enumerable#find
, gunakanArray#assoc
:Ini juga merupakan pengganti yang baik untuk
Enumerable#any?
beberapa situasi.Array#rassoc
melakukan hal yang sama, tetapi memeriksa elemen terakhir sub-array:sumber
a.any?
baris dalamrassoc
contoh, apa fungsinya|x,|
? Bagaimana bedanya|x|
?x=[1,2]
vsx,=[1,2]
. Menggunakan contoh saya di atas, dengan|x|
, di iterasi pertamax
akan[0,"foo"]
. Dengan|x,y|
,x
akan0
dany
akan"foo"
. Demikian juga, dengan|x,|
,x
akan0
. Dengan kata lain, dikatakan "masukkan elemen pertamax
dan buang sisanya.|,y|
adalah SyntaxError, ergo|_,y|
. Tapi saya baru saja menyadari bahwa itu|*,y|
berfungsi, yang lebih bersih daripada menggunakan variabel bernama_
(tapi tidak lebih pendek).