こんな感じで。
def perm(arry)
return [arry] if arry.size <= 1
ret = []
beg = arry[0]
rest = perm(arry[1..-1])
rest.each{|a|
ret << [beg] + a
a.size.times{|i|
ret << a[0..i] + [beg] + a[i+1..-1]
}
}
return ret
end
p perm( [:a, :b, :c] )
もっと長い配列をちかんしたい場合。
class Permutation
def initialize(ary)
if ary.size <= 1
@buf = [ary]
else
@buf = []
@beg = ary[0]
@rest = Permutation.new(ary[1..-1])
fill_buf()
end
end
def fill_buf
return @buf if @buf.size > 0
if @rest and a = @rest.perm
@buf << [@beg] + a
a.size.times{|i|
@buf << a[0..i] + [@beg] + a[i+1..-1]
}
return @buf
else
return nil
end
end
def perm
ret = @buf.pop
if ret
return ret
else
if fill_buf()
return @buf.pop
else
return nil
end
end
end
end
perm = Permutation.new((1..100).to_a)
6.times{
p perm.perm
}
ふと思いついて Zlib のメモリーリークを直してみようと思った。けど、どうやったらいいか良く分からなかった。ruby の例外は C 言語の longjump で実装されている。C++ と違って C 言語にはスタックを巻き戻す時にデストラクタを実行するような仕組みがないので、人が管理しないといけない。どこら辺で例外が起きたことを検知してメモリを解放するコードを書いたらいいかはコードの全体を把握していないといけない。でもまあ、ext/zlib/zlib.c の全体なんて知るわけないし。
なんで C 言語には GC がないんだろう。
とか思っていたら解決法を思いついた。C 言語で頑張らずに Ruby のコードで書けば良いのだ。
require 'zlib'
module Zlib
class Inflate
def self.inflate(string)
zstream = self.new
buf = zstream.inflate(string)
zstream.finish
zstream.close
buf
end
end
end
こう書いておけばメモリリークは起きない。
最近のコメント