Любые способы избежать использования большого количества операторов if

Я только что закончил изучение основ Python в CS50 и сейчас пытаюсь создать небольшую игровую программу для практики. На полпути я столкнулся с потенциальной проблемой.

Подводя итог игры, она выглядит так:

  1. Пользователь вводит 5 цифр от 0 до 9.
  2. В игре запрограммировано несколько фиксированных шаблонов для 5 номеров.
  3. Программа определяет, соответствует ли ввод пользователя какому-либо шаблону или нет.
  4. На основании того, что соответствует (если соответствует), программа выставляет пользователю оценку.

Пример:

User's input - 1,2,3,4,5
Possible patterns - a,a+1,a+2,a+3,a+4  1 point
                  - a,a+2,a+4,a+6,a+8  2 points
                  - a,a+1,a+3,a+5,a+7  3 points

Таким образом, в этом случае пользователь получает 1 балл.

Моя текущая проблема заключается в том, что я пытаюсь создать много разных шаблонов (например, 20), но на данный момент я знаю только один способ - использовать оператор if для каждого шаблона, например:

if .....

if .....

if .....

Делать это для каждого шаблона кажется неправильным. Я пытался найти способы уменьшить количество операторов if, но такие методы, как использование таблицы переходов (словарей), похоже, здесь не работают. Заранее спасибо.

В вашем примере что такое a?

001 30.04.2024 19:20

а — наименьшее число из пяти чисел, которые вводит пользователь.

Koh Cw 30.04.2024 19:27
Почему в Python есть оператор "pass"?
Почему в Python есть оператор "pass"?
Оператор pass в Python - это простая концепция, которую могут быстро освоить даже новички без опыта программирования.
Некоторые методы, о которых вы не знали, что они существуют в Python
Некоторые методы, о которых вы не знали, что они существуют в Python
Python - самый известный и самый простой в изучении язык в наши дни. Имея широкий спектр применения в области машинного обучения, Data Science,...
Основы Python Часть I
Основы Python Часть I
Вы когда-нибудь задумывались, почему в программах на Python вы видите приведенный ниже код?
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
Алиса и Боб имеют неориентированный граф из n узлов и трех типов ребер:
Оптимизация кода с помощью тернарного оператора Python
Оптимизация кода с помощью тернарного оператора Python
И последнее, что мы хотели бы показать вам, прежде чем двигаться дальше, это
Советы по эффективной веб-разработке с помощью Python
Советы по эффективной веб-разработке с помощью Python
Как веб-разработчик, Python может стать мощным инструментом для создания эффективных и масштабируемых веб-приложений.
1
2
116
7
Перейти к ответу Данный вопрос помечен как решенный

Ответы 7

Для такого сценария на большинстве языков можно использовать «Переключить (совпадение)» или «Карта (данные формы объекта)».

пример:

def http_error(status):
    match status:
        case 400:
            return "Bad request"
        case 404:
            return "Not found"
        case _:
            return "Something's wrong with the internet"

Как это можно использовать для задаваемого вопроса?

user19077881 30.04.2024 21:15

@user19077881 user19077881 Если вы этого не понимаете, не используйте его.

alithecodeguy 01.05.2024 09:04
Ответ принят как подходящий

Вы можете поместить свои шаблоны и оценки в списки. Например, сохраните шаблоны в виде лямбда-выражений, которые можно вычислить на основе входных данных a.

Затем вы можете перебирать шаблоны, оценивать их и сравнивать результат с пользовательским вводом.

user_input = [12, 14, 16, 18, 20]
a = user_input[0]

# define your patterns and their scores
patterns = [
    lambda x: [x, x + 1, x + 2, x + 3, x + 4],
    lambda x: [x, x + 2, x + 4, x + 6, x + 8],
    lambda x: [x, x + 3, x + 6, x + 9, x + 12],
]
scores = [1, 2, 3]


def compare_list(list1, list2):
    return list1 == list2


score = 0
for idx, pattern in enumerate(patterns):
    if compare_list(user_input, pattern(a)):
        print("Pattern found")
        score = scores[idx]
        break

print(f"Score: {score}")

Возможно, вам придется отсортировать списки перед проверкой равенства, в зависимости от шаблонов, которые вы хотите сопоставить.

Функциональность match/case была добавлена ​​в Python 3.10, поэтому, если ваша версия ограничена и, следовательно, ограничена операторами if, возможно, программа проверки вызовет другую функцию, чтобы вы могли вернуться, если оператор if совпадает (поэтому вы ограничиваете количество операторов if ). Затем добавьте математику в свои утверждения if, чтобы они охватывали несколько сценариев.

Пример:

<-SNIP->

def check_value(a, value):
    checkvalue = value - a
    # sort the if statements from highest to lowest return
    if checkvalue%2 == 1:
        return 3
    if checkvalue%2 == 0:
        return 2
    if checkvalue <= 4:
        return 1
    # etc
    return 0

# Call the checker in your other method:
# a is target value
# value is under input value
win_result = check_value(a, value)

<-SNIP->

Обновлено: теперь я вижу, что для каждой разницы может быть несколько результатов выигрыша, что делает if или match с return бесполезным решением. В этом случае вы можете использовать dict для хранения пар разница/выигрыш. Примечание. Вы можете использовать целочисленные ключи для словаря, если вы определяете dict с помощью {}, но не с помощью dict().

Пример:

<-SNIP->

result_dict = {
    1 : 4, # 1+3
    2 : 3, # 1+2
    3 : 4, # 1+3
    4 : 3, # 1+3
    5 : 3, # 3
    # and so on
    }

win_result = result_dict[user_value-target_value]

<-SNIP->

Вы можете использовать список или словарь для хранения кортежа (distance_between_element, точки) Рассчитайте расстояние между элементами списка.

input = [1,2,3,4,5]
result = []
for i in range(input)-1:
   result.append(list[i+1] -list[i])

Теперь вам нужен дикт. с ключом [1,1,1,1] и значением 1 это будет a, a+1, a+2, a+3, a+4 и получит 1 балл.

Если пользователи введут 1 2 3 4 5, то это будет строка, поэтому для этого ответа потребуется преобразование в список целых чисел. Также лучше не дублировать имя input, которое используется в Python для определенной цели.

user19077881 30.04.2024 21:14
def pattern1(numbers):
    # Check if numbers match the pattern a, a+1, a+2, a+3, a+4
    return all(numbers[i] == numbers[0] + i for i in range(len(numbers)))

def pattern2(numbers):
    # Check if numbers match the pattern a, a+2, a+4, a+6, a+8
    return all(numbers[i] == numbers[0] + 2*i for i in range(len(numbers)))

def pattern3(numbers):
    # Check if numbers match the pattern a, a+1, a+3, a+5, a+7
    return all(numbers[i] == numbers[0] + sum(range(i+1)) for i in range(len(numbers)))

# Dictionary to store patterns and their scores
patterns = {
    pattern1: 1,
    pattern2: 2,
    pattern3: 3
}

def evaluate_input(user_input):
    # Convert the user input string to a list of integers
    numbers = list(map(int, user_input.split(',')))

    # Initialize score
    score = 0

    # Check each pattern
    for pattern, points in patterns.items():
        if pattern(numbers):
            score += points

    return score

# Main program
user_input = input("Enter 5 numbers separated by commas (e.g., 1,2,3,4,5): ")
score = evaluate_input(user_input)
print(f"Your score: {score}")

Объяснение:

  1. Функции шаблона: шаблон1, шаблон2 и шаблон3 — это функции, которые проверяют определенные шаблоны во входных числах. Их можно корректировать или расширять в зависимости от правил игры.
  2. Словарь шаблонов: каждая функция шаблона связана со значением точки в словаре. Это позволяет легко расширять или модифицировать систему оценок.
  3. Оценка входных данных: функция Assessment_input преобразует вводимые пользователем данные в список целых чисел, затем проверяет каждый шаблон, вызывая соответствующую функцию шаблона. Если шаблон совпадает, к счету добавляются соответствующие баллы.
  4. Основная программа: запрашивает у пользователя ввод данных, оценивает его и распечатывает результат.

Такой подход делает ваш код более организованным и масштабируемым, упрощая добавление новых шаблонов или изменений в оценку. Это снижает сложность и повышает удобство сопровождения за счет инкапсуляции логики шаблонов в отдельные функции.

Предполагая, что ваша версия Python допускает сопоставление регистров (и что каждая запись соответствует вашим примерам последовательного увеличения/уменьшения первого числа), вы можете преобразовать входные данные в шаблон и сопоставить их для получения оценки, используя приведенный ниже код. Если механизмы входа могут иметь более сложный вариант, тогда преобразование необходимо будет соответствующим образом изменить.

user_str = input('enter five numbers ')

def func(entry): 
    comp = []
    vals = entry.split()
    for num in vals:
       comp.append(int(num) - int(vals[0]))
    match comp[1:]:         # compare all but first element
        case [1, 2, 3, 4]: points = 1
        case [2, 4, 6, 8]: points = 2
        case [1, 3, 4, 7]: points = 3
        case _: points = 0   # catch all non-matching patterns
    return points

print(func(user_str))

поэтому, если пользователь вводит 1 2 3 4 5, код выдает 1

Приятно видеть, как пользователь вводит все числа одновременно! Я думаю, что некоторая комбинация вашего и моего ответа была бы идеальной. Таким образом, метод будет возвращаться для каждого совпадения вместо установки возвращаемого значения и возврата в конце метода.

AutumnKome 01.05.2024 14:26

Это будет проще и понятнее. Идея здесь состоит в том, чтобы узнать hcf. hcf — это не что иное, как самое большое число, на которое можно разделить все элементы входных данных. Если после нахождения hcf все элементы входных данных разделить на hcf, вы напрямую получите шаблон.

# Get comma separated input
usr_entry = input()

# convert input into list
usr_entry = usr_entry.split(',')

#convert each element into int 
usr_entry = [int(float(x)) for x in usr_entry]

# create a dict keys being pattern with a = 1
dct = {(1, 2, 3, 4, 5) : 1,
        (1, 3, 5, 7, 9) : 2,
        (1, 2, 4, 6, 8) : 3}

# find the smallest number of the user input
small = min(usr_entry)

if tuple(usr_entry) not in dct.keys():
    # Iterate from small to 1 in reverse step being -1
    for i in range(small, 0, -1):

        if i != 1:
            #find out hcf and break
            if all(x % i == 0 for x in usr_entry):
                hcf = i; break
                
                
else: hcf = 1

# Divide all the user input by hcf
usr_entry = [x/hcf for x in usr_entry]

# convert the usr_entry to tuple
usr_entry = tuple(usr_entry)

print(dct[usr_entry])

Другие вопросы по теме