↓の文を読み、誰が魚を飼っているかを当てて下さい

http://d.hatena.ne.jp/kmizushima/20090629/1246212207 を見て、自分も解いてみたくなったので、rubyのリハビリも兼ねて挑戦してみました。

問題は以下の通り。

それぞれ異なる色の、5つの建物が並んでいます。
それらの家にはそれぞれ出身地の異なる家主が住んでいます。
5人全てが、何か飲み物を飲み、タバコを吸い、ペットを飼っています。
ただし、飲み物の種類、タバコの銘柄、ペットの種類はそれぞれべつべつです。
問題: ↓の文を読み、誰が魚を飼っているかを当てて下さい。
1.日本人は赤い家に住んでいます。
2.アメリカ人は犬を飼っています。
3.中国人はお茶を飲みます。
4.緑の家は白い家の左にあります。
5.緑の家の家主はコーヒーを飲みます。
6.セブンスターを吸う家主は鳥を飼っています。
7.黄色い家の家主はマイルドセブンを吸っています。
8.ちょうど真ん中に位置する家の家主は牛乳を飲みます。
9.イタリア人は一番左の家に住んでいます。
10.マルボロを吸う家主の家のお隣さんは猫を飼っています。
11.馬を飼っている家主の家のお隣さんはマイルドセブンを吸っています。
12.ホープを吸っている家主はビールを飲みます。
13.ブラジル人はラークを吸っています。
14.青い家の隣の家にイタリア人は住んでいます。
15.マルボロを吸う家主の隣の家の家主は水を飲みます。

結局、凄く単純に条件に当てはまる物を列挙しているだけのコードになっちゃいました。しかし、rubyだと便利なメソッドがそろっているので「〜なことがしたいな」と思った時、標準ライブラリにそんなメソッドがあるのが嬉しいですね。
一応、解答は畳んでおきます。

#!/usr/bin/ruby

colors = %w(赤 白 緑 黄 青)
states = %w(日本 アメリカ 中国 イタリア ブラジル)
tabacco = %w(セブンスター マイルドセブン マルボロ ホープ ラーク)
drinks = %w(お茶 コーヒー 牛乳 水 ビール)
pets = %w(犬 鳥 猫 馬 魚)

def create_patterns(colors, states, tabacco, drinks, pets)
  results = []
  # 並び順は配列の順番そのまま
  colors.permutation.each do |c|
    # 4.緑の家は白い家の左にあります。
    next if c[c.index("緑") + 1] != "白"
    
    states.permutation.each do |s|
      # 9.イタリア人は一番左の家に住んでいます。
      next if s.index("イタリア") != 0
      # 1.日本人は赤い家に住んでいます。
      next if c[s.index("日本")] != "赤"
      # 14.青い家の隣の家にイタリア人は住んでいます。
      c_index = c.index("青")
      s_index = s.index("イタリア")
      next if c_index + 1 != s_index and c_index - 1 != s_index
      
      tabacco.permutation.each do |t|
        # 7.黄色い家の家主はマイルドセブンを吸っています。
        next if t[c.index("黄")] != "マイルドセブン"
        # 13.ブラジル人はラークを吸っています。
        next if t[s.index("ブラジル")] != "ラーク"
        
        drinks.permutation.each do |d|
          # 8.ちょうど真ん中に位置する家の家主は牛乳を飲みます。
          next if d.index("牛乳") != 2
          # 3.中国人はお茶を飲みます。
          next if d[s.index("中国")] != "お茶"
          # 5.緑の家の家主はコーヒーを飲みます。
          next if d[c.index("緑")] != "コーヒー"
          # 12.ホープを吸っている家主はビールを飲みます。
          next if d[t.index("ホープ")] != "ビール"
          # 15.マルボロを吸う家主の隣の家の家主は水を飲みます。
          t_index = t.index("マルボロ")
          d_index = d.index("水")
          next if t_index + 1 != d_index and t_index - 1 != d_index
          
          pets.permutation.each do |p|
            # 2.アメリカ人は犬を飼っています。
            next if p[s.index("アメリカ")] != "犬"
            # 6.セブンスターを吸う家主は鳥を飼っています。
            next if p[t.index("セブンスター")] != "鳥"
            # 10.マルボロを吸う家主の家のお隣さんは猫を飼っています。
            t_index = t.index("マルボロ")
            p_index = p.index("猫")
            next if t_index + 1 != p_index and t_index - 1 != p_index
            # 11.馬を飼っている家主の家のお隣さんはマイルドセブンを吸っています。
            t_index = t.index("マイルドセブン")
            p_index = p.index("馬")
            next if t_index + 1 != p_index and t_index - 1 != p_index
            
            results << [c, s, t, d, p]
          end
        end
      end
    end
  end
  results
end

create_patterns(colors, states, tabacco, drinks, pets).each do |pat|
  5.times do |i|
    print pat.map{|p| p[i]}.join(','), "\n"
  end
end