麻雀の和了判定
麻雀の和了
久しぶりの記事です.今年は麻雀について頑張るぞということで麻雀のプログラミングをしたいと思います.
七対子や国士無双を除いた一般形の和了を考えます.よくあるプログラムでは刻子や順子の抜き出し方のパターンを考えて再帰的な手法で和了判定を行います.
この記事では,左から刻子,順子の順で面子分解を行うことで和了判定を行っています.なので非常に高速に行うことができます.
アルゴリズムの正当性を競技プログラミングの問題で確認します.
a = [0] * 9 s = list(map(int, input())) tot = sum(s) - 13 for i in s: a[i - 1] += 1 def seven_pairs(a): cnt = 0 for i in range(9): if a[i] == 2: cnt += 1 return cnt == 7 def can_decomp(p): k1 = 0 k2 = 0 for i in range(7): if p[i] - k1 - k2 < 0: return False k0 = (p[i] - k1 - k2) % 3 if p[i+1] - k0 - k1 < 0 or p[i+2] - k0 < 0: return False k2 = k1 k1 = k0 if (p[7] - k1 - k2) % 3 != 0 or (p[8] - k1) % 3 != 0: return False return True def check(p): for i in range((tot % 3) * 2 % 3, 9, 3): if p[i] >= 2: p[i] -= 2 if can_decomp(p): p[i] += 2 return True p[i] += 2 return False for i in range(9): if a[i] == 4: continue a[i] += 1 tot += i if seven_pairs(a): print(i + 1) elif check(a): print(i + 1) a[i] -= 1 tot -= i