-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathmodule_2.py
More file actions
392 lines (322 loc) · 18.3 KB
/
module_2.py
File metadata and controls
392 lines (322 loc) · 18.3 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
# Stepick.org — Python: основы и применение
# 2. Cтандартные средства языка Python
import itertools
from datetime import date, timedelta
from simplecrypt import decrypt, DecryptionException
import os.path
# === 2.1 Ошибки и исключения ===
def m_2_1_1():
"""
Вашей программе будет доступна функция foo, которая может бросать
исключения. Вам необходимо написать код, который запускает эту функцию,
затем ловит исключения ArithmeticError, AssertionError, ZeroDivisionError
и выводит имя пойманного исключения.
"""
try:
foo()
except ZeroDivisionError:
print("ZeroDivisionError")
except ArithmeticError:
print("ArithmeticError")
except AssertionError:
print("AssertionError")
def m_2_1_2():
"""
Вам дано описание наследования классов исключений в следующем формате.
<имя исключения 1> : <имя исключения 2> <имя исключения 3> ...
Это означает, что исключение 1 наследуется от исключения 2, исключения 3...
Антон написал код, который выглядит следующим образом.
try:
foo()
except <имя 1>:
print("<имя 1>")
except <имя 2>:
print("<имя 2>")
...
Костя посмотрел на этот код и указал Антону на то, что некоторые
исключения можно не ловить, так как ранее в коде будет пойман их
предок. Но Антон не помнит какие исключения наследуются от каких.
Помогите ему выйти из неловкого положения и напишите программу,
которая будет определять обработку каких исключений можно удалить из кода.
Важное примечание:
В отличие от предыдущей задачи, типы исключений не созданы.
Создавать классы исключений также не требуется
Мы просим вас промоделировать этот процесс, и понять какие из
исключений можно и не ловить, потому что мы уже ранее где-то
поймали их предка.
Формат входных данных
В первой строке входных данных содержится целое число
n - число классов исключений. В следующих n строках содержится описание
наследования классов.
В i-й строке указано от каких классов наследуется i-й класс.
Обратите внимание, что класс может ни от кого не наследоваться.
Гарантируется, что класс не наследуется сам от себя (прямо или косвенно),
что класс не наследуется явно от одного класса более одного раза.
В следующей строке содержится число m - количество обрабатываемых
исключений. Следующие m строк содержат имена исключений в том порядке,
в каком они были написаны у Антона в коде.
Гарантируется, что никакое исключение не обрабатывается дважды.
Формат выходных данных
Выведите в отдельной строке имя каждого исключения, обработку
которого можно удалить из кода, не изменив при этом поведение программы.
Имена следует выводить в том же порядке, в котором они идут
во входных данных.
"""
def parents(name):
result = set()
for parent in relations.get(name, []):
result.add(parent)
result |= parents(parent)
return result
def create_relations(count):
data = {}
for _ in range(count):
name, *parents = input().split()
if ":" in parents:
data[name] = parents[1:]
else:
data[name] = []
return data
def call(count):
calls = []
for _ in range(count):
name = input()
if parents(name) & set(calls):
print(name)
else:
calls.append(name)
relations = create_relations(int(input()))
call((int(input())))
def m_2_1_3():
"""
Реализуйте класс PositiveList, отнаследовав его от класса list,
для хранения положительных целых чисел.
Также реализуйте новое исключение NonPositiveError.
В классе PositiveList переопределите метод append(self, x)
таким образом, чтобы при попытке добавить неположительное целое
число бросалось исключение NonPositiveError и число не добавлялось,
а при попытке добавить положительное целое число, число добавлялось
бы как в стандартный list.
В данной задаче гарантируется, что в качестве аргумента x метода
append всегда будет передаваться целое число.
"""
class NonPositiveError(Exception):
pass
class PositiveList(list):
def append(self, object):
if object > 0:
return super().append(object)
else:
raise NonPositiveError("Only positive integers are allowed")
# === 2.2 Работа с кодом: модули и импорт ===
def m_2_2_1():
"""
В первой строке дано три числа, соответствующие некоторой
дате date -- год, месяц и день.
Во второй строке дано одно число days -- число дней.
Вычислите и выведите год, месяц и день даты, которая наступит,
когда с момента исходной даты date пройдет число дней, равное days.
Примечание: Для решения этой задачи используйте стандартный
модуль datetime. Вам будут полезны класс datetime.date для хранения
даты и класс datetime.timedelta для прибавления дней к дате.
"""
# from datetime import date, timedelta
year, month, day = [int(x) for x in input().split()]
days = timedelta(days=int(input()))
d = date(year, month, day)
result = d + days
print(result.year, result.month, result.day)
def m_2_2_2():
"""
Алиса владеет интересной информацией, которую хочет заполучить Боб.
Алиса умна, поэтому она хранит свою информацию в зашифрованном файле.
У Алисы плохая память, поэтому она хранит все свои пароли в открытом
виде в текстовом файле. Бобу удалось завладеть зашифрованным файлом с
интересной информацией и файлом с паролями, но он не смог понять какой
из паролей ему нужен. Помогите ему решить эту проблему.
Алиса зашифровала свою информацию с помощью библиотеки simple-crypt.
Она представила информацию в виде строки, и затем записала в бинарный
файл результат работы метода simplecrypt.encrypt.
Вам необходимо установить библиотеку simple-crypt, и с помощью метода
simplecrypt.decrypt узнать, какой из паролей служит ключом для расшифровки
файла с интересной информацией.
Ответом для данной задачи служит расшифрованная интересная информация Алисы.
...............................
Для решения используется модуль pycryptodome и simplecrypt.py (src:
https://github.com/andrewcooke/simple-crypt/blob/master/src/simplecrypt/__init__.py )
"""
with open("data/encrypted.bin", "rb") as file:
encrypted = file.read()
with open("data/passwords.txt", encoding="UTF-8") as file:
for passwd in file:
try:
decrypted = decrypt(passwd.strip(), encrypted)
print(decrypted.decode("utf-8"))
break
except DecryptionException:
continue
except Exception:
continue
# === 2.3 Итераторы и генераторы ===
def m_2_3_1():
"""
Одним из самых часто используемых классов в Python является класс filter.
Он принимает в конструкторе два аргумента a и f – последовательность и
функцию, и позволяет проитерироваться только по таким элементам x из
последовательности a, что f(x) равно True. Будем говорить, что в этом
случае функция f допускает элемент x, а элемент x является допущенным.
В данной задаче мы просим вас реализовать класс multifilter, который будет
выполнять ту же функцию, что и стандартный класс filter, но будет
использовать не одну функцию, а несколько.
Решение о допуске элемента будет приниматься на основании того, сколько
функций допускают этот элемент, и сколько не допускают. Обозначим эти
количества за pos и neg.
Введем понятие решающей функции – это функция, которая принимает два
аргумента – количества pos и neg, и возвращает True, если элемент
допущен, и False иначе.
Рассмотрим процесс допуска подробнее на следующем примере.
a = [1, 2, 3]
f2(x) = x % 2 == 0 # возвращает True, если x делится на 2
f3(x) = x % 3 == 0
judge_any(pos, neg) = pos >= 1 # возвращает True, если хотя бы
одна функция допускает элемент
В этом примере мы хотим отфильтровать последовательность a и оставить
только те элементы, которые делятся на два или на три.
Функция f2 допускает только элементы, делящиеся на два, а функция f3
допускает только элементы, делящиеся на три. Решающая функция допускает
элемент в случае, если он был допущен хотя бы одной из функций f2 или f3,
то есть элементы, которые делятся на два или на три.
"""
class multifilter:
@staticmethod
def judge_half(pos, neg):
return pos >= neg
@staticmethod
def judge_any(pos, neg):
return pos >= 1
@staticmethod
def judge_all(pos, neg):
return neg == 0
def __init__(self, iterable, *funcs, judge=judge_any):
self.iterable = iterable
self.funcs = funcs
self.judge = judge
def __iter__(self):
for i in self.iterable:
res = [f(i) for f in self.funcs]
pos, neg = res.count(True), res.count(False)
if self.judge(pos, neg):
yield i
"""
#test
def mul2(x):
return x % 2 == 0
def mul3(x):
return x % 3 == 0
def mul5(x):
return x % 5 == 0
a = [i for i in range(31)]
print(
list(multifilter(a, mul2, mul3, mul5))
== [
0,
2,
3,
4,
5,
6,
8,
9,
10,
12,
14,
15,
16,
18,
20,
21,
22,
24,
25,
26,
27,
28,
30,
]
)
print(
list(multifilter(a, mul2, mul3, mul5, judge=multifilter.judge_half))
== [0, 6, 10, 12, 15, 18, 20, 24, 30]
)
print(list(multifilter(a, mul2, mul3, mul5, judge=multifilter.judge_all)) == [0, 30])
"""
def m_2_3_2():
"""
Целое положительное число называется простым, если оно имеет ровно два
различных делителя, то есть делится только на единицу и на само себя.
Например, число 2 является простым, так как делится только на 1 и 2.
Также простыми являются, например, числа 3, 5, 31, и еще бесконечно много
чисел. Число 4, например, не является простым, так как имеет три
делителя – 1, 2, 4. Также простым не является число 1, так как оно имеет
ровно один делитель – 1.
Реализуйте функцию-генератор primes, которая будет генерировать простые
числа в порядке возрастания, начиная с числа 2.
"""
def primes():
num = 1
while True:
num += 1
if num == 2 or all(num % div != 0 for div in range(2, int(num**0.5) + 1)):
yield num
# print(list(itertools.takewhile(lambda x: x <= 31, primes())))
# print("[2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31]")
# === 2.4 Работа с файловой системой и файлами ===
def m_2_4_1():
"""
Вам дается текстовый файл, содержащий некоторое количество непустых строк.
На основе него сгенерируйте новый текстовый файл, содержащий те же строки
в обратном порядке.
"""
input_file = "data/dataset_24465_4.txt"
ouput_file = "data/result_2_4_1.txt"
with open(input_file, encoding="UTF-8") as f, open(
ouput_file, "w", encoding="UTF-8"
) as res:
data = [line.strip() for line in f if line]
res.write("\n".join(data[::-1]))
def m_2_4_2():
"""
Вам дана в архиве (ссылка) файловая структура, состоящая из директорий
и файлов. Вам необходимо распаковать этот архив, и затем найти в данной
в файловой структуре все директории, в которых есть хотя бы один файл
с расширением ".py". Ответом на данную задачу будет являться файл со
списком таких директорий, отсортированных в лексикографическом порядке.
Для лучшего понимания формата задачи, ознакомьтесь с примером.
"""
# import os.path
dir_name = "data/main"
result = set(
os.path.relpath(curentdir, "data")
for curentdir, dirs, files in os.walk(dir_name)
if any(file.endswith(".py") for file in files)
)
with open("data/result_2_4_2.py", "w", encoding="UTF-8") as f:
f.write("\n".join(sorted(result)))
# === 2.5 Работа с функциями: functools и лямбда-функции ===
def m_2_5_1():
"""
Лямбда функции предоставляют нам удобный способ создать функцию
«прямо на месте». Но иногда, когда нужно создавать много однотипных
лямбда функций, еще удобнее будет создать функцию, которая будет
их генерировать. Реализуйте функцию mod_checker(x, mod=0), которая
будет генерировать лямбда функцию от одного аргумента y, которая будет
возвращать True, если остаток от деления y на x равен mod, и False иначе.
"""
def mod_checker(x, mod=0):
return lambda y: y % x == mod
mod_3 = mod_checker(3)
print(mod_3(3) == True)
print(mod_3(4) == False)
mod_3_1 = mod_checker(3, 1)
print(mod_3_1(4) == True)
# === 2.6 Стиль программирования: PEP 8 и документация ===