久しぶりにrubyで遊ぶ
ruby1.9便利
require 'enumerator'がいらなくて済むし、to_enumとかもいらない。
# 行番号付きprint def print_with_number io io.each_line.with_index{ |x,i| puts("#{i}:#{x}")} end print_with_number("test\nfoo\nbar") # 0:test # 1:foo # 2:bar # deep-reverse class Array def deep_reverse self.reverse_each.map{ |e| (e.respond_to?(:map)? e.deep_reverse : e)} end end a = [1,2,[3,[4]],[5,[6,[7,8]]],9] a.deep_reverse # => [9, [[[8, 7], 6], 5], [[4], 3], 2, 1] # split evens and odds class Array def mypartition self.inject([[],[]]) { |re,x| ((yield(x))? re[0] : re[1]).push(x); re} end end (1..10).to_a.mypartition{ |x| x % 2 == 1} # => [[1, 3, 5, 7, 9], [2, 4, 6, 8, 10]] # cross-product def cross_product(*args) if args.length == 1 args.first.map{ |x| [x]} else cross_product(*args[1..-1]).inject([]) do |re,xs| re.concat args.first.map{ |y| [y,*xs]} end end end cross_product(%w{x y z },[1,2,3], %w{ a b c}) # => [["x", 1, "a"], ["y", 1, "a"], ["z", 1, "a"], ["x", 2, "a"], ["y", 2, "a"], ["z", 2, "a"], ["x", 3, "a"], ["y", 3, "a"], ["z", 3, "a"], ["x", 1, "b"], ["y", 1, "b"], ["z", 1, "b"], ["x", 2, "b"], ["y", 2, "b"], ["z", 2, "b"], ["x", 3, "b"], ["y", 3, "b"], ["z", 3, "b"], ["x", 1, "c"], ["y", 1, "c"], ["z", 1, "c"], ["x", 2, "c"], ["y", 2, "c"], ["z", 2, "c"], ["x", 3, "c"], ["y", 3, "c"], ["z", 3, "c"]] # powerset def powerset(s) if s.empty? [[]] else child, x = powerset(s[1..-1]), s.first child.concat(child.map{ |y| [x,*y]}) end end powerset([1,2,3]) # => [[], [3], [2], [2, 3], [1], [1, 3], [1, 2], [1, 2, 3]] # permutation def permutation(arr, n) if n == 1 arr.map{ |x| [x]} else arr.inject([]) do |re,x| re.concat( permutation(arr.reject{ |y| x == y},n-1).map{ |ys| [x,*ys]}) end end end permutation([1,2,3,4],2) # => [[1, 2], [1, 3], [1, 4], [2, 1], [2, 3], [2, 4], [3, 1], [3, 2], [3, 4], [4, 1], [4, 2], [4, 3]] arr = (1..6).to_a permutation(a,2) == a.permutation(2).map{ |e| e} # => true def combination(arr, n) case when arr.nil? then [] when n == 1 then arr.map{ |x| [x]} else arr.dup.inject([]) do |re,x| re.concat( combination(arr.reject!{ |y| x == y},n-1).map{ |ys| [x,*ys]}) end end end arr = (1..6).to_a combination(arr.dup,3) # => [[1, 2, 3], [1, 2, 4], [1, 2, 5], [1, 2, 6], [1, 3, 4], [1, 3, 5], [1, 3, 6], [1, 4, 5], [1, 4, 6], [1, 5, 6]] combination(arr.dup,2) == arr.combination(2).map{ |e| e} # => true
combination,permutation,partitionはEnumerableのmethodの中にあるので、defaultで使える。
combinationは、元のArrayを破壊してしまうからあまり綺麗じゃないかもしれない。