From: しん <dezawa / aliadne.net>
Subject: [ruby-list:42665] 組み合わせを作るrubyらしい方法
Date: Thu, 10 Aug 2006 12:23:47 +0900

るびきちです。

>  [1,2,3,4].conbination(2)   => [ [1,2],[1,3],[1,4],[2,3],[2,4],[3,4] ]
>  [1,2,3].conbination([4,5]) => [ [1,4],[1,5],[2,4],[2,5],[3,4],[3,5] ]

まず、名前はcombinationですね。
配列が引数の場合は、ペアを求めるという意味でしょうか?
よくわからないので上の場合のみを。

> こんな結果を帰すものを ruby的に作るにはどうしたものでしょうか。

むしろ関数プログラミング的に。
ブロックを使ってるからそういう意味でRuby的なのかも。

class Array
  def flatmap(&block)
    map(&block).inject([]){|x, ret|
      x+ret
    }
  end

  def remove(x)
    dup.delete_if{|y| y==x}
  end

  def combination(n)
    case n
    when  0
      [[]]
    when 1
      map{|x| [x]}
    else
      flatmap{|x|
        remove(x).combination(n-1).map{|ary|
          if x < ary[0]
            [x]+ary
          end
        }.compact
      }
    end
  end

end



require 'test/unit'
class TestCombination < Test::Unit::TestCase
  def test_flatmap
    assert_equal([2,4], [2,4].flatmap{|x| [x]})
    assert_equal([1,2,2,3], [1,2].flatmap{|x| [x, x+1]})
  end

  def test_1
    assert_equal([ [1,2],[1,3],[1,4],[2,3],[2,4],[3,4] ],  [1,2,3,4].combination(2))
  end
end

--
rubikitch
http://www.rubyist.net/~rubikitch/