麻雀って何ぞ!?

面白そうな記事を見つけたのでPythonの勉強がてらやってみた。

あなたのスキルで飯は食えるか? 史上最大のコーディングスキル判定
http://www.itmedia.co.jp/enterprise/articles/1004/03/news002.html

制限時間3時間とあるが何とか2時間半くらいで出来た。Pythonの構文とかググったりしたので習熟した言語でやれば2時間くらいか。Pythonの勉強なので、出来るだけPythonの機能(set)とかを使ってみました。でも出力フォーマットとか整えていなかったり、明らかにリファクタリングできる所があったりするけど・・・。なんていうか飽きたんだよ(-_-)許して下さい。

以下ソースコード(手抜き)です。

result_list = []

def get_shuntsu(x, tehai):
    if x in tehai and x + 1 in tehai and x + 2 in tehai :
        work_tehai = list(tehai)
        work_tehai.remove(x)
        work_tehai.remove(x + 1)
        work_tehai.remove(x + 2)
        return [x, x + 1, x + 2], list(work_tehai)
    else :
        return [], list(tehai)

def get_kotsu(x, tehai):
    if tehai.count(x) >= 3 :
        work_tehai = list(tehai)
        [work_tehai.remove(y) for y in (x, x, x)]
        return [x, x, x], list(work_tehai)
    else :
        return [], list(tehai)

def make_mentsu(tehai, fixed_tehai):
    for x in tehai :
        mentsu, amari = get_shuntsu(x, tehai)
        if mentsu :
            if len(amari) == 1 :
                result_list.append(fixed_tehai + [mentsu, amari, (amari[0],)])
                return
            if len(amari) == 2 :
                if amari[1] - amari[0] == 0 :
                    result_list.append(fixed_tehai + [mentsu, amari, (fixed_tehai[0][0], amari[0])])
                elif amari[1] - amari[0] == 1 :
                    machi = []
                    if amari[0] > 1 :
                        machi.append(amari[0] - 1)
                    if amari[1] < 9 :
                        machi.append(amari[1] + 1)
                    result_list.append(fixed_tehai + [mentsu, amari, tuple(machi)])
                elif amari[1] - amari[0] == 2 :
                    result_list.append(fixed_tehai + [mentsu, amari, (amari[0] + 1,)])
                return
            
            make_mentsu(amari, fixed_tehai + [mentsu])
        
        mentsu, amari = get_kotsu(x, tehai)
        if mentsu :
            if len(amari) == 1 :
                result_list.append(fixed_tehai + [mentsu, amari, (amari[0],)])
                return
            if len(amari) == 2 :
                if amari[1] - amari[0] == 0 :
                    result_list.append(fixed_tehai + [mentsu, amari, (fixed_tehai[0][0], amari[0])])
                elif amari[1] - amari[0] == 1 :
                    machi = []
                    if amari[0] > 1 :
                        machi.append(amari[0] - 1)
                    if amari[1] < 9 :
                        machi.append(amari[1] + 1)
                    result_list.append(fixed_tehai + [mentsu, amari, tuple(machi)])
                elif amari[1] - amari[0] == 2 :
                    result_list.append(fixed_tehai + [mentsu, amari, (amari[0] + 1,)])
                return
            
            make_mentsu(amari, fixed_tehai + [mentsu])

if __name__ == "__main__" :
    tehai = [1, 1, 1, 2, 3, 4, 5, 6, 7, 8, 9, 9, 9]
    tehai.sort()
    
    for x in tehai :
        if tehai.count(x) > 1 :
            work_tehai = list(tehai)
            [work_tehai.remove(y) for y in (x, x)]
            make_mentsu(work_tehai, [[x, x]])
        
        make_mentsu(tehai, [])
    
    [result.sort() for result in result_list]
    result_set = set([repr(result) for result in result_list])
    for result in result_set :
        print result

出力結果こんな感じ。マンズ(1-9)、ソーズ(101-109)、ピンズ(201-209)、字牌(適当にバラバラ)のようにデータを定義すればマンズ以外にも対応出来そう。

[[1, 1, 1], [2, 3], [4, 5, 6], [7, 8, 9], [9, 9], (1, 4)]
[[1, 1, 1], [2, 3, 4], [5, 6, 7], [8], [9, 9, 9], (8,)]
[[1, 1], [1, 2, 3], [4, 5], [6, 7, 8], [9, 9, 9], (3, 6)]
[[1, 1, 1], [2, 3, 4], [5, 6], [7, 8, 9], [9, 9], (4, 7)]
[[1, 1, 1], [2], [3, 4, 5], [6, 7, 8], [9, 9, 9], (2,)]
[[1, 1, 1], [2, 3, 4], [5, 6, 7], [8, 9], [9, 9], (7,)]
[[1, 1], [1, 2, 3], [4, 5, 6], [7, 8, 9], [9, 9], (9, 1)]
[[1, 1], [1, 2], [3, 4, 5], [6, 7, 8], [9, 9, 9], (3,)]
[[1, 1, 1], [2, 3, 4], [5], [6, 7, 8], [9, 9, 9], (5,)]
[[1, 1], [1, 2, 3], [4, 5, 6], [7, 8], [9, 9, 9], (6, 9)]
[[1, 1], [1, 2, 3], [4, 5, 6], [7, 8, 9], [9, 9], (1, 9)]