まず結論
すべての組み合わせは、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として利用している。
間違っていたらごめんなさい。