решатель палача на Python

Oct 08 2020

Я написал программу, которая читает файл csv, содержащий 100 строк, которые выглядят так:

1;S****L;SCHOOL
2;*A*G*A*;HANGMAN

затем попробуйте угадать буквы, как в игре с палачом. Моя задача - подсчитать все правильные и неправильные буквы, а затем суммировать их. Код работает нормально, я получаю около 1670 правильных + неправильных попыток угадать буквы. Мой подход заключался в создании словаря, в котором я сохраняю все буквы алфавита и читаю каждое слово из файла, затем суммирую каждое появление буквы и сохраняю их в словаре. Что-то вроде

{
   "A" : 30,
   "B" : 40
}

Затем я сортирую диктант по вхождению каждой буквы и сначала пытаюсь угадать букву с наибольшей вероятностью.

Мой вопрос. Можно ли что-то улучшить, чтобы получить меньшее количество попыток?

import csv

INPUT_FILE = "words.csv"


def oppenFile():        # function to read the file
    with open(INPUT_FILE, "r", encoding="utf-8") as words:
        reader = list(csv.reader(words, delimiter=";"))
        return reader


def letterCount():      # function that count every the letter in the file and return a dict: {A : 2}
    letters = dict.fromkeys("QWERTYUIOPĂÎASDFGHJKLȘȚÂZXCVBNM", 0)
    words = oppenFile()
    for w in range(len(words)):
        for l in list(words[w][2]):
            if l not in list(words[w][1]):
                letters[l] += 1
    return letters


def checkLetters(word, wholeWord, letters):     # function that solve a word return the number of right + wrong attempts
    attempts = 0
    for letter, key in letters.items():
        if letter in wholeWord and letter not in word:
            attempts += 1
            index = [i for i, lit in enumerate(wholeWord) if lit == letter]
            letters[letter] -= len(index)
            for j in range(len(index)):
                word = word[:index[j]] + letter + word[(index[j] + 1):]

        elif '*' not in word:
            break
        else:
            attempts += 1
    return attempts


def hangman():
    words = oppenFile()
    numberOfAttempts = 0
    letters = letterCount()

    for i in range(len(words)):
        letters = dict(sorted(letters.items(), key=lambda x: x[1], reverse=True)) # sort the dict

        numberOfAttempts += checkLetters(words[i][1], words[i][2], letters)

    print(f"{numberOfAttempts} right + wrong attempts")


if __name__ == "__main__":
    hangman()

Ответы

5 hjpotter92 Oct 08 2020 at 04:07

Добро пожаловать в Code Review!

PEP-8

В Python принято (и рекомендуется) следовать руководству по стилю PEP-8 для написания чистого, поддерживаемого и последовательного кода.

Функции и переменные должны быть названы в lower_snake_case, классы как UpperCamelCase, а константы как UPPER_SNAKE_CASE.

Подсказка типов

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

Подсчет букв

Python предоставляет collections.Counterдля вас встроенный .

Комментарии

Комментарии здесь не особо помогают. Кроме того, для функций лучше писать строки документации, а не комментарии.

Имена переменных

Вы открываете файл и называете его указатель как words, тогда как функция возвращает список слов; называется reader, что , в свою очередь , хранится в переменной называется words?

Странные преобразования

Вы создаете сопоставление букв с их соответствующими счетчиками в виде словаря (hash-map / table / lookup), затем преобразуете его в список двухзначных кортежей, сортируете его и конвертируете обратно в словарь. Зачем? dictимеет \$ O(1) \$ поиск и сортировка в вашем случае не имеют смысла.

Итерация с индексом

Вы используете следующую структуру цикла:

for i in range(len(words)):

где iсамо по себе не служит никакой цели. Каждый случай использования iимеет форму words[i]. Вы можете просто перебирать значения самого wordsсписка:

for word in words: