Драка

Что нужно сделать

Вы работаете в команде разработчиков мобильной игры, и вам досталась такая часть от ТЗ заказчика:

Есть два юнита, каждый из них называется «Воин». Каждому устанавливается здоровье в 100 очков. Они бьют друг друга в случайном порядке. Тот, кто бьёт, здоровье не теряет. У того, кого бьют, оно уменьшается на 20 очков от одного удара. После каждого удара надо выводить сообщение, какой юнит атаковал и сколько у противника осталось здоровья. Как только у кого-то заканчивается ресурс здоровья, программа завершается сообщением о том, кто одержал победу.

Реализуйте такую программу.

Что оценивается

  • Результат вычислений корректен.
  • Модели реализованы в стиле ООП, основной функционал описан в методах классов и в отдельных функциях.
  • Сообщения о процессе получения результата осмысленны и понятны для пользователя.
  • Переменные, функции и собственные методы классов имеют значащие имена, не a, b, c, d.
import random

class Warrior:
    def __init__(self, name, health=100, power=20):
        self.name = name
        self.health = health
        self.power = power

def duel(warrior_1, warrior_2):
    print('Дуэль началась:\n')
    while warrior_1.health > 0 and warrior_2.health > 0:
        hit = random.randint(1, 2)
        if hit == 1:
            hit = warrior_1
            warrior_2.health -= warrior_1.power
            print(f'{warrior_1.name}({warrior_1.health}) '
                  f'атаковал {warrior_2.name}({warrior_2.health}).')
        else:
            hit = warrior_2
            warrior_1.health -= warrior_2.power
            print(f'{warrior_2.name}({warrior_2.health}) '
                  f'атаковал {warrior_1.name}({warrior_1.health}).')
    print(f'\nПобеду одержал {hit.name}')

viking = Warrior('Викинг')
knight = Warrior('Рыцарь')

duel(viking, knight)

Чат

Что нужно сделать

Реализуйте программу — чат, в котором могут участвовать сразу несколько человек, то есть программа может работать одновременно для нескольких пользователей. При запуске запрашивается имя пользователя. После этого он выбирает одно из действий:

  1. Посмотреть текущий текст чата.
  2. Отправить сообщение (затем вводит сообщение).

Действия запрашиваются бесконечно.

Примечание: для решения задачи вам будет достаточно текущих знаний, нужно лишь проявить немного фантазии и хитрости. Не нужно лезть в дебри работы с сетями, создания GUI-приложений и прочих штук. (Но если очень хочется, то останавливать вас никто не будет!)

Что оценивается

  • Результат вычислений корректен.
  • Основной функционал описан в отдельных функциях.
  • Переменные и функции имеют значащие имена, не только a, b, c, d (подробнее об этом в видео 2.3).
  • Входные и выходные файлы названы так, как указано в задании.
  • Сообщения об ошибках осмысленные и понятные для пользователя.
with open('chat_log.txt', 'w', encoding='UTF-8') as chat:
    chat.writelines('Чат:\n')

def chat(chatfile):
    while True:
        try:
            name = input('Введите имя: ')
            act = int(input('''1 - Посмотреть текущий текст чата
2 - Отправить сообщение
Введите нужный вариант: '''))
            if act == 1:
                with open(chatfile, 'r', encoding='UTF-8') as file:
                    print(file.read())
            if act == 2:
                with open(chatfile, 'a', encoding='UTF-8') as file:
                    message = input('Сообщение: ')
                    file.writelines(f'{str(name)}: {str(message)}\n')
        except:
            print('\nДействуйте по инструкции.')

chat('chat_log.txt')

Регистрация

Что нужно сделать

У вас есть файл с протоколом регистраций пользователей на сайте — registrations.txt. Каждая строка содержит имя, емейл и возраст, разделённые пробелами. Например: Василий test@test.ru 27.

Напишите программу, которая проверяет данные из файла для каждой строки:

  • Присутствуют все три поля.
  • Поле «Имя» содержит только буквы.
  • Поле «Имейл» содержит @ и . (точку).
  • Поле «Возраст» является числом от 10 до 99.

В результате проверки сформируйте два файла:

  • registrations_good.log — для правильных данных, записывать строки в том виде, как есть;
  • registrations_bad.log — для ошибочных, записывать строку и вид ошибки.

Для валидации строки данных напишите функцию, которая может выдавать исключения:

  • НЕ присутствуют все три поля: IndexError.
  • Поле «Имя» содержит НЕ только буквы: NameError.
  • Поле «Имейл» НЕ содержит @ и . (точку): SyntaxError.
  • Поле «Возраст» НЕ является числом от 10 до 99: ValueError.

Формат выходных данных

Содержимое файла registrations_bad.log:
Ольга kmrn@gmail.com 123		Поле «Возраст» НЕ является числом от 10 до 99
Чехова kb@gmail.com 142		Поле «Возраст» НЕ является числом от 10 до 99
……
Степан ky 59		Поле «Имейл» НЕ содержит @ и . (точку)
……

Содержимое файла registrations_good.log:
Геннадий ttdababmt@gmail.com 69
Ольга ysbxur@gmail.com 20
……

Что оценивается

  • Результат вычислений корректен.
  • Формат вывода соответствует примеру.
  • Основной функционал описан в отдельных функциях.
  • Переменные и функции имеют значащие имена, не только a, b, c, d (подробнее об этом в видео 2.3).
  • Входные и выходные файлы названы так, как указано в задании.
def logwriter(doc):
    with open(doc, 'r', encoding='UTF-8') as file, \
            open('registrations_good.log', 'w', encoding='UTF-8') as good_log, \
            open('registrations_bad.log', 'w', encoding='UTF-8') as bad_log:
        for line in file:
            try:
                reg_list = line.split()
                if len(reg_list) < 3:
                    raise IndexError
                if reg_list[0].isalpha() == False:
                    raise NameError
                if '@' not in reg_list[1] or '.' not in reg_list[1]:
                    raise SyntaxError
                if 99 < int(reg_list[2]) or int(reg_list[2]) < 0:
                    raise ValueError
            except IndexError:
                bad_log.writelines(str(line) + '\t(!)НЕ присутствуют все три поля\n')
            except NameError:
                bad_log.writelines(str(line) + '\t(!)Поле «Имя» содержит НЕ только буквы\n')
            except SyntaxError:
                bad_log.writelines(str(line) + '\t(!)Поле «Имейл» НЕ содержит @ и . (точку)\n')
            except ValueError:
                bad_log.writelines(str(line) + '\t(!)Поле «Возраст» НЕ является числом от 10 до 99\n')
            else:
                good_log.writelines(str(line))

logwriter('registrations.txt')

Счастливое число

Что нужно сделать

Напишите программу, которая запрашивает у пользователя число до тех пор, пока сумма этих чисел не станет больше либо равна 777. Каждое введённое число при этом дозаписывается в файл out_file.txt. Сделайте так, чтобы перед дозаписью программа с вероятностью 1 к 13 выбрасывала пользователю случайное исключение и завершалась.

Пример 1

Введите число: 10
Введите число: 500
Введите число: 200
Введите число: 67
Вы успешно выполнили условие для выхода из порочного цикла!

Содержимое файла out_file.txt:
10
500
200
67

Пример 2

Введите число: 10
Введите число: 500
Вас постигла неудача!

Содержимое файла out_file.txt:
10

Что оценивается

  • Результат вычислений корректен.
  • Формат вывода соответствует примеру.
  • input содержит корректные приглашения для ввода.
  • Основной функционал описан в отдельных функциях.
  • Переменные и функции имеют значащие имена, не только a, b, c, d (подробнее об этом в видео 2.3).
  • Выходной файл назван так, как указано в задании.
import random

with open('out_file.txt', 'w', encoding='UTF-8') as file:
    finish = 0
    while finish < 777:
        try:
            exc = random.randint(1, 13)
            if exc == 13:
                raise BaseException
            num = int(input('Введите число: '))
            file.writelines(str(num) + '\n')
            finish += num
        except BaseException:
            print('Вас постигла неудача!')
            break
    if finish >= 777:
        print('Успех!')

with open('out_file.txt', 'r', encoding='UTF-8') as file:
    print('\nСодержимое файла out_file.txt: ')
    print(file.read())

Имена 2

Что нужно сделать

Есть файл people.txt, в котором построчно хранится N имён пользователей.

Напишите программу, которая берёт количество символов в каждой строке файла и в качестве ответа выводит общую сумму. Если в какой-либо строке меньше трёх символов (не считая литерала \n), то вызывается ошибка и сообщение, в какой именно строке возникла ошибка. Программа при этом не завершается и обрабатывает все имена файла.

Также при желании можно вывести все ошибки в отдельный файл errors.log.

Пример работы программы

Содержимое файла people.txt:
Василий
Николай
Надежда
Никита
Ян
Ольга
Евгения
Кристина

Ответ в консоли:
Ошибка: менее трёх символов в строке 4.
Общее количество символов: 49.

Что оценивается

  • Результат вычислений корректен.
  • Формат вывода соответствует примеру.
  • Основной функционал описан в отдельных функциях.
  • Переменные и функции имеют значащие имена, не только a, b, c, d (подробнее об этом в видео 2.3).
  • Входные и выходные файлы названы так, как указано в задании.
with open('people.txt', 'w', encoding='UTF-8') as file:
    file.write('''Василий
Николай
Надежда
Никита
Ян
Ольга
Евгения
Кристина''')

with open('people.txt', 'r', encoding='UTF-8') as file, \
        open('errors.log', 'w', encoding='UTF-8') as log_file:
    count = 0
    num = 0

    for line in file:
        try:
            num += 1
            nice_line = line.rstrip()
            count += len(nice_line)
            if len(nice_line) < 3:
                raise BaseException
        except BaseException:
            print(f'Ошибка: в {num} строке менее трех символов.')
            log_file.write(f'Ошибка: в {num} строке менее трех символов.\n')

print(f'Общее количество символов: {count}')

Война и мир

Что нужно сделать

Мало кто не знает про знаменитый роман Л. Н. Толстого «Война и мир». Это довольно объёмное произведение лежит в архиве voina-i-mir.zip. Напишите программу, которая подсчитывает статистику по буквам (не только русского алфавита) в этом романе и выводит результат на экран (или в файл). Результат должен быть отсортирован по частоте встречаемости букв (по возрастанию или убыванию). Регистр символов имеет значение.

Постарайтесь написать программу так, чтобы для её работы не требовалась распаковка архива «вручную».

Что оценивается

  • Результат вычислений корректен.
  • Основной функционал описан в отдельных функциях.
  • Переменные и функции имеют значащие имена, не только a, b, c, d (подробнее об этом в видео 2.3).
  • Входной файл назван так, как указано в задании, выходной файл имеет значащее имя.
file = open('voyna-i-mir.txt', 'r', encoding='UTF-8')
symbols = dict()
abc = 'a b c d e f g h i j k l m n o p q r s t u v w x y z'.split()
ru_abc = 'а б в г д е ё ж з и й к л м н о п р с т у ф х ц ч ш щ ъ ы ь э ю я'.split()

for words in file.read().split():
    for sym in words:
        if sym.lower() in abc or sym.lower() in ru_abc:
            if sym not in symbols:
                symbols[sym] = 1
            else:
                symbols[sym] += 1

sorted_tuple = sorted(symbols.items(), key=lambda x: x[1], reverse=True)
result = open('result.txt', 'w', encoding='UTF-8')
result.write('Количество букв в отрывке романа "Война и мир: "\n')

for i in sorted_tuple:
    result.write(str(i[0]) + '-' + str(i[1]) + '\n')

file.close()
result.close()

Частотный анализ

Что нужно сделать

Есть файл text.txt, который содержит текст. Напишите программу, которая выполняет частотный анализ, определяя долю каждой буквы английского алфавита в общем количестве английских букв в тексте, и выводит результат в файл analysis.txt. Символы, не являющиеся буквами английского алфавита, учитывать не нужно.

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

Пример:

Содержимое файла text.txt:
Mama myla ramu.

Содержимое файла analysis.txt:
a 0.333
m 0.333
l 0.083
r 0.083
u 0.083
y 0.083

Что оценивается

  • Результат вычислений корректен.
  • Формат вывода соответствует примеру.
  • Основной функционал описан в отдельных функциях.
  • Переменные и функции имеют значащие имена, не только a, b, c, d (подробнее об этом в видео 2.3).
  • Входные и выходные файлы названы так, как указано в задании.
file = open('text.txt', 'r', encoding='UTF-8')
text = file.read()
abc = 'a b c d e f g h i j k l m n o p q r s t u v w x y z'.split()
uniq_symb = {}
count = 0

for i in text.lower():
    if i in abc:
        count += 1
        if i not in uniq_symb:
            uniq_symb[i] = 1
        else:
            uniq_symb[i] += 1

for k, v in uniq_symb.items():
    uniq_symb[k] = round((v / count), 3)

res = [(k, v) for k, v in uniq_symb.items()]
res = sorted(res, key=lambda i:i[0])
res = sorted(res, key=lambda i:i[1], reverse=True)

new_file = open('analysis.txt', 'w', encoding='UTF-8')
for i in res:
    new_file.writelines(str(i) + '\n')

file.close()
new_file.close()

Турнир

Что нужно сделать

В файле first_tour.txt записано число K и данные об участниках турнира по настольной игре «Орлеан»: фамилии, имена и количество баллов, набранных в первом туре. Во второй тур проходят участники, которые набрали более K баллов в первом туре.

Напишите программу, которая выводит в файл second_tour.txt данные всех участников, прошедших во второй тур, с нумерацией.

В первой строке нужно вывести в файл second_tour.txt количество участников второго тура. Затем программа должна вывести фамилии, инициалы и количество баллов всех участников, прошедших во второй тур, с нумерацией. Имя нужно сократить до одной буквы. Список должен быть отсортирован по убыванию набранных баллов.

Пример:

Содержимое файла first_tour.txt:
80
Ivanov Serg 80
Sergeev Petr 92
Petrov Vasiliy 98
Vasiliev Maxim 78

Содержимое файла second_tour.txt:
2
1) V. Petrov 98
2) P. Sergeev 92

Что оценивается

  • Результат вычислений корректен.
  • Формат вывода соответствует примеру.
  • Основной функционал описан в отдельных функциях.
  • Переменные и функции имеют значащие имена, не только a, b, c, d (подробнее об этом в видео 2.3).
  • Входные и выходные файлы названы так, как указано в задании.
first_file = open('first_tour.txt', 'r', encoding='UTF-8')
second_file = open('second_tour.txt', 'a', encoding='UTF-8')
win_list = []
start = int(first_file.readline())
for line in first_file:
    person = line.split()
    if int(person[2]) > start:
        new_person = ((person[1][0]), (person[0]), int(person[2]))
        win_list.append(new_person)

win_list.sort(key=lambda i:i[2], reverse=True)
second_file.write(f'{len(win_list)}\n')
for num, pers in enumerate(win_list, 1):
    second_file.write(f'{num}) {pers[0]}. {pers[1]} {pers[2]}\n')

first_file.close()
second_file.close()

Файлы и папки

Что нужно сделать

Напишите программу, которая получает на вход путь до каталога (это может быть и просто корень диска) и выводит общее количество файлов и подкаталогов в нём. Также выведите на экран размер каталога в килобайтах (1 килобайт = 1024 байт).

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

Результат работы программы на примере python_basic\Module14:

E:\PycharmProjects\python_basic\Module14
Размер каталога (в Кб): 8.373046875
Количество подкаталогов: 7
Количество файлов: 15

Что оценивается

  • Результат вычислений корректен.
  • Формат вывода соответствует примеру.
  • input содержит корректные приглашения для ввода.
  • Основной функционал описан в отдельных функциях.
  • Переменные и функции имеют значащие имена, не только a, b, c, d
import os

user_path = input('Введите путь: ')

def path_scan(abs_path, folders = 0, files = 0):
    for i in os.listdir(abs_path):
        path = os.path.join(abs_path, i)
        if os.path.isfile(path): files += 1
        if os.path.isdir(path): folders += 1
    size = os.path.getsize(abs_path)
    return size, folders, files

print(f'Размер каталога, количество подкаталогов и файлов: {path_scan(user_path)}')

Дзен Пайтона

Что нужно сделать

В файле zen.txt хранится так называемый Дзен Пайтона — текст философии программирования на языке Python. Выглядит он так:

Beautiful is better than ugly.
Explicit is better than implicit.
Simple is better than complex.
Complex is better than complicated.
Flat is better than nested.
Sparse is better than dense.
Readability counts.
Special cases aren't special enough to break the rules.
Although practicality beats purity.
Errors should never pass silently.
Unless explicitly silenced.
In the face of ambiguity, refuse the temptation to guess.
There should be one-- and preferably only one --obvious way to do it.
Although that way may not be obvious at first unless you're Dutch.
Now is better than never.
Although never is often better than *right* now.
If the implementation is hard to explain, it's a bad idea.
If the implementation is easy to explain, it may be a good idea.
Namespaces are one honking great idea -- let's do more of those!

Напишите программу, которая выводит на экран все строки этого файла в обратном порядке.

Кстати, попробуйте открыть консоль Python и ввести команду import this.

Результат работы программы:

Namespaces are one honking great idea -- let's do more of those!
If the implementation is easy to explain, it may be a good idea.
If the implementation is hard to explain, it's a bad idea.
Although never is often better than *right* now.
…

Что оценивается

  • Результат вычислений корректен.
  • Формат вывода соответствует примеру.
  • Основной функционал описан в отдельных функциях.
  • Переменные и функции имеют значащие имена, не только a, b, c, d (подробнее об этом в видео 2.3).
  • Входной файл назван так, как указано в задании.
zen_file = open('zen.txt', 'r')

for i in zen_file.read().split('\n')[::-1]:
    print(i)

zen_file.close()