Определить действительный стрит 8-карточный покер

Напишите улучшенный код для идентификации действительной серии из восьми карт., например 4H,5S,AC,7C,8H,AH,0S,JC. Обратите внимание, что комбинация карт может включать в себя символы Wild (как мы видим в нашем примере, где Туз треф заменяет шестерку, а туз червей заменяет девятку), но она должна включать как минимум две «естественные» карты (т. Е. не-подстановочные знаки). Также обратите внимание, что последовательность карточек важна для этого типа группы, и что 4H,5S,AC,8C,7H,AH,AS,AC, например, не является правильной прямой восьмеркой, так как это не последовательность. Тузы являются единственными дикими картами и должны представлять другую карту. Разрешены дубликаты карт.

Входы карты находятся в списке из 2 строк значений со значением:

  • От 2 до 9 — от 2 до 9
  • 0 — за 10
  • J — для Джека
  • Q — для королевы
  • K — для короля
  • A — для Ace

Масти показаны со значениями S (пика), C ​​(булава), H (сердце), D (ромб).

  1. Пример ввода для проверки: 4H,5S,AC,7C,8H,AH,0S,JC

    Выход: True

  2. Пример ввода для проверки: AH,5S,AC,7C,AH,AH,AS,AC

    Выход: True

  3. Пример ввода для проверки: 4H,5S,AC,8C,7H,AH,AS,AC

    Выход: ложь

Вот мой код:

group = input().split(",")
if len(group) == 8:
    #check for ace
    ace = [0 for card in group if card[0] == 'A']
    run_vals = {"0": 10, "J": 11, "Q": 12, "K":13}
    if len(ace) < 6:
        miss_count = 0
        for index in range(len(group)-1):
            if group[index][0]  == "A":
                miss_count += 1
                if group[index+1][0]  == "A" and index == len(group)-2:
                    miss_count += 1
                    continue
                else:
                    continue
                
            if group[index+1][0]  == "A" and index == len(group)-2:
               miss_count += 1
               continue
            if group[index+1][0]  == "A" and index <len(group)-2:
               continue
            
            if group[index+1][0] in run_vals:
                num1 = run_vals[group[index+1][0]]
            else:
                num1 = int(group[index+1][0])
                
            if group[index][0] in run_vals:
                num2 = run_vals[group[index][0]]
            else:
                num2 = int(group[index][0])

            if (num1 - num2) != 1:
                miss_count += 1
              
        if miss_count == len(ace):
            print(True)
        else:
            print(False)

    elif len(ace) == 6:
        ace_in_between = 0
        range_limits = [card for card in group if card[0] != "A"]
        for index in range(len(group)):
            if index > group.index(range_limits[0]) and index< group.index(range_limits[1]):
                ace_in_between += 1
        range_limits = [run_vals[val[0]] if val[0] in run_vals else val[0] for val in range_limits]
        if ace_in_between + 1 == (int(range_limits[1]) - int(range_limits[0]) ):
            print(True)
        else:
            print(False)
    else:
        print(False)
else:
    print(False)

3 ответа
3

Хорошие новости! В вашем коде есть много возможностей для улучшения! (Как это для положительного спина?)

Подсчет тузов

    ace = [0 for card in group if card[0] == 'A']

Этот код создает список (ace), который содержит только 0 элементов, равных количеству тузов в group. Содержание списка никогда не используется, только длина. Наконец, дважды запрашивается длина списка.

Это очень сложная реализация для простого подсчета количества тузов:

    aces = sum(card[0] == 'A' for card in group)

Или чуть менее наискось:

    aces = sum(1 for card in group if card[0] == 'A')

Карты декодирования

    run_vals = {"0": 10, "J": 11, "Q": 12, "K":13}
    ...
            if group[index+1][0] in run_vals:
                num1 = run_vals[group[index+1][0]]
            else:
                num1 = int(group[index+1][0])

            if group[index][0] in run_vals:
                num2 = run_vals[group[index][0]]
            else:
                num2 = int(group[index][0])
    ...
        range_limits = [run_vals[val[0]] if val[0] in run_vals else val[0] for val in range_limits]
        if ace_in_between + 1 == (int(range_limits[1]) - int(range_limits[0]) ):

Я вижу много in run_vals тесты и int(...) слепки. Представьте, насколько чище мог бы выглядеть ваш код, если бы вы просто заполнили все поля run_vals?

    run_vals = {"A": 1,
                "2": 2, "3": 3, "4": 4, "5": 5,
                "6": 6, "7": 7, "8": 8, "9": 9,
                "0": 10, "J": 11, "Q": 12, "K":13}

Я добавил сопоставление «А» к 1 просто для полноты. Это позволит вам протестировать all(card[0] in run_vals for card in group) чтобы проверить, что все карты имеют действительный ранг, например, никто не подбирает «1 пик».

В этом отношении вы также можете проверить действительные костюмы, такие как all(card[1] in {'C', 'D', 'H', 'S'} for card in group), чтобы не попасться в «7 пентаклей».

Прямо

Проблема была бы предельно простой, если бы не было джокеров. Вы могли написать:

    rank = [run_vals[card[0]] for card in group]
    start = rank[0]
    for idx in range(len(rank)):
        if rank[idx] != start + idx:
            return False
    return True

Было бы легко поддерживать дикие карты, если бы мы знали, что первая карта не туз. Мы могли бы просто добавить исключение для тузов:

    for idx in range(len(rank)):
        if rank[idx] != start + idx and rank[idx] != 1:
            return False

Начальное значение

Что будет, если первой картой будет туз? Что ж, вторая карта (предположим, что это не туз) диктует, что начало было на один ранг ниже. Или, если это был туз, то третья карта и так далее:

    for idx in range(len(rank)):
        if rank[idx] == 1:
            start = rank[idx] - idx
            break
    else:
        return False     # Only aces exist!

Функции!

Ваш код — это один сложный сценарий без каких-либо функций. Если вы еще не научились их писать, учитесь. Если вы узнали, используйте их!

Переработанный код

Следующий код является повторной реализацией некоторых из вышеперечисленных идей. Однако петли вроде for idx in len(range(list)) были заменены на более Pythonic for idx, value in enumerate(list) петли. Циклы, возвращающие False если одна итерация дает False результат был заменен на all(...) оператор с выражением генератора. Он также демонстрирует некоторые подсказки типов, """docstrings""" (включая использование (doctest), чтобы помочь написать код, более понятный для других и содержащий встроенные модульные тесты.

Еще одно улучшение — это формулировка задачи, которая гласит, что должно быть как минимум 2 «естественных» карты. Вместо того, чтобы проверять количество тузов, которое меньше или равно 6 — число, которое нигде не фигурирует в формулировке задачи, — выполняется прямая проверка с заданным значением 2.

RANK = dict(zip("A234567890JQK", range(1, 14)))
WILD = RANK['A'] 

def straight_of_eight(card_string: str) -> bool:
    """
    Determine if a string of cards is an ascending straight,
    with at least 2 natural cards.

    >>> straight_of_eight("4H,5S,AC,7C,8H,AH,0S,JC")
    True

    >>> straight_of_eight("4H,5S,AC,8H,7C,AH,0S,JC")
    False
    """
    
    ranks = [RANK[card[0]] for card in card_string.split(',')]

    if len(ranks) != 8:
        return False   # Were not given exactly 8 cards

    if sum(rank != WILD for rank in ranks) < 2:
        return False   # Not enough natural cards

    # Determine starting rank for the straight
    start = next(rank - idx for idx, rank in enumerate(ranks) if rank != WILD)

    return 2 <= start <= 6 and all(rank == idx or rank == WILD
                                   for idx, rank in enumerate(ranks, start))

if __name__ == '__main__':
    import doctest
    doctest.testmod()

    group = input()
    print(straight_of_eight(group))

  • Большое спасибо!

    — Алоизиус Ребейро

это из проекта 2 COMP10001? Простым решением является использование алгоритма Снида (ранее называвшегося Чака) для решения этой проблемы и поиска других типов групп.

    Я предлагаю вам не использовать какой-либо код, предоставленный другими пользователями stackoverflow, в качестве ответа для проекта. Это серьезный академический проступок, и университет узнает об этом с помощью своего алгоритма обнаружения, а также другие студенты обнаружат это и, возможно, сообщат об этом. Риск получения 0 баллов и потенциального исключения НЕ стоит того, чтобы заработать эти дополнительные баллы.

    Добавить комментарий

    Ваш адрес email не будет опубликован. Обязательные поля помечены *