こんな感じで。
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
こう書いておけばメモリリークは起きない。
最近のコメント