Ruby'de golf için ipuçları


62

Ruby'de golf oynamak için hangi genel ipuçlarını verebilirsiniz?

Genel olarak Ruby'ye özgü golf problemlerini kodlamak için uygulanabilecek fikirler arıyorum. (Örneğin, "Yorumları kaldır" bir cevap olmaz.)

Lütfen cevap başına bir ipucu gönderin.


Birinin Rub ve Ruby gibi bir dil yazması gerekiyor, her Ruby belirteci için tek bir Unicode karakterini kullanıyor, Jelly ve Pyth gibi. :)
Mark Thomas

Yanıtlar:


46
  • 126'ya kadar sayılar 100 olarak yazılabilir ?diçin ?~1.8 içinde.
  • Benzer bir notta, 1.9? X'te tek karakterli bir dizgeye ihtiyacınız varsa, "x" den daha kısadır.
  • Yeni satır eklemeden bir dizge basmanız gerekirse, $><<"string"bundan daha kısadır print"string".
  • Birden fazla giriş satırını okumak gerekirse $<.map{|l|...}, bundan daha kısadır while l=gets;...;end. Ayrıca $<.readhepsini bir kerede okumak için kullanabilirsiniz .
  • Bir dosyadan okumanız gerekiyorsa $<ve getseğer dosya adınız varsa stdin yerine bir dosyadan okuyacaksınız ARGV. Yani yeniden uygulamaya golfiest yolu catolacaktır: $><<$<.read.

1
? x genel olarak ascii kodunu verir, böylece tüm basılabilirleri gerçekçi bir şekilde iki karakterli rakamlara getirebilirsiniz. 1.9 farklıdır, 'a'.ord ascii sayısını verir, ancak ondalık sürümden dört bayt daha uzundur.
Hiato

8
Uygulamanın daha kolay bir yolu catda yakut dosyasını tamamen boş bırakmak (0 byte) ve -pbayrakla birlikte komut satırından çalıştırılması konusunda ısrar etmektir .
daniero

1
ya da, @ daniero'nun kendi cevabından ,puts *$<
Değil ki Charles

1
Yani 1.8 yılında, tüm yapmam gereken gitmek? ~ Ve 126 dönecek?
Simply Beautiful Art,

5
Sen gibi düşünüyor kullanarak 126 ötesine gidebilir ya , yoksa yeterince çılgın ise:?﷽.ord=65021
Sadece güzel Sanatı

32

Bir dizinin kuyruğunu ve başını almak için uyarıcı operatörünü kullanın:

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

Bu aynı zamanda diğer şekilde de çalışır:

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

*Öğeleri birleştirmek için yöntemi bir dizideki bir dizeyle kullanın :

[1,2,3]*?,
=> "1,2,3"

27
  • Kullanım abortProgramı sonlandırmak ve standart hataya bir dize yazdırmak için - daha kısa putsizlediexit
  • Bir satır okursanız gets, daha sonra ~/$/uzunluğunu bulmak için kullanabilirsiniz (eğer varsa izleyen bir yeni satırı saymaz)
  • []Bir dize başka içerip içermediğini kontrol etmek için kullanın :'foo'['f'] #=> 'f'
  • Kullanım tryerine gsubkarakter akıllıca değiştirmeler için:'01011'.tr('01','AB') #=> 'ABABB'
  • Sondaki yeni satırları silmeniz gerekirse, chopyerinechomp

2
+1 abortve~/$/
J -_- L

Lütfen nasıl kullanılacağını açıklayın~/$/
Mathieu CAROFF

@MathieuCAROFF her aradığınızda gets, sonucu $_değişkende saklanır . /regex/ ~= stringilk eşleşmenin dizinini döndürür. ~Bir regex'e çağrı yapmak eşdeğerdir /regex/ ~= $_. Yani böyle bir şey olurdus=gets;l= ~/$/
Cyoce

20

Senin End end.

endKodunuzdan kaldırmayı deneyin .

def...endİşlevleri tanımlamak için kullanmayın . Ruby 1.9'daki yeni -> operatörüyle bir lambda yapın. (-> operatörü bir "stabby lambda" veya "çizgi roketi" dir .) Bu, işlev başına 5 karakter kaydeder.

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

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

Yöntem çağrıları c nveya c(n). Lambda aramaları c[n]. Her birinin maliyeti 1 karakter olarak değiştirildiği c niçin c[n], c n5 kereden fazla kullanabiliyorsanız , yöntemi saklayın.

do...endBlokları alan tüm yöntemler {...}bunun yerine blokları alabilir . Bu 3 ila 5 karakter kaydeder. Önceliği {...}çok yüksekse, düzeltmek için parantez kullanın.

# 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','}

Değiştir if...else...endile üçlü operatörü ?: . Bir dalda iki veya daha fazla ifade varsa, bunları parantez içine alın.

# 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')

Muhtemelen sahip değilsin whileya da untildöngüler, ama yaparsan, onları değiştirici biçimde yaz.

(a+=1
b-=1)while a<b

Parantezler puts'statement 3'gerekli mi?
Cyoce

15

W0lf ilavesi

Dizilerle çalışırken, 2 karakter kaydetmek .compactiçin ile değiştirilebilir -[nil].

Yukarıdaki ile birleştiğinde -> -[p]başka 2 karakter kaydetmeyi daha da kısaltabilirsiniz.


14

Mümkün örneğin kısa önceden tanımlanmış değişkenleri kullanın $*yerine ARGV. Burada birçok yararlı bilginin yanı sıra iyi bir listesi var .


12

(Eğer pr gerektiğinden, bu dize interpolasyon kullanırken Martin BÜTTNER adlı kullanıcının yayınını ) nesne bir desen (olması durumunda, süslü parantez gerekmez $, @onun önünde). Gibi büyülü değişkenler için Faydalı $_, $&, $1vb:

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

Bu nedenle, kullandığınızdan daha fazla bir değişken yazdırmanız gerekirse, bazı baytları kaydedebilirsiniz.

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"

11

Belirli bir öğenin earalık içinde olup olmadığını bulmanız gerekiyorsa r,

r===e

daha uzun yerine:

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

veya

r.member?(e)

veya

r.include?(e)

3
Daha r===ekısa değil mi?
akuhn

@akuhn Evet, öyle. Çok daha kısa. İşaret ettiğin için teşekkür ederim, kodumu 10 karakterle kısaltmama yardımcı oldu, bu çok büyük: codegolf.stackexchange.com/a/6125/3527
Cristian Lupascu

1
Rica ederim. Bir switch ifadesinde kullanılabilecek her şey ===uygulandı.
akuhn

10

$_ son okuma satırı.

  • print - yazdırılan içeriğin argümanı yoksa $_
  • ~/regexp/ - için kısa $_=~/regexp/

Ruby 1.8'de, Kernelbu konuda çalışan dört yöntem var $_:

  • chop
  • chomp
  • sub
  • gsub

Ruby 1.9'da, bu dört yöntem yalnızca komut dosyanız -nveya kullanıyorsa mevcuttur -p.

Bazı değişkenleri sık sık yazdırmak istiyorsanız trace_var(:var_name){|a|p a}


2
Bunlar yalnızca Ruby'yi -pveya -nseçeneğiyle çalıştırdığınızda kullanılabilir . Referans.
Darren Stone

1
O görünüyor trace_varküresel $ değişkenleri ile çalışan tek
daniero

10

Dize enterpolasyonu kullanın!

  1. Değiştirmek için to_s. Bir dizgiye dönüştürmek istediğiniz her şeyin parantezine ihtiyacınız varsa, to_sdize enterpolasyonundan iki byte daha uzundur:

    (n+10**i).to_s
    "#{n+10**i}"
    
  2. Birleştirmeyi değiştirmek için. İki dize ile çevrili bir şeyi birleştirirseniz, enterpolasyon sizi bir bayttan kurtarabilir:

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

    Ayrıca, orta şeyin kendisi birleştirildiyse çalışır, yalnızca birleştirmeyi enterpolasyonun içine taşırsanız (birden çok enterpolasyon kullanmak yerine):

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

10

önlemek lengthiçindeif a.length<n

length6 bayt, kod golf biraz pahalı. Çoğu durumda, dizinin belirli bir noktada bir şey olup olmadığını kontrol edebilirsiniz. alacağınız son dizini geçerseniz nilfalsey değeri alırsınız .

Böylece değiştirebilirsiniz:

if a.length<5için if !a[4]-5 baytı

veya

if a.length>5için if a[5]-6 baytı

veya

if a.length<niçin if !a[n-1]-3 baytı

veya

if a.length>niçin if a[n]-6 baytı

Not : Sadece tüm gerçek değerleri içeren bir diziyle çalışacaktır. dizinin içinde nilveya falseiçinde olması sorunlara neden olabilir.


4
Her zaman kullanırım size… Ama bu kesinlikle daha iyi. Btw, için Stringde çalışıyor .
Manat çalışması

10

trueVe falseanahtar kelimeleri kullanmayın .

kullanın:

  • !piçin true(teşekkürler, histocrat!)
  • !0için false. İhtiyacınız olan tek şey sahte bir değerse, o zaman kullanmanız yeterlidir p(ki döner nil).

bazı karakterleri kaydetmek için.


1
Gerçekte ihtiyacınız olmadığı sürece true(yani, eğer bir gerçeğe uygun değer yeterliyse, bir if koşulunda olduğu gibi), ihtiyacınız bile olmaz !!.
Martin Ender

4
Ve benzer şekilde p(buna göre değerlendirilir nil) daha kısa bir falsey değeridir. Hangi almak için en kısa yol demektir trueolduğunu !p.
histocrat

@ histokrat iyi nokta! Cevabımı düzenledim.
Cristian Lupascu


9

Hiç bir numara almak gerekiyorsa ARGV, getveya benzer bir şey defalarca yerine çağıran bir şeyler yapmak to_iüzerine, sadece kullanabilirsiniz ?1.upto x{do something x times}x dizedir.

Böylece ?1.upto(a){}yerine kullanarak x.to_i.times{}2 karakter kaydedersiniz.

Ayrıca gibi şeyler yeniden yazabilir p 1 while 1veya p 1 if 1olarak p 1while 1veyap 1if 1

Bu örnek pek kullanışlı değil, ancak başka şeyler için de kullanılabilir.

Ayrıca, bir dizinin ilk öğesini bir değişkene atamanız gerekirse, a,=ciki karakterin karşısınaa=c[0]


9

Ruby 2.3 ve 2.4'teki yeni özellikler

Golf oyununuza yardımcı olacak yeni dil özelliklerinden haberdar olmak iyidir. En son Rubies'de birkaç tane harika olanlar var.

Ruby 2.3

Güvenli navigasyon operatörü: &.

Dönebilecek bir yöntem çağırdığınızda nilancak ek yöntem çağrıları zincirleme yapmak istiyorsanız, bu nildurumu ele alan baytları boşa harcarsınız :

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

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

"Güvenli gezinme operatörü", bir ifadenin tamamı için döner nilve dönerse , yöntem çağrıları zincirini durdurur nil:

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

Array#dig & Hash#dig

Kısa bir ad ile iç içe geçmiş öğelere derin erişim:

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

İade nilo çıkmaz vurursa:

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

Enumerable#grep_v

' Enumerable#grepİn tersi , verilen argümana uymayan tüm öğeleri döndürür (karşılaştırıldığında ===). Gibi grep, bir blok verilirse bunun yerine sonuç döndürülür.

(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

Verilen anahtar için değeri veren bir Proc döndürür, bu oldukça kullanışlı olabilir:

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]

Yakut 2.4

Ruby 2.4 henüz çıkmadı, ancak yakında olacak ve bazı harika küçük özelliklere sahip. (Yayınlandığı zaman, bu yazıyı dokümanlara bazı linklerle güncelleyeceğim.) Bu harika blog yayınında bunların çoğunu öğrendim .

Enumerable#sum

Daha fazla yok arr.reduce(:+). Şimdi sadece yapabilirsin arr.sum. Numeric elements ( [].sum == 0) için varsayılan olarak 0 olan, isteğe bağlı bir başlangıç ​​değer bağımsız değişkenini alır . Diğer türler için bir başlangıç ​​değeri sağlamanız gerekir. Ayrıca, eklemeden önce her bir elemana uygulanacak bir bloğu kabul eder:

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

Integer#digits

Bu, bir sayının basamağını en az en büyük önem sırasına göre döndürür:

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

Demek ki, 123.to_s.chars.map(&:to_i).reversebu oldukça hoş.

Bir bonus olarak, isteğe bağlı bir radix argümanını alır:

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

Comparable#clamp

Teneke söylediklerini yapar:

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

Karşılaştırılabilir olduğundan, Karşılaştırılabilir içeren herhangi bir sınıfla kullanabilirsiniz, örneğin:

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

String#unpack1

2 baytlık tasarruf .unpack(...)[0]:

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

Hassas argüman için Numeric#ceil, floorvetruncate

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

Koşullu olarak çoklu atama

Bu Ruby'nin önceki sürümlerinde bir hataya neden olur, ancak 2.4'te izin verilir.

(a,b=1,2) ? "yes" : "no" # => "yes"
(a,b=nil) ? "yes" : "no" # => "no"

Golf Math::E.ceil(1)için Math::E.ceil 1ve aynı şekilde için floorve truncate.
Tek kelimeyle güzel sanat

1
@SimplyBeautifulArt Ruby'de golf oynayan birinin bu atlamayı kendi kendine yapabileceğini umuyorum.
Jordan

Çünkü Enumerable#sum, .flatten.sum2 bayttan daha kısa.sum{|a,b|a+b}
Asone Tuhid

(-Math::E).truncate(1)-Math::E.truncate(1)1 bayt daha kısa olan eşdeğeri
Asone Tuhid

1
&.böyle bir abonelik ile kullanılabilir a&.[]i(1 bayt daha kısa a&.at i). Parantez gerekirse, a||a[i]1 bayt a&.[](i)veya daha kısa olsa daa&.at(i)
Asone Tuhid

7

Bilimsel gösterim genellikle bir veya iki karakterin tıraş edilmesi için kullanılabilir:

x=1000
#versus
x=1e3

9
Not: Bu bir Tamsayı yerine bir Kayan değer (1000.0) döndürür, bu da büyük sayılarla yanlış sonuçlara neden olabilir.
Dogbert

4
Ah, 1e2iyi 100.0bir yüzdeye ihtiyaç duyduğundan daha iyidir .
Phrogz

Bu ilkeye benzer şekilde 1.0*, 1 karakterden daha kısa.to_f
Unihedron

7

Parantez yerine operatör yöntemlerini kullanın

Demek istediğimi söyleyelim a*(b+c). Öncelik nedeniyle, a*b+cişe yaramayacak (belli ki). Ruby'nin operatör olarak yöntemlerini kullanmanın en iyi yolu kurtarmaya geliyor! Sen kullanabilirsiniz a.*b+cönceliğini yapmak *daha düşüktür +.

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

Bu aynı zamanda !ve ~operatörleri ile de çalışabilir (unary +ya da unary gibi şeyler -işe yaramıyor, çünkü yöntemleri -@ve +@kaydediyor ()ama ekliyorlar .@)

(~x).to_s # too long
~x.to_s   # error
x.~.to_s  # 1 byte saved!

6

Kullanım ||yerine orve &&onun yerine and.

Bir karakterin yanında, andoperatörün etrafındaki boşlukları (ve belki de braketi) kaydedebilirsiniz.

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

Bir dizi üzerinde döngü yaparsanız normalde kullanın each. Ancak mapbir dizi üzerinde de döngüler var ve bir karakterden daha kısa.


6

TDD kod-golf mücadelesine girmeye çalıştım. Özellikleri gibi bir şeydi

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

Code-golf uğruna, bir modül veya sınıf oluşturmak gerekmez.

Onun yerine

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

biri yapabilir

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

13 karakter kaydeder!


7
Ha, çok kapsamlı. Eğer gerekli davranışı eklemek kalmamış PigLatin, aynı zamanda etmek @pig_latin, $pig_latinve 'pig'['latin'].
histocrat

@ histokrat: Şimdi anlıyorum. Bunun nedeni translatetanımlanmıştır nil.
Eric Duminil

6

Çekirdek # p eğlenceli bir yöntemdir.

Yerine p varkullanın puts var. Bu, tamsayılar ve kayan noktalarla mükemmel çalışır, ancak her türle olmaz. Dizelerin etrafına tırnak işaretleri basıyor, bu muhtemelen istediğiniz şey değil.

Tek bir argümanla kullanıldığında, pyazdırdıktan sonra argümanı döndürür.

Birden fazla argümanla kullanıldığında, pbir dizideki argümanları döndürür.

Yerine p(argüman olmadan) kullanın nil.


10
Maalesef p 'some string'baskılar "some string"ve sadece some stringdiğerleri tarafından eleştirilmediği gibi.
Patrick Oscity

1
Temelde p saynı puts s.inspect, ama geri döners
Cyoce

6

#Each kullanmayın. #Map ile tüm öğelerin üzerinde döngü yapabilirsiniz. Yani yerine

ARGV.each{|x|puts x}

aynısını daha az baytta yapabilirsiniz.

ARGV.map{|x|puts x}

Tabii ki, bu durumda puts $*daha kısa olurdu.


Rasyonel ve karmaşık sayılar için değişmezler vardır:

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

=> true
true
true

Dizelerin içindeki çoğu baytı kullanabilirsiniz. "\x01"(6 bayt), ""(3 bayt) ile kısaltılabilir . Sadece bir bayt'a ihtiyacınız varsa, bu ?(2 bayt) daha da kısaltılabilir .

Aynı şekilde, yeni satırları şöyle kısaltabilirsiniz:

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

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

Sen kullanabilirsiniz ?\nve ?\tbir byte daha kısa olan, hem de "\n"ve "\t". Şaşırtmak için, ayrıca bir boşluk var.


Değiştirmeniz gerekse bile, argümanları dolaşmak yerine sabitleri kullanın. Tercüman, stderr'e uyarı verecek , fakat kimin umrunda. Birbirleriyle ilgili daha fazla değişken tanımlamanız gerekirse, bunları şu şekilde zincirleyebilirsiniz:

A=C+B=7+C=9

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

Bu C=9;B=16;A=17ya da daha kısa C=0;B=C+7;A=C+B.


Sonsuz bir döngüye ihtiyacınız varsa kullanın loop{...}. Bilinmeyen uzunlukta ilmekler diğer ilmeklerle daha kısa olabilir:

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

while'
'!=f(gets);end

Biraz daha gsub / regexp püf noktaları. '\1'Bir blok yerine özel kaçış karakterlerini kullanın:

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

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

Ve $1eğer işlem yapmanız gerekiyorsa özel değişkenler vb. Sadece bloğun içinde tanımlanmadıklarını unutmayın:

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

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

Boşluklardan, yeni satırlardan ve parantezlerden kurtulun. Yakut içinde biraz ihmal edebilirsiniz. Şüpheniz varsa, daima çalışıp çalışmadığını deneyin ve aklınızda bulundurun, bunun bazı editörlerin sözdizimini vurguladığını ...

x+=1if$*<<A==????::??==??

"Lütfen cevap başına bir ipucu gönderin." Ayrıca ?\ngüzel, ama aslında tırnak içine newline karakter koymaktan daha kısa değil. (sekme için aynı)
Martin Ender

Ve puts$*daha da kısa.
Cyoce

Bir şeyi kanıtlamaya çalıştığını biliyorum ama son örneğin aynı x+=1;$*<<A
olduğuna eminim

6

Splat operatörünü kullanmanın başka bir yolu: tek bir dizi değişmez atamak istiyorsanız *, sol taraftaki bir taraf sağ taraftaki köşebentlerden daha kısadır:

a=[0]
*a=0

Birden fazla değerle uyarıcı operatöre bile ihtiyacınız kalmaz (bu konuda beni düzelttiği için histocrat sayesinde):

a=[1,2]
a=1,2

İkinci durum aslında uyarısına ihtiyaç duymaz.
histocrat

@histokrat Oh vay, bu durumda ikinci değerin atılacağını düşündüm.
Martin Ender

1
Bunları Ruby'de golf oynadığım süre boyunca bilmediğime inanamıyorum.
Doorknob

6

Bir meydan okuma çıkış birden çok satır, yapmak zorunda kalmamasıdır gerektirdiğinde döngü mesela bir dizinin her satırı yazdırmak için sonuçları üzerinden. putsYöntem, bir dizi düzleştirmek ve ayrı bir satırda her öğe yazdırılır.

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

Uyarıcı operatörünü #psizinle birleştirmek, onu daha da kısaltabilir:

p *a

Sıçrama operatörü (teknik olarak *@yöntem, sanırım) ayrıca dizi olmayan numaralandırmanızı dizilere aktarır:

> 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

1
*@bir yöntem değildir, uyarısı sözdizimsel şekerdir
Asone Tuhid

6

Bir dizinin yinelenen öğelerini kaldırırken bazı baytları kaydedin

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

[]Bir değişkende boş bir dizi kullanacaksanız , daha fazla bayt kaydedebilirsiniz:

a.uniq;b=[] # before
a|b=[]      # after
      ^^^^^

2
İlk vaka için, a&a1 byte kısadır
Asone Tuhid

5

Ruby'nin kısaltılmış bir versiyonu olan Ruby yerine Goruby kullanın. Rvm ile yükleyebilirsiniz

rvm install goruby

Goruby, kodunuzun çoğunu Ruby'de yazdığınız gibi yazmanıza izin verir, ancak yerleşik olarak ek kısaltmalar vardır. Bir şeyin mevcut en kısa kısaltmasını bulmak shortest_abbreviationiçin, örneğin yardımcı yöntemini kullanabilirsiniz :

shortest_abbreviation :puts
#=> "pts"

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

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

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

Ayrıca çok kullanışlı takma sayiçin putskendisi ile kısaltılmış edilebileceği s. Yani yerine

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

şimdi yazabilirsin

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

alfabeyi büyük harflerle basmak (bu çok iyi bir örnek değildir). Bu blog yazısı , daha fazla okumaya meraklıysanız, daha fazla şey ve içsel çalışmalardan bazılarını açıklar.

PS: hyöntemi kaçırmayın ;-)


Fazla 2 yıl sonra ve nihayet anladım Bu cevap bana neyi hatırlattı ...
undergroundmonorail

5

Bunun yerine bir diziye katılmak için

[...].join

Bunu yap

[...]*''

2 bayt kaydeder. Bir ayırıcı kullanımıyla katılmak için

[...]*?,

5

Abonelik Numaraları!

Bunu daha dün keşfettim. 's biti- pozisyonda n[i]döndürür . Örnek:ni

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

Ve şimdi gibi daha fazla argüman kullanabilirsinizn[0..3]
Simply Beautiful Art

4

2 karakter kaydedebilir ve kullanabilirsiniz.

[*(...)]

onun yerine

(...).to_a

Örneğin, dizi olarak istediğimiz bir aralığımız olduğunu varsayalım:

(1..2000).to_a

Sadece böyle yap:

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

Ve şimdi bir dizi olarak menzile sahipsin.


5
Bence de [*1..2000]çalışır?
Lynn,

4

<< numara

a.push x

kısaltılabilir:

a<<x

-4 bayt için.


2
Not: Bu aynı zamanda Strings
Cyoce

4

Array#assoc/rassoc

Bir dizi diziniz varsa ve belirli bir değerle başlayan alt diziyi bulmak istediğinizde Enumerable#find, kullanmayın Array#assoc:

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

Bu aynı zamanda Enumerable#any?bazı durumlarda iyi bir alternatiftir .

Array#rassoc aynı şeyi yapar, ancak alt dizilerin son öğesini denetler:

a = [[123,"good"],[456,"good"]]
a.any?{|*,x|x=="bad"} # => false
a.rassoc("bad") # => nil

İçin a.any?hat rassoc örneğin, ne yok |x,|do? Nasıl farklı |x|?
Cyoce

@Cyoce Block parametresinin imha edilmesi, imha atamasıyla aynı kuralları takip eder, bu yüzden x=[1,2]vs gibidir x,=[1,2]. Yukarıdaki örneğimi kullanarak |x|, ilk yinelemede xolacak [0,"foo"]. İle |x,y|, xolacak 0ve yolacak "foo". Aynı şekilde, birlikte |x,|, xolacaktır 0. Başka bir deyişle, "ilk elemanı yerleştir xve gerisini
Ürdün

Tersine çalışmadığını unutmayın, örneğin |,y|, bir SyntaxError, ergo |_,y|. Ama şimdi farkettim ki, |*,y|eserler adında bir değişken kullanmaktan daha temiz _(ama daha kısa değil).
Jordan
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.