(未完成)やってみた。麻雀の上がりチェックプログラム
洗濯の合間1時間ほどでできたところまでです。
問題の要件的には未完成で、重複がでる状況があり、コードの最後に書いてあります。
基本のアルゴリズムは簡単です(ただし七対子チェックは入ってません)。
- 全体的には、各通りツモってみて、その14牌で上がりパターンかチェックして、上がってれば出力する
- 上がりチェックは、まず頭の対子をすべて列挙し、各対子に対しそれを除いた12牌で4面子になるか検査する
コードはPythonで、generatorを多用しています。
一番時間かかったのは用語選びでしょうか。呼び方がわからないものもありました:
- 手配+ツモ牌 のことをなんて呼ぶのだろうか
- 面子と対子(や単騎、カンチャン、両面なども)といった組になるものをなんと呼ぶのだろうか
識別子は漢字で書けばよかったかな(とはいえgoogle入力も麻雀用語には強くないようで、読みからは変換できないので大変ですが)。
以下コード:
# -*- coding: utf-8 -*- class Hai(object): def __init__(self, num, tsumo=False): self.num = num self.tsumo = tsumo pass def __eq__(self, other): return self.num == other.num and self.tsumo == other.tsumo pass def main(): tehai_str = raw_input("haipai> ").strip() tehai = parse(tehai_str) tsumo_list = [Hai(i, True) for i in range(1, 10)] # TBD: validate: count of same num <= 4 for tsumo in tsumo_list: tsumotehai = rihai(tehai + [tsumo]) for toitsu, rest in iter_toitsu(tsumotehai): for sumentsu in iter_allmentsu(rest): print(format_tenpai(toitsu, sumentsu)) pass pass pass pass def parse(tehai): if len(tehai) != 13: raise Exception("tehai should be 13 hai") return [Hai(int(tehai[i])) for i in range(len(tehai))] def rihai(tsumo_and_tehai): return sorted(tsumo_and_tehai, lambda a, b: cmp(a.num, b.num)) def iter_toitsu(ritsumo): same = [] for i in range(len(ritsumo) - 1): if ritsumo[i].num == ritsumo[i+1].num: toitsu = ritsumo[i:i+2] rest = ritsumo[:i] + ritsumo[i+2:] if toitsu in same: continue same.append(toitsu) yield (toitsu, rest) pass pass pass def is_juntsu(mentsu): return (mentsu[0].num + 1 == mentsu[1].num and mentsu[0].num + 2 == mentsu[2].num) def is_kotsu(mentsu): return mentsu[0].num == mentsu[1].num == mentsu[2].num def is_mentsu(mentsu): return is_juntsu(mentsu) or is_kotsu(mentsu) def pick1(hailist): for i in range(len(hailist)): yield (hailist[i], hailist[:i] + hailist[i+1:]) pass pass def iter_allmentsu(rest): if len(rest) == 0: yield [] return a = rest[0] r1 = rest[1:] same = [] for b, r2 in pick1(r1): for c, r3 in pick1(r2): mentsu = [a, b, c] if mentsu in same: continue same.append(mentsu) if not is_mentsu(mentsu): continue for allmentsu in iter_allmentsu(r3): yield [mentsu] + allmentsu pass pass pass pass def format_tenpai(toitsu, sumentsu): return (format_group(toitsu) + "".join(format_group(mentsu) for mentsu in sumentsu)) def format_group(group): if any(hai.tsumo for hai in group): return "[%s]" % "".join(str(hai.num) for hai in group if not hai.tsumo) else: return "(%s)" % "".join(str(hai.num) for hai in group) pass if __name__ == "__main__": main() # TODO: unify tamen machi: 1113335557778 makes same two pattern # TODO: unify juntsu/kotsu order: 1111222233339 makes same two pattern but different order
- つづき: 暫定、完成版 - ラシウラ