与えられた文字列をバラバラにして、ランダムに並び替えて出力する Enumerator を返すメソッドというものを考えてみましょう、と思ったのですが…
まずは、愚直に1文字ずつ取り出す仕方を考えると、文字列を配列に変換して、Array#delete_at
を使うかなと。こんな感じ。
random_stream1.rb
def random_stream1(str)
tmp = str.chars
Enumerator.new do |y|
tmp.size.times do
y << tmp.delete_at(rand(tmp.size))
end
end
end
str = "Ruby is smart programming language!"
stream1 = random_stream1(str)
stream1.to_a.join #=>"rlg uin!yaR rsgansbae tugmmamrop ig"
それよりも、便利メソッドArray#shuffle
を使えば、もっと簡単か。せっかくストリームにしているので、改行コードがあったところで切ってみることにしましょう。
random_stream2.rb
def random_stream2(str)
str.chars.shuffle.to_enum
end
str = "Ruby is smart programming language!\n"
stream2 = random_stream2(str)
stream2.to_a.join #=>"gniaasanmoy\n grgietsla p mg!u umrbRr"
stream2.take_while { _1 != "\n" }.join #=>"gniaasanmoy"
でも、メモリ効率を考えて Enumerator を返しているのに、途中で配列に直しているのがどっちもいまいちって感じがするんですよねー… なんかうまい方法はないもんですかねえ。