+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/passwords.txt b/passwords.txt
new file mode 100644
index 0000000..e69de29
diff --git a/task1.py b/task1.py
new file mode 100644
index 0000000..7734d79
--- /dev/null
+++ b/task1.py
@@ -0,0 +1,95 @@
+"""
+Задание 1.
+Реализуйте свои пользовательские функции, в которых реализуйте:
+a) заполнение списка и словаря,
+ сделайте замеры и сделайте выводы, что выполняется быстрее и почему
+b) выполните набор операций и со списком, и со словарем,
+ сделайте замеры и сделайте выводы, что и где выполняется быстрее и почему
+Подсказка: для замеров воспользуйтесь модулем time (см. примеры урока 1)
+Примечание: eсли вы уже знаете, что такое декоратор и как его реализовать,
+то реализуйте ф-цию-декоратор для подсчета времени работы ваших пользовательских функций
+И примените ее к своим функциям!
+Прошу вас внимательно читать ТЗ и не забыть выполнить все пункты.
+"""
+
+# Заполнение словаря на очень больших числах выполняется медленее, чем заполнение списка.
+# Однако остальные функции во много раз, а то и на несколько порядков, быстрее.
+# Связанно это с тем, что при заполнении словаря происходит хэширование данных,
+# что помогает обращаться к его элементам сразу по ключам, в то время как в случае со списком,
+# этот процесс занимает куда больше времени, потому что запрашиваемый элемент приходится искать перебором.
+
+
+from time import perf_counter
+
+
+def time_measure(func):
+ def measure(x, num):
+ start = perf_counter()
+ for _ in range(num):
+ func(x)
+ end = perf_counter()
+ print(f'{func} - {end - start}')
+ return measure
+
+
+@time_measure
+def fulfill_lst(lst):
+ for i in range(1000000):
+ lst.append(i)
+
+
+@time_measure
+def fulfill_dct(dct):
+ for i in range(1000000):
+ dct[i] = i
+
+
+@time_measure
+def delete_lst(lst):
+ for i in range(100000):
+ lst.remove(i)
+
+
+@time_measure
+def delete_dct(dct):
+ for i in range(100000):
+ del dct[i]
+
+
+@time_measure
+def pop_lst(lst):
+ return lst.pop()
+
+
+@time_measure
+def pop_dct(dct):
+ for i in range(200000, 300000):
+ return dct.pop(i)
+
+
+@time_measure
+def search_lst(lst):
+ return 400000 in lst
+
+
+@time_measure
+def search_dct(dct):
+ return 400000 in dct
+
+
+lst_a = []
+for i in range(1000000):
+ lst_a.append(i)
+
+dct_a = {}
+for i in range(1000000):
+ dct_a[i] = i
+
+fulfill_lst([], 10000)
+fulfill_dct({}, 10000)
+delete_lst(lst_a, 1)
+delete_dct(dct_a, 1)
+pop_lst(lst_a, 100000)
+pop_dct(dct_a, 1)
+search_lst(lst_a, 1000)
+search_dct(dct_a, 1000)
\ No newline at end of file
diff --git a/task2.py b/task2.py
new file mode 100644
index 0000000..898091d
--- /dev/null
+++ b/task2.py
@@ -0,0 +1,35 @@
+"""
+Задание 2.
+Ваша программа должна запрашивать пароль
+Для этого пароля вам нужно получить хеш, используя функцию sha256
+Для генерации хеша обязательно нужно использовать криптографическую соль
+Обязательно выведите созданный хеш.
+Далее программа должна запросить пароль повторно
+Вам нужно проверить, совпадает ли пароль с исходным
+Для проверки необходимо сравнить хеши паролей
+ПРИМЕР:
+Введите пароль: 123
+В базе данных хранится строка: 555a3581d37993843efd4eba1921f1dcaeeafeb855965535d77c55782349444b
+Введите пароль еще раз для проверки: 123
+Вы ввели правильный пароль
+Обязательно усложните задачу! Добавьте сохранение хеша в файле и получение его из файла.
+А если вы знаете как через Python работать с БД, привяжите к заданию БД и сохраняйте хеши там.
+"""
+
+from hashlib import sha256
+from uuid import uuid4
+
+
+def check_password():
+ salt = uuid4().hex
+ password_hash = sha256(salt.encode() + input('Введите пароль: ').encode()).hexdigest()
+ with open('passwords.txt', 'a') as f:
+ f.write(password_hash + '\n')
+ print(f'В базе данных хранится строка: {password_hash}')
+ with open('passwords.txt', 'r') as f:
+ if f.readlines()[-1][:-1] == sha256(salt.encode() + input('Введите пароль ещё раз: ').encode()).hexdigest():
+ print('Вы ввели правильный пароль!')
+
+
+check_password()
+
diff --git a/task3.py b/task3.py
new file mode 100644
index 0000000..4f10432
--- /dev/null
+++ b/task3.py
@@ -0,0 +1,26 @@
+"""
+Задание 3.
+Определить количество различных (уникальных) подстрок с использованием хеш-функции.
+Дана строка S длиной N, состоящая только из строчных латинских букв.
+Подсказка: примените вычисление хешей для подстрок с помощью хеш-функций и множества
+Можно воспользоваться ф-цией hash() (см. материалы к уроку)
+Пример:
+рара - 6 уникальных подстрок
+рар
+ра
+ар
+ара
+р
+а
+"""
+
+
+def all_substrings(string):
+ answer = set()
+ for i in range(len(string)):
+ for j in range(i + 1, len(string) + 1):
+ answer.add(hash(string[i:j]))
+ print(f'Общее количество подстрок: {len(answer) - 1}')
+
+
+all_substrings('papa')
\ No newline at end of file
diff --git a/task4.py b/task4.py
new file mode 100644
index 0000000..45d0be0
--- /dev/null
+++ b/task4.py
@@ -0,0 +1,41 @@
+"""
+Задание 4.
+Реализуйте скрипт "Кэширование веб-страниц"
+Функция должна принимать url-адрес и проверять
+есть ли в кэше соответствующая страница, если нет, то вносить ее в кэш
+Подсказка: задачу решите обязательно с применением 'соленого' хеширования и хеш-таблиц
+Можете условжнить задачу, реализовав ее через ООП
+Не забудьте, что кэширование - механизм, а хеш-таблица - средство его реализации.
+Задание творческое. Здесь нет жестких требований к выполнению.
+"""
+
+from hashlib import sha256
+from uuid import uuid4
+
+
+class UrlCash:
+
+ cash = {}
+ salts = []
+
+ def __init__(self, url):
+ self.salt = uuid4().hex
+ self.salts.append(self.salt)
+ self.url = sha256(self.salt.encode() + url.encode()).hexdigest()
+ self.cash[self.url] = url
+
+
+def cash_check():
+ url = input('Введите url: ') # для удобства тестирования
+ for salt in UrlCash.salts:
+ if sha256(salt.encode() + url.encode()).hexdigest() in UrlCash.cash:
+ return
+ UrlCash(url)
+ #print(UrlCash.cash)
+
+
+cash_check()
+#cash_check()
+#cash_check()
+#cash_check()
+#cash_check()
\ No newline at end of file