ヤマカサのプログラミング勉強日記

プログラミングに関する日記とどうでもよい雑記からなるブログです。

向聴数の計算1

向聴数

向聴数とは聴牌に必要な数ですが,ここでは向聴数を求めるために手牌と手牌の距離という概念を用います.基本的にはこの記事の方針でやります.

[麻雀]シャンテン数計算アルゴリズム - Qiita

手牌の表現

麻雀牌は34種あるので長さが34の配列  h を用いて手牌を表現します.萬子は0から8,筒子は9から17,索子は18から26,字牌は27から33として番号を割り当てます.例えば, h_{1} = 2 のとき,手牌に2mが2つあるとします.

手牌と手牌の距離

手牌  f と手牌  g の距離を  d(f, g) として

 d(f, g) = \displaystyle \sum_{i=0}^{33} |f_{i} - g_{i}|

とします.

和了形と手牌の距離

向聴数を求めるには全ての和了形の集合  \boldsymbol{W} に対して,手牌  g との距離の最小値を  t(g) とすると,

  t(g) = \displaystyle \min_{w \in \boldsymbol{W}} d(w, g)

と表現できます.全ての和了形に対して,愚直に  t(g) を求めることは効率が悪いので小問題に分割して考えます.

1色手における手牌と和了形の距離

和了形におけるある色の数

和了形においてある色の数は,

 0, 2, 3, 5, 6, 8, 9, 11, 12, 14

 10 通りあります.この数を  n とすると, n \bmod 3 = 0 のとき面子分解可能であり, n \bmod 3 = 2 のとき面子分解可能かつ雀頭が存在することになります.

和了形における手牌のパターンと手牌の距離

和了形においてある色の数の集合を \boldsymbol{N}

 \boldsymbol{N} = \{0, 2, 3, 5, 6, 8, 9, 11, 12, 14\}

とします.ここで,和了形におけるある色のパターンの集合を  \boldsymbol{W}_{n} (n \in \boldsymbol{N}) とします.一色手における手牌を  g として, \boldsymbol{W}_{n} g の最小値を   t_{n}(g) とすると,

  t_{n}(g) = \displaystyle \min_{w \in \boldsymbol{W}_{n}}  d(w, g)

となります.

 14 枚における一色手のパターンは, 118800 通りあり, \boldsymbol{W}_{14} の数は  13277 通りなので,愚直に   t_{n}(g) を求めることができます.実際に動かしてみると2分もかからないくらいでした.これらをテーブルとして保存して向聴数を求めます.

一般手における和了形と手牌の距離

萬子,筒子,索子,字牌の枚数を  i, j, k, l とし,その手牌を  g_m, g_p, g_s. g_z とします.ここで,手牌  g g = \{ g_m, g_p, g_s, g_z\} です.また,ある和了形における萬子,筒子,索子,字牌の枚数を  n_m, n_p, n_s, n_z としその集合を  \boldsymbol{N} とすると,

  t(g) = \displaystyle \min_{\{ n_m, n_p, n_s, n_z\} \in \boldsymbol{N}} ( t_{n_{m}}(g_{m}) +  t_{n_{p}}(g_{p}) +  t_{n_{s}}(g_{s})  +  t_{n_{z}}(g_{z}) )

と計算できます.注意として,数牌と字牌は別にして求める必要があります.  \boldsymbol{N} の大きさは  140 なので高速に向聴数を求めることができます.