TransWikia.com

Работа цикла for в игре "Быки и коровы". Питон

Stack Overflow на русском Asked on December 3, 2020

Делаю игру “Быки и коровы”.
Если буква из testword есть в correctword и стоит в том же месте, то bulls += 1
Если буква из testword есть в correctword, но не на своем месте, то cows += 1
Программа работает правильно во всех случаях, кроме одного: когда игрок предлагает слово, в котором есть повторяющиеся буквы. Пример:

correctword = [м, о, н, а, х] # загаданное компьютером слово  
testword = [м, о, н, н, н] # тестовое слово, которое ввел игрок. программа сравнивает его с загаданным  

bulls = 0  
cows = 0  

for i in correctword: # для каждой буквы в correctword  
    if i in testword: # если одна из букв есть в testword  
         if testword.index(i) == correctword.index(i): # и если индексы букв совпадают, то:  
             bulls += 1 # увеличить счетчик bulls на 1  
         else:  
             cows += 1 # иначе увеличить счетчик cows на 1  

В описанном случае программа считает: bulls = 3, cows = 0, а должна: bulls = 3, cows = 2
Если поменять итерируемый список:

for i in testword:  
    if i in correctword:  

то также именно эта ситуация считается неверно, но уже иначе: bulls =5, cows =0.

Думаю, дело в том, что list.index(i) возвращает положение ПЕРВОГО элемента со значением i, а надо не первого, а каждого.
Что делать?

2 Answers

Вот вариант решения, использующий словари и множества позиций для каждого символа.

correctword = ['м', 'о', 'н', 'а', 'х']  # загаданное компьютером слово
testword = ['м', 'о', 'н', 'н', 'н']  # тестовое слово, которое ввел игрок. программа сравнивает его с загаданным

bulls = 0
cows = 0

correctword_map = {}  # словарь {символ: множество позиций с этим символом} для корректного слова
testword_map = {}     # словарь {символ: множество позиций с этим символом} для проверяемого слова

length = len(correctword)  # длина слова
for c in set(correctword):  # для каждого уникального символа
    correctword_map[c] = set()  # инициализируем значение в словаре пустым множеством
    testword_map[c] = set()
    for i in range(length):  # пробегаем по каждой позиции в обоих словах и
        if correctword[i] == c:
            correctword_map[c].add(i)  # добавляем в множество позиции, в которых встречается этот символ
        if testword[i] == c:
            testword_map[c].add(i)

for c in set(correctword):  # для каждого уникального символа
    correctword_positions = correctword_map[c]  # берем множество позиций этого символа в корректном слове
    testword_positions = testword_map[c]        # берем множество позиций этого символа в проверяемом слове
    bulls += len(testword_positions.intersection(correctword_positions))  # быки - прибавляем размер пересечения этих множеств
    cows += len(testword_positions.difference(correctword_positions))     # коровы - прибавляем размер разности этих множеств

print(bulls)
print(cows)

В принципе, можно сделать проще.

Например, не пробегать дважды по set(correctword), а делать всё за один проход. Да и словари набивать не обязательно, можно просто работать с множествами.

В общем, есть простор для творческой доработки.

Answered by Pavel on December 3, 2020

python3

def each(s: str, f):
    sL = len(s)
    i = 0
    while i < sL:
        val = s[i]
        f(val, i)
        i += 1


def foo(a: str, b: str):
    # aL = len(a)
    bL = len(b)
    bulls = 0
    cows = 0

    def q(v, i: int):
        nonlocal bulls, cows
        if i >= bL:
            return
        isOK = v == b[i]
        if isOK:
            bulls += 1
        else:
            cows += 1
        # print(b[i])
    each(a, q)
    return [bulls, cows]


bulls, cows = foo('монах', 'моннн')

print(bulls)
print(cows)

o ,-

Answered by qwabra on December 3, 2020

Add your own answers!

Ask a Question

Get help from others!

© 2024 TransWikia.com. All rights reserved. Sites we Love: PCI Database, UKBizDB, Menu Kuliner, Sharing RPP