”ごいた”で出現する駒の組合せ数を総当り計算してみた

まず結論

すべての組み合わせは、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枚の駒が取り得るパターン

ごいた (Goita) カードゲーム
数学が苦手なため、簡単なプログラムを書いて、総当り計算で調べた。(確率的に発生しやすいしにくいはあるものの)ひとりに配られる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

usage:

ruby combination.rb | ruby int2moji.rb > pattern.txt

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として利用している。


間違っていたらごめんなさい。