この記事は Ruby Advent Calendar 2016の20日目の記事のつもりで書いている。
Advent Calendar というものに参加するのは初めてなので緊張している。
実務ではあまり ruby を使っていないので、私は自分が主催しているどう書く( https://yhpg.doorkeeper.jp/ )での ruby の使われ方を書こうと思う。
思いついた順なので、ごちゃごちゃするけど気にしない方向で。
Array#transpose
行列ではないものをtranspose
できる言語が他にあるかどうか知らないんだけど、transpose
は便利。
x方向で処理するプログラムだけを用意しておいて、y方向の処理は、データを transpose したものを渡すことで済ますとか。
あるいは、平面的なものを回転するときに役に立つ。
2次元配列をreverse
してからtranspose
すると時計回りに、transpose
してからreverse
すると反時計回りに回せる。
Object#tap〜break
メソッドチェインをしていくなかで、パスしていくオブジェクトを $x$ から $f(x)$ に変更したい場合に使う。
foo.略{略}.略{略}.tap{ |x| break f(x) }.略{略}
のような感じ。
標準で存在して然るべきメソッドだと思う。
Integer#divmod
除算の結果の商と剰余がいっぺんに手に入る。
123.divmod(100) #=> [1, 23]
一次元的に表現された平面から座標を取るときに活躍する。
配列でもらえるので、そのままメソッドチェインに流し込んだりするのも便利。
Array#minmax
min と max がいっぺんに手に入る。
"helloworld".chars.minmax # => ["d", "w"]
こんな感じ。
これもそのままメソッドチェインに流すことが出来る。便利。
String#ord Integer#chr
"a"〜"z" を 0〜25 などに変換する必要がある場面は多いので、n=c.ord-?a.ord
のような計算はよく出てくる。
逆変換は、c=(n+?a.ord).chr
。
Integer#[ ]
Integer
には123[4]
のように呼べるメソッドがあって、トラブルの原因になりやすいような気もするけど、ビット演算が簡単にできるのはとても便利。
先の例は、( (123 & (1<<4))==0 )? 0 : 1
と同じなので、
123[4] # => 1
ちなみに、Integer#[ ]=
はない。
Array#& と Array#|
[1,1,2,3,4,4] & [3,4,4,5] # => [3, 4]
[1,1,2,3,4,4] | [3,4,4,5] # => [1, 2, 3, 4, 5]
のように、Array#uniq
の処理を含んでいることに注意。というか、そこもわかっていると便利。
Math.log2 と Math.cbrt
Math.log2 は、 $\frac{\ln(x)}{\ln(2)}$ の計算をする。何に使うのかというと、場合の数。
なので、Math.log2(x).ceil
のような感じで、ceil
やfloor
とセットで使うと思う。
Math.log(x)/Math.log(2)
のような計算と違って、誤差が出にくい。
Math.log(2**29)/Math.log(2) #=> 29.000000000000004
Math.log2(2**29) #=> 29.0
そういえば、三乗根の Math.cbrt
が便利だったこともある:
64**(1.0/3) # => 3.9999999999999996
Math.cbrt(64) #=> 4.0
こちらも誤差が出にくい。
オープンクラスの悪用
たとえば、平面上の座標を配列で表現しようと思うとする。
そんなとき、
class Array
def x; self[0]; end
def y; self[1]; end
end
のような悪用をすると結構便利。仕事だと許されないと思うけど、どう書くならアリだと思う。
Array#combination と仲間たち
Array
には、combination
, permutation
, repeated_combination
, repeated_permutation
という4つの便利メソッドがある。
それぞれ名前のとおりなんだけど、実行結果は以下の通り:
[1,2,3].combination(2).to_a
#=> [[1, 2], [1, 3], [2, 3]]
[1,2,3].permutation(2).to_a
#=> [[1, 2], [1, 3], [2, 1], [2, 3], [3, 1], [3, 2]]
[1,2,3].repeated_combination(2).to_a
#=> [[1, 1], [1, 2], [1, 3], [2, 2], [2, 3], [3, 3]]
[1,2,3].repeated_permutation(2).to_a
#=> [[1, 1], [1, 2], [1, 3], [2, 1], [2, 2], [2, 3], [3, 1], [3, 2], [3, 3]]
実際に書こうとすると再帰だったりして面倒になるので、これがあるのは本当に助かる。というか、出題者としては困るぐらい便利。
【宣伝】
現在、私が主催するオフラインリアルタイムどう書くでは
の参加者を募集しています。