回答:
?d
と?~
1.8で。$><<"string"
は、より短いですprint"string"
。$<.map{|l|...}
は、よりも短くなりwhile l=gets;...;end
ます。また$<.read
、一度にすべてを読むために使用できます。$<
およびgets
ファイル名がである場合、ファイルの代わりに、標準入力から読み込みますARGV
。したがって、再実装cat
するための最もゴルフらしい方法は次のようになります$><<$<.read
。cat
は、ルビーファイルを完全に空のまま(0バイト)にして、-p
フラグ付きのコマンドラインから実行するように主張することです。
puts *$<
☺
または♫
などの思考を使用して、126を超えることができます。または、気が狂った場合:?﷽.ord=65021
スプラット演算子を使用して、配列の末尾と先頭を取得します。
head, *tail = [1,2,3]
head => 1
tail => [2,3]
これは他の方法でも機能します:
*head, tail = [1,2,3]
head => [1,2]
tail => 3
*
配列の文字列を使用してメソッドを使用して、要素を結合します。
[1,2,3]*?,
=> "1,2,3"
abort
プログラムを終了し、STDERRに文字列を印刷する-より短くputs
続きますexit
gets
、それを使用~/$/
してその長さを見つけることができます(これは、存在する場合、末尾の改行をカウントしません)[]
文字列に別の文字列が含まれているかどうかを確認するために使用します。'foo'['f'] #=> 'f'
tr
代わりに使用gsub
:'01011'.tr('01','AB') #=> 'ABABB'
chop
代わりにchomp
abort
andの+1~/$/
~/$/
gets
、その結果が$_
変数に保存されます。 /regex/ ~= string
最初に一致したインデックスを返します。~
正規表現の呼び出しはと同等/regex/ ~= $_
です。だからそれは次のようなものになるだろうs=gets;l= ~/$/
end
。end
コードから削除してみてください。
def...end
関数の定義には使用しないでください。Ruby 1.9の新しい->演算子でラムダを作成します。(->演算子は「stabby lambda」または「dash rocket」です。)これにより、関数ごとに5文字が節約されます。
# 28 characters
def c n
/(\d)\1/=~n.to_s
end
# 23 characters, saves 5
c=->n{/(\d)\1/=~n.to_s}
メソッド呼び出しはc n
またはc(n)
です。ラムダ呼び出しはc[n]
です。それぞれの変更c n
にc[n]
は1文字かかるためc n
、5回以上使用できる場合はメソッドを保持します。
do...end
ブロックを取るすべてのメソッドは、{...}
代わりにブロックを取ることができます。これにより、3〜5文字が節約されます。の優先順位が{...}
高すぎる場合は、括弧を使用して修正します。
# 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','}
交換するif...else...end
と三項演算子 ?:
。ブランチに2つ以上のステートメントがある場合は、括弧で囲みます。
# 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')
あなたはおそらく持っていないwhile
か、until
ループが、あなたがしなければ、その後の修飾形でそれらを書きます。
(a+=1
b-=1)while a<b
puts'statement 3'
必要ですか?
文字列補間を使用している場合(MartinBüttnerの投稿を参照してください)、オブジェクトの前にシギル($
、@
)がある場合、中括弧は必要ありません。以下のような魔法の変数のために有用な$_
、$&
、$1
など:
puts "this program has read #$. lines of input"
したがって、変数を他の方法で使用するよりも多く印刷する必要がある場合も、いくつかのバイトを節約できます。
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"
特定の要素e
が範囲内にあるかどうかを調べる必要がある場合は、r
使用できます
r===e
長い代わりに:
r.cover?(e) # only works if `r.exclude_end?` is false
または
r.member?(e)
または
r.include?(e)
r===e
さらに短くはありませんか?
===
実装されています。
$_
最後に読み取られた行です。
print
-印刷コンテンツの引数が指定されていない場合 $_
~/regexp/
-の略 $_=~/regexp/
Ruby 1.8では、以下Kernel
で動作する4つのメソッドがあります$_
。
chop
chomp
sub
gsub
Ruby 1.9では、これらの4つのメソッドは、スクリプトが-n
またはを使用する場合にのみ存在します-p
。
変数を頻繁に印刷したい場合は、 trace_var(:var_name){|a|p a}
trace_var
グローバルな$ variablesのみで動作するようです
文字列補間を使用してください!
を置き換えるにはto_s
。文字列にしたいものを括弧で囲む必要がある場合to_s
、文字列補間よりも2バイト長くなります。
(n+10**i).to_s
"#{n+10**i}"
連結を置き換える。他の2つの文字列に囲まれたものを連結すると、補間により1バイト節約できます。
"foo"+c+"bar"
"foo#{c}bar"
また、(複数の補間を使用する代わりに)補間内で連結を移動するだけで、中間のもの自体が連結される場合にも機能します。
"foo"+c+d+e+"bar"
"foo#{c+d+e}bar"
length
でif a.length<n
length
6バイトで、コードゴルフでは少しコストがかかります。多くの場合、代わりに、指定されたポイントで配列に何かがあるかどうかを確認できます。最後のインデックスをnil
超えて取得すると、falsey値を取得します。
変更できます:
if a.length<5
以下のif !a[4]
ため-5バイト
または
if a.length>5
以下のif a[5]
ため-6バイト
または
if a.length<n
以下のif !a[n-1]
ため-3バイト
または
if a.length>n
以下のif a[n]
ため-6バイト
注:すべての真理値の配列でのみ機能します。持っnil
またはfalse
アレイ内では、問題が発生することがあります。
size
ます...しかし、これは間違いなく優れています。ところで、String
あまりにも動作します。
キーワードtrue
とfalse
キーワードを使用しないでください。
つかいます:
!p
以下のためtrue
(おかげで、histocrat!)!0
のためにfalse
。必要なのが偽の値だけである場合は、単にp
(を返すnil
)を使用できます。いくつかの文字を保存します。
true
(つまり、if条件のように真実の値で十分な場合)を除いて、必要はありません!!
。
p
(評価されるnil
)はより短いfalsey値です。これは取得するための最短の方法は、意味true
です!p
。
あなたは今までの番号を取得する必要がある場合ARGV
、get
またはその何倍も何かをする似たような、代わりに呼び出すto_i
ことで、あなただけ使用することができ?1.upto x{do something x times}
、xは文字列です。
そのため、の?1.upto(a){}
代わりに使用x.to_i.times{}
すると2文字節約されます。
また、再書き込みできるようなものp 1 while 1
かp 1 if 1
などp 1while 1
またはp 1if 1
この例はあまり有用ではありませんが、他の用途に使用できます。
また、配列の最初の要素を変数に割り当てる必要がある場合は、a,=c
2文字を保存しますが、a=c[0]
あなたのゴルフゲームを支援する新しい言語機能に遅れないようにしておくのは良いことです。最新のルビーにはいくつか素晴らしいものがあります。
&.
返される可能性のあるメソッドを呼び出したnil
が、そうでない場合は追加のメソッド呼び出しをチェーンしたいnil
場合、ケースを処理するバイトを浪費します。
arr = ["zero", "one", "two"]
x = arr[5].size
# => NoMethodError: undefined method `size' for nil:NilClass
x = arr[5].size rescue 0
# => 0
「安全なナビゲーション演算子」は、式全体nil
が返さnil
れ、返される場合、メソッド呼び出しのチェーンを停止します。
x = arr[5]&.size || 0
# => 0
Array#dig
& Hash#dig
ネストされた要素へのディープアクセス、素敵な短い名前:
o = { foo: [{ bar: ["baz", "qux"] }] }
o.dig(:foo, 0, :bar, 1) # => "qux"
nil
行き止まりになったら返します:
o.dig(:foo, 99, :bar, 1) # => nil
Enumerable#grep_v
—の逆はEnumerable#grep
、指定された引数に一致しないすべての要素を返します(と比較===
)。のようgrep
に、ブロックが与えられた場合、その結果が代わりに返されます。
(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
指定されたキーの値を生成するProcを返します。これは非常に便利です。
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はまだリリースされていませんが、まもなくリリースされ、いくつかの素晴らしい機能が追加されます。(リリースされたら、この投稿をドキュメントへのリンクで更新します。)これらのほとんどについては、この素晴らしいブログ投稿で学びました。
Enumerable#sum
これ以上arr.reduce(:+)
。今すぐできますarr.sum
。オプションの初期値引数を取ります。これは、数値要素([].sum == 0
)のデフォルトは0です。他のタイプの場合、初期値を提供する必要があります。また、追加前に各要素に適用されるブロックを受け入れます。
[[1, 10], [2, 20], [3, 30]].sum {|a,b| a + b }
# => 66
Integer#digits
これは、数字の桁の配列を最小から最大の重要度順に返します。
123.digits # => [3, 2, 1]
と比較して、たとえば、123.to_s.chars.map(&:to_i).reverse
これはかなりいいです。
ボーナスとして、オプションの基数引数が必要です。
a = 0x7b.digits(16) # => [11, 7]
a.map{|d|"%x"%d} # => ["b", "7"]
Comparable#clamp
それは錫で言うことをします:
v = 15
v.clamp(10, 20) # => 15
v.clamp(0, 10) # => 10
v.clamp(20, 30) # => 20
Comparableにあるため、Comparableを含む任意のクラスで使用できます。例:
?~.clamp(?A, ?Z) # => "Z"
String#unpack1
上の2バイトの節約.unpack(...)[0]
:
"👻💩".unpack(?U) # => [128123]
"👻💩".unpack(?U)[0] # => 128123
"👻💩".unpack1(?U) # => 128123
Numeric#ceil
、floor
およびtruncate
Math::E.ceil(1) # => 2.8
Math::E.floor(1) # => 2.7
(-Math::E).truncate(1) # => -2.7
これにより、Rubyの以前のバージョンではエラーが発生しますが、2.4では許可されています。
(a,b=1,2) ? "yes" : "no" # => "yes"
(a,b=nil) ? "yes" : "no" # => "no"
Math::E.ceil(1)
へMath::E.ceil 1
、そして同様のためfloor
とtruncate
。
Enumerable#sum
、.flatten.sum
より2バイト短いです.sum{|a,b|a+b}
(-Math::E).truncate(1)
等価である-Math::E.truncate(1)
1バイト短くなっている
&.
このような添字付きで使用できますa&.[]i
(より1バイト短いa&.at i
)。ブラケットが必要な場合は、もののa||a[i]
1つのバイトがより短くなっているa&.[](i)
かa&.at(i)
あなたが表現したいとしましょうa*(b+c)
。優先順位のため、a*b+c
動作しません(明らかに)。メソッドとして演算子を使用するRubyのクールな方法が役に立ちます!を使用a.*b+c
して、の優先順位をの優先順位より*
低くすることができます+
。
a*(b+c) # too long
a*b+c # wrong
a.*b+c # 1 byte saved!
また、これはで動作することができます!
し、~
(単項のようなものオペレータ+
または単項-
それらのメソッドであるため動作しない-@
と+@
省電力、()
しかし追加.@
)
(~x).to_s # too long
~x.to_s # error
x.~.to_s # 1 byte saved!
||
代わりにor
、&&
代わりに使用しますand
。
1文字の横に、and
演算子の周りのスペース(およびおそらくブラケット)を保存できます。
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
配列でループする場合、通常はを使用しますeach
。しかしmap
、配列もループし、1文字短くなります。
私はちょうどTDDコードゴルフの挑戦を試みました。すなわち、仕様を通過させるために最短のコードを書いてください。仕様は次のようなものでした
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
コードゴルフのために、モジュールやクラスを作成する必要はありません。
の代わりに
module PigLatin def self.translate s;'some code'end;end
できること
def(PigLatin=p).translate s;'some code'end
13文字を節約します!
PigLatin
、ほかに@pig_latin
、$pig_latin
と'pig'['latin']
。
translate
定義されているためnil
です。
カーネル#pは楽しいメソッドです。
p var
代わりに使用puts var
。これは整数と浮動小数点数で完全に機能しますが、すべての型では機能しません。文字列の周りに引用符を印刷しますが、これはおそらくあなたが望むものではありません。
単一の引数で使用され、 p
印刷後に返します。
複数の引数で使用され、 p
、引数を配列返します。
のp
代わりに(引数なし)を使用しnil
ます。
p 'some string'
印刷します。"some string"
some string
p s
はと同じですが、puts s.inspect
戻りますs
#eachを使用しないでください。#mapを使用すると、すべての要素を適切にループできます。の代わりに
ARGV.each{|x|puts x}
少ないバイトで同じことができます。
ARGV.map{|x|puts x}
もちろん、この場合puts $*
はさらに短くなります。
有理数と複素数のリテラルがあります:
puts 3/11r == Rational(3,11)
puts 3.3r == Rational(66,20)
puts 1-1.i == Complex(1,-1)
=> true
true
true
文字列内のほとんどのバイトを使用できます。"\x01"
(6バイト)は""
(3バイト)に短縮できます。この1バイトだけが必要な場合は、これをさらに短くすることができます。?
(2バイト)に。
同様に、次のように改行を短くすることができます。
(0..10).to_a.join'
'
=> "0\n1\n2\n3\n4\n5\n6\n7\n8\n9\n10"
あなたは使用することができます?\n
し、?\t
より短い1バイトであるだけでなく"\n"
"\t"
。 andなります。難読化のために、スペースもありますか?
引数を変更する必要がある場合でも、引数を渡す代わりに定数を使用します。インタープリターはstderrに警告を出しますにが、誰が気にします。互いに関連する変数をさらに定義する必要がある場合は、次のように連鎖させることができます。
A=C+B=7+C=9
=> A=17, B=16, C=9
これは C=9;B=16;A=17
かC=0;B=C+7;A=C+B
。
無限ループが必要な場合は、を使用しますloop{...}
。未知の長さのループは、他のループでは短くなる場合があります。
loop{break if'
'==f(gets)}
while'
'!=f(gets);end
いくつかのgsub / regexpトリック。'\1'
ブロックの代わりに特別なエスケープ文字を使用します。
"golf=great short=awesome".gsub(/(\w+)=(\w+)/,'(\1~>\2)')
"golf=great short=awesome".gsub(/(\w+)=(\w+)/){"(#{$1}~>#{$2})")
また、$1
操作を実行する必要がある場合は、特殊変数など。ブロック内だけでなく、それらも定義されていることに注意してください。
"A code-golf challenge." =~ /(\w+)-(\w+)/
p [$1,$2,$`,$']
=> ["code", "golf", "A ", " challenge."]
スペース、改行、括弧を削除します。ルビーではかなり省略できます。疑わしい場合は、それがなくても機能するかどうかを常に試してください。これにより、エディターの構文の強調表示が壊れる可能性があります...
x+=1if$*<<A==????::??==??
?\n
いいですが、実際に引用符の中に改行文字を入れるよりも短くありません。(タブと同じ)
puts$*
さらに短いです。
x+=1;$*<<A
splat演算子を使用するさらに別の方法:単一の配列リテラルを割り当てたい場合*
、左側のa は右側の括弧よりも短くなります。
a=[0]
*a=0
複数の値を使用すると、スプラット演算子さえ必要ありません(それについて修正してくれたhistocratに感謝します):
a=[1,2]
a=1,2
チャレンジで複数行を出力する必要がある場合、たとえば配列の各行を印刷するために結果をループする必要はありません。このputs
メソッドは配列を平坦化し、各要素を別々の行に出力します。
> a = %w(testing one two three)
> puts a
testing
one
two
three
スプラット演算子を組み合わせると、#p
さらに短くすることができます。
p *a
スプラット演算子(技術的には*@
メソッドだと思います)は、配列でない列挙型も配列にキャストします。
> p a.lazy.map{|x|x*2}
#<Enumerator::Lazy: #<Enumerator::Lazy: [1, 2, 3]>:map>
対
> p *a.lazy.map{|x|x*2}
2
4
6
*@
スプラットは糖衣構文では、この方法ではありません
a.uniq # before
a|[] # after
^^
[]
変数で空の配列を使用する場合、さらに多くのバイトを保存できます。
a.uniq;b=[] # before
a|b=[] # after
^^^^^
a&a
1バイトの短い
Rubyの代わりにGorubyを使用します。これはRubyの短縮バージョンのようなものです。rvmでインストールできます
rvm install goruby
Gorubyあなたはルビーを書くことになるとあなたのコードのほとんどを書くことができますが、内蔵の追加の略語を持っているもののために利用可能な最短の省略形を見つけるために、あなたはヘルパーメソッドを使用することができます。shortest_abbreviation
例えば、:
shortest_abbreviation :puts
#=> "pts"
Array.new.shortest_abbreviation :map
#=> "m"
String.new.shortest_abbreviation :capitalize
#=> "cp"
Array.new.shortest_abbreviation :join
#=> "j"
また、非常に便利なエイリアスはsay
、puts
それ自体をで短縮することができますs
。の代わりに
puts [*?a..?z].map(&:capitalize).join
あなたは今書くことができます
s [*?a..?z].m(&:cp).j
アルファベットを大文字で印刷します(これは非常に良い例ではありません)。このブログ投稿では、さらに読みたい場合は、より多くのものと内部の動作について説明しています。
PS:h
メソッドをお見逃しなく;;)
昨日これを発見しました。-番目の位置にのビットをn[i]
返します。例:n
i
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
Array#assoc
/rassoc
配列の配列があり、特定の値で始まるサブ配列を検索する場合はEnumerable#find
、使用しないでくださいArray#assoc
:
a = [[0,"foo"],[0,"bar"],[1,"baz"],[0,"qux"]]
a.find{|x,|x==1} # => [1,"baz"]
a.assoc(1) # => [1,"baz"]
これは、Enumerable#any?
状況によっては適切な代替品です。
Array#rassoc
同じことをしますが、サブ配列の最後の要素をチェックします:
a = [[123,"good"],[456,"good"]]
a.any?{|*,x|x=="bad"} # => false
a.rassoc("bad") # => nil
a.any?
行のrassoc
場合、何をし|x,|
ますか?とはどう違い|x|
ますか?
x=[1,2]
vs のようになりx,=[1,2]
ます。上記の私の例を使用すると|x|
、最初の反復でx
はになります[0,"foo"]
。で|x,y|
、x
で0
あり、でy
ある"foo"
。同様に、と|x,|
はにx
なります0
。言い換えれば、「最初の要素を入れてx
、残りを捨てる。」
|,y|
、SyntaxError、ergo |_,y|
です。しかし、私はたった今|*,y|
それが動作することに気づきました。これは名前の付いた変数を使用するよりも簡潔です_
(ただし短縮されません)。