LoginSignup
1
1

More than 5 years have passed since last update.

yhpg05 - 大貧民 をPythonで解いてみる

Last updated at Posted at 2017-07-19

http://nabetani.sakura.ne.jp/hena/ord5dahimi/
で出題された大貧民をPythonで解くことに挑戦してみる。

もう、どうしようという感じでテストコードが通らないまま投稿してしまう。
多分、目視では正解していると思うのですが。

出せる手札の組み合わせを計算するのにitertoolsを使ってみた。
計算した組み合わせの中から出せる手札を探して回る作戦。

複数枚手札を出す場合の結果と期待値が同じ並びにならないので、テストコードが通らない。
結果の比較の仕方をもっと工夫しないとうまくいかない。ぐぬぬ。

2017/7/23追記
コメントいただいた内容を参考に、テストコードを通るように修正。
同じランクが出せていたバグを発見したので、こっそり修正。 test("C7H7,S7CTH8D5HACQS8JoD6SJS5H4", "HAJo,JoSJ,H8S8,H8Jo,CQJo,CTJo,JoS8" );
でC7Joも出せる手札に加わっていた。

yhpg05.py
#!/usr/bin/env python3
# -*- coding:utf-8 -*-

# https://yhpg.doorkeeper.jp/
# http://nabetani.sakura.ne.jp/hena/ord5dahimi/

import itertools

#数値の大小で求められるように都合よく変換する
converter = {
    "3":0,
    "4":1,
    "5":2,
    "6":3,
    "7":4,
    "8":5,
    "9":6,
    "T":7,
    "J":8,
    "Q":9,
    "K":10,
    "A":11,
    "2":12,
    "o":13
}

def solve(data):
    data = data.split(",")
    field = list(sorted([data[0][i: i+2] for i in range(0, len(data[0]), 2)]))
    hands = [data[1][i: i+2] for i in range(0, len(data[1]), 2)]
    # 手札にあるカードで場に出ている枚数を出す場合の組み合わせを作っておく
    hands = list(sorted(itertools.combinations(hands,len(field))))

    # 出せる手札が1枚もない場合は終わり
    if len(hands) == 0:
        return list("-")

    result = []
    if len(field) == 1:
        #場が1枚だけカードが出ている
        for hand in hands:
            if isAvailableCard(field[0][1:2], hand[0][1:2]):
                result.append(hand[0])
    else:
        #場に2枚以上カードが出ている
        #場の値がいくつなのか取得する
        num = getFieldNum(field)
        #手札から出せるカードを調べる
        temp = []
        temp.append(getAvailableCards(num,hands))
        temp = temp[0]
        for card in temp:
            result.append("".join(card))

    if len(result) == 0:
        return list("-")
    else:
        return result

#場に2枚以上カードが出ている場合のランクから計算用の値に変換して返す
def getFieldNum(field):
    for card in field:
        if card == "Jo":
            #ジョーカーは無視
            continue
        else:
            #同じランクの同時出ししか対応しないので、最初に見つけたのを返す
            return converter[card[1]]

#場にカードが一枚しか出ていない前提で手持ちのカードが出せる場合はtrueが返る
def isAvailableCard(field, hand):
    return converter[field] < converter[hand]

#場にカードが2枚以上出されている場合に、出せる手札のlistを作成して返す
def getAvailableCards(num, hands):
    result = []
    for cards in hands:
        for card in cards:
            if card == "Jo":
                #ジョーカーは無視
                continue
            else:
                #if  converter[card[1]] < num: 
                if  converter[card[1]] <= num:
                    continue
                else:
                    #ほかの組がすべて同じランクだったら、出せる手札
                    if isSameRank(cards):
                        result.append(cards)
                    break

    return result

#ランクがすべて同じ値ならtrueを返す
def isSameRank(cards):
    rank = -1
    for card in cards:
        if card == "Jo":
            #ジョーカーは無視
            continue
        else:
            if rank == -1:
                rank = card[1]
            else:
                if rank == card[1]:
                    continue
                else:
                    #違うランクが含まれている場合はNG
                    return False
    # ここまで来た場合はすべてのカードが同じランク
    return True

def test(data, expect):
    def sort(hands):
        result = []
        for hand in hands:
            result.append(sorted([hand[i: i+2] for i in range(0, len(hand), 2)]))
        return sorted(result)
    result = solve(data)
    expect = sort(expect.split(","))
    result = sort(result)
    if result == expect:
        print("成功: " , result , "/" , expect )
    else:
        print("失敗: " , result , "/" , expect )

test( "DJ,", "-" );
test( "H7,HK", "HK" );
test( "S3,D4D2", "D4,D2" );
test( "S9,C8H4", "-" );
test( "S6,S7STCK", "CK,ST,S7" );
test( "H4,SAS8CKH6S4", "S8,CK,H6,SA" );
test( "ST,D6S8JoC7HQHAC2CK", "Jo,C2,CK,HA,HQ" );
test( "SA,HAD6S8S6D3C4H2C5D4CKHQS7D5", "H2" );
test( "S2,D8C9D6HQS7H4C6DTS5S6C7HAD4SQ", "-" );
test( "Jo,HAC8DJSJDTH2", "-" );
test( "S4Jo,CQS6C9DQH9S2D6S3", "DQCQ,D6S6,H9C9" );
test( "CTDT,S9C2D9D3JoC6DASJS4", "JoC2,SJJo,DAJo" );
test( "H3D3,DQS2D6H9HAHTD7S6S7Jo", "JoHA,JoD6,JoH9,D6S6,D7S7,JoS6,HTJo,JoDQ,S2Jo,JoD7,JoS7" );
test( "D5Jo,CQDAH8C6C9DQH7S2SJCKH5", "CQDQ" );
test( "C7H7,S7CTH8D5HACQS8JoD6SJS5H4", "HAJo,JoSJ,H8S8,H8Jo,CQJo,CTJo,JoS8" );
test( "SAHA,S7SKCTS3H9DJHJH7S5H2DKDQS4", "-" );
test( "JoC8,H6D7C5S9CQH9STDTCAD9S5DAS2CT", "CTDT,H9D9,S9D9,DACA,CTST,H9S9,DTST" );
test( "HTST,SJHJDJCJJoS3D2", "DJCJ,SJDJ,JoHJ,CJHJ,SJJo,HJSJ,DJJo,JoCJ,JoD2,SJCJ,DJHJ" );
test( "C7D7,S8D8JoCTDTD4CJ", "D8S8,JoS8,CTJo,DTJo,JoCJ,CTDT,D8Jo" );
test( "DJSJ,DTDKDQHQJoC2", "JoDK,HQDQ,DQJo,C2Jo,JoHQ" );
test( "C3H3D3,CKH2DTD5H6S4CJS5C6H5S9CA", "S5H5D5" );
test( "D8H8S8,CQHJCJJoHQ", "JoCQHQ,JoHJCJ" );
test( "H6D6S6,H8S8D8C8JoD2H2", "D2H2Jo,D8JoS8,D8S8C8,C8D8H8,JoC8S8,H8JoC8,S8H8C8,JoS8H8,C8JoD8,D8H8S8,D8JoH8" );
test( "JoD4H4,D3H3S3C3CADASAD2", "DACASA" );
test( "DJHJSJ,SQDQJoHQCQC2CA", "SQJoCQ,DQCQJo,JoSQHQ,SQCQHQ,DQHQSQ,HQDQCQ,HQDQJo,SQDQCQ,CQJoHQ,SQJoDQ" );
test( "H3D3Jo,D4SKH6CTS8SAS2CQH4HAC5DADKD9", "HASADA" );
test( "C3JoH3D3,S2S3H7HQCACTC2CKC6S7H5C7", "-" );
test( "H5C5S5D5,C7S6D6C3H7HAH6H4C6HQC9", "C6D6S6H6" );
test( "H7S7C7D7,S5SAH5HAD5DAC5CA", "SADACAHA" );
test( "D4H4S4C4,S6SAH6HAD6DAC6CAJo", "C6H6S6D6,SAJoDACA,S6H6C6Jo,SACAJoHA,HADASAJo,HADAJoCA,CADAHASA,D6C6JoH6,S6D6C6Jo,H6JoS6D6" );
test( "DTCTSTHT,S3SQH3HQD3DQC3CQJo", "HQSQJoDQ,SQCQDQJo,DQCQHQJo,SQHQJoCQ,CQDQHQSQ" );
test( "JoS8D8H8,S9DTH9CTD9STC9CAC2", "H9C9D9S9" );
1
1
2

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
1