”ごいた”で出現する駒の組合せ数を総当り計算してみた
まず結論
すべての組み合わせは、pastebinを見て欲しい。http://pastebin.com/861HSAVH
はじめに
単純に組合せを計算すると、駒が32枚あって4人に8枚ずつ配るので、
32C8 x 24C8 x 16C8
= 10,518,300 x 735,471 x 12,870
= 9.9561092e+16 = 約1京
と、約1京パターンが発生してしまう。
しかし実際には、
- 王と玉は同じ駒とみなしてよい
- 同じ種類の駒が複数ある(王2枚、飛2枚、角2枚、金4枚、銀4枚、馬4枚、香4枚、歩10枚)。それぞれ同じ種類の駒は同じ駒としてみなしてよい
- 歩は10枚だが、ひとりあたりは最大8枚までしか配られない
という制約が成り立つ。この制約をもとに、ごいたで出現する駒のパターンが何通りあるか計算してみよう。
ひとりの打ち手に配られる8枚の駒が取り得るパターン
数学が苦手なため、簡単なプログラムを書いて、総当り計算で調べた。(確率的に発生しやすいしにくいはあるものの)ひとりに配られる8枚の駒のパターンは3,699になる。ちなみに5歩以上になるケースはこのうち117ある(5歩は81、6歩は28、7歩は7、8歩は1)。
code:
# combination.rb DAMA = 1 HISHA = 2 KAKU = 3 KIN = 4 GIN = 5 BAKKO = 6 GON = 7 SHI = 8 KOMA = [ [DAMA]*2, [HISHA]*2, [KAKU]*2, [KIN]*4, [GIN]*4, [BAKKO]*4, [GON]*4, [SHI]*8].flatten KOMA.combination(8).to_a.uniq.each{|a| puts a.join}
# int2moji.rb MOJI = [" ", "王", "飛", "角", "金", "銀", "馬", "香", "歩"] fu = Array.new(9, 0) while gets k = $_.chomp.split("").map{|s| MOJI[s.to_i]} printf("%04d,%s\n", $., k.join(",")) fu[k.count("歩")] += 1 end STDERR.puts fu
all patterns:
結果はpastebinに貼っときます。http://pastebin.com/B3j5vcy5
2人の打ち手に配られる16枚の駒が取り得るパターン
さらに、ペアの2人分の16枚の駒のパターンは4,126,296になる。
# combination2.rb < pattern.txt DAMA = 1 HISHA = 2 KAKU = 3 KIN = 4 GIN = 5 BAKKO = 6 GON = 7 SHI = 8 KOMA = [ [DAMA]*2, [HISHA]*2, [KAKU]*2, [KIN]*4, [GIN]*4, [BAKKO]*4, [GON]*4, [SHI]*10 ].flatten koma = [] while gets koma.push $_.chomp.split("").map{|s| s.to_i} end n = 0 koma.each_index do |i| rest = KOMA.clone koma[i].each{|j| rest.delete_at(rest.index(j))} koma.each_index do |j| if koma[j].uniq.all? { |k| rest.count(k) >= koma[j].count(k) } puts koma[i].join+koma[j].join n += 1 end end STDERR.printf("%d %d\n", i, n) end
なお、処理の高速化のためにcombination.rbの出力をpattern.txtとして利用している。
4人全員の打ち手に配られる32枚の駒が取り得るパターン
さらにさらに、敵味方合わせて4人全員の駒のパターンの数も計算したところ、803,872,134となる。1京に比べれば少ないとはいえ、8億か..。
DAMA = 1 HISHA = 2 KAKU = 3 KIN = 4 GIN = 5 BAKKO = 6 GON = 7 SHI = 8 KOMA = [ [DAMA]*2, [HISHA]*2, [KAKU]*2, [KIN]*4, [GIN]*4, [BAKKO]*4, [GON]*4, [SHI]*10 ].flatten koma = [] f = File.open("pattern.txt", "r") while f.gets koma.push $_.chomp.split("").map{|s| s.to_i} end n = 0 f = File.open("pattern2.txt", "r") while f.gets koma2 = $_.chomp.split("").map{|s| s.to_i} rest = KOMA.clone koma2.each{|i| rest.delete_at(rest.index(i))} koma.each do |k| if k.uniq.all? { |i| rest.count(i) >= k.count(i) } #puts koma2.join+k.join n += 1 end end STDERR.printf("%d %d\n", $., n) end
なお、処理の高速化のためにcombination.rbの出力をpattern.txt、combination2.rbの出力をpattern2.txtとして利用している。
間違っていたらごめんなさい。