Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
30 changes: 30 additions & 0 deletions task_1.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
"""
Задание 1.
Приведен код, который позволяет сохранить в
массиве индексы четных элементов другого массива
Сделайте замеры времени выполнения кода с помощью модуля timeit
Попробуйте оптимизировать код, чтобы снизить время выполнения
Проведите повторные замеры
Добавьте аналитику: что вы сделали и почему
"""
import timeit


def func_1(nums = range(10000)):
new_arr = []
for i in range(len(nums)):
if nums[i] % 2 == 0:
new_arr.append(i)
return new_arr

def func_2(nums = range(10000)):
return [i for i in range(len(nums)) if nums[i] % 2 == 0]



print(timeit.timeit("func_1()", setup="from __main__ import func_1", number=1000))

print(timeit.timeit("func_2()", setup="from __main__ import func_2", number=1000))


# func_2() выполняется быстрее. Наверное потому, что генераторные выражения оптимизируются на уровне С-кода, на котором написан Python
49 changes: 49 additions & 0 deletions task_2.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
"""
Задание 2.

Приведен код, который формирует из введенного числа
обратное по порядку входящих в него цифр.
Задача решена через рекурсию

Сделайте замеры времени выполнения кода с помощью модуля timeit

Попробуйте оптимизировать код, чтобы снизить время выполнения
Проведите повторные замеры

Подсказка: примените мемоизацию

Добавьте аналитику: что вы сделали и почему
"""

import timeit

def memorize(func):
def g(n, memory={}):
r = memory.get(n)
if r is None:
r = func(n)
memory[n] = r
return r
return g


def recursive_reverse(number):
if number == 0:
return str(number % 10)
return f'{str(number % 10)}{recursive_reverse(number // 10)}'

@memorize
def recursive_reverse_mem(number):
if number == 0:
return str(number % 10)
return f'{str(number % 10)}{recursive_reverse(number // 10)}'


number = 100
print(timeit.timeit("recursive_reverse(number)", setup="from __main__ import recursive_reverse, number", number=1000))
print(timeit.timeit("recursive_reverse_mem(number)", setup="from __main__ import recursive_reverse_mem, number", number=1000))

"""
0.0011725
0.0001552999999999971 - При использовании меморизации выполняется на порядок быстрее из-за сохранения части результатов.
"""
69 changes: 69 additions & 0 deletions task_3.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
"""
Задание 3.

Приведен код, формирующий из введенного числа
обратное по порядку входящих в него
цифр и вывести на экран.

Сделайте профилировку каждого алгоритма через cProfile и через timeit

Сделайте вывод, какая из трех реализаций эффективнее и почему
"""
import timeit
import cProfile

def revers(enter_num, revers_num=0):
if enter_num == 0:
return
else:
num = enter_num % 10
revers_num = (revers_num + num / 10) * 10
enter_num //= 10
revers(enter_num, revers_num)


def revers_2(enter_num, revers_num=0):
while enter_num != 0:
num = enter_num % 10
revers_num = (revers_num + num / 10) * 10
enter_num //= 10
return revers_num


def revers_3(enter_num):
enter_num = str(enter_num)
revers_num = enter_num[::-1]
return revers_num

enter_num = 1000
print(timeit.timeit("revers(enter_num)", setup="from __main__ import revers, enter_num", number=1000))
print(timeit.timeit("revers_2(enter_num)", setup="from __main__ import revers_2, enter_num", number=1000))
print(timeit.timeit("revers_3(enter_num)", setup="from __main__ import revers_3, enter_num", number=1000))
"""
0.0009411999999999962
0.0006379999999999997
0.00040070000000000383 Наиболее быстрая реализация, поскоьку использует индексный доступ к массиву и не выполняет никаких математических вычислений или рекурсии
"""


def main():
enter_num = 123456789123456789
print(revers(enter_num))
print(revers_2(enter_num))
print(revers_3(enter_num))

cProfile.run('main()')
# Время выполнения модулей очень маленькое и на пофилировании его не видно
"""
Ordered by: standard name

ncalls tottime percall cumtime percall filename:lineno(function)
1 0.000 0.000 0.001 0.001 <string>:1(<module>)
19/1 0.000 0.000 0.000 0.000 task_3.py:15(revers)
1 0.000 0.000 0.000 0.000 task_3.py:25(revers_2)
1 0.000 0.000 0.000 0.000 task_3.py:33(revers_3)
1 0.000 0.000 0.001 0.001 task_3.py:49(main)
1 0.000 0.000 0.001 0.001 {built-in method builtins.exec}
3 0.001 0.000 0.001 0.000 {built-in method builtins.print}
1 0.000 0.000 0.000 0.000 {method 'disable' of '_lsprof.Profiler' objects}
"""
56 changes: 56 additions & 0 deletions task_4.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
"""
Задание 4.
Приведены два алгоритма. В них определяется число,
которое встречается в массиве чаще всего.
Сделайте профилировку каждого алгоритма через timeit
Попытайтесь написать третью версию, которая будет самой быстрой.
Сделайте замеры и опишите, получилось ли у вас ускорить задачу.
"""
import timeit

array = [1, 3, 1, 3, 4, 5, 1, 9, 9, 9, 1, 1, 1, 1, 1, 1, 8, 8, 8]


def func_1():
m = 0
num = 0
for i in array:
count = array.count(i)
if count > m:
m = count
num = i
return f'Чаще всего встречается число {num}, ' \
f'оно появилось в массиве {m} раз(а)'


def func_2():
new_array = []
for el in array:
count2 = array.count(el)
new_array.append(count2)

max_2 = max(new_array)
elem = array[new_array.index(max_2)]
return f'Чаще всего встречается число {elem}, ' \
f'оно появилось в массиве {max_2} раз(а)'

def func_3():
new_array = sorted(array)
return f'Чаще всего встречается число {new_array[0]}, ' \
f'оно появилось в массиве {new_array.count(new_array[0])} раз(а)'


print(func_1())
print(func_2())
print(func_3())


print(timeit.timeit("func_1()", setup="from __main__ import func_1", number=1000))
print(timeit.timeit("func_2()", setup="from __main__ import func_2", number=1000))
print(timeit.timeit("func_3()", setup="from __main__ import func_3", number=1000))

"""
0.004593599999999996
0.006162799999999996
0.001634499999999997 Я так понимаю, что функция sorted() реазизована на уровне С-кода и поэтому этот метод получился самым быстрым
"""
82 changes: 82 additions & 0 deletions task_5.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
"""
Задание 5.*
Приведен наивный алгоритм нахождения i-го по счёту
простого числа (через перебор делителей).

Попробуйте решить эту же задачу,
применив алгоритм "Решето эратосфена" (https://younglinux.info/algorithm/sieve)

Подсказка:
Сравните алгоритмы по времени на разных порядковых номерах чисел:
10, 100, 1000
Опишите результаты, сделайте выводы, где и какой алгоритм эффективнее
Подумайте и по возможности определите сложность каждого алгоритма
"""
import timeit
n = int(input('Введите порядковый номер искомого простого числа: '))

def simple(i):
"""Без использования «Решета Эратосфена»"""
result = []
count = 1
n = 2
while count <= i:
t = 1
is_simple = True
while t <= n:
if n % t == 0 and t != 1 and t != n:
is_simple = False
break
t += 1
if is_simple:
if count == i:
break
result.append(n)
if n >= i :
break
count += 1
n += 1
return result



def sieve_eratosthenes(n):
a = [0] * n
for i in range(n):
a[i] = i
a[1] = 0
m = 2
while m < n:
if a[m] != 0:
j = m * 2
while j < n:
a[j] = 0
j = j + m
m += 1
result = []
for i in a:
if a[i] != 0:
result.append(a[i])
return result


# Мне пришлось модифицировать ваш алгоритм, что бы он выдавал массив, как и в алгоритме "Решето эратосфена" (https://younglinux.info/algorithm/sieve)

print (f'n = {n}')
print(timeit.timeit("simple(n)", setup="from __main__ import simple, n", number=1000))
print(timeit.timeit("sieve_eratosthenes(n)", setup="from __main__ import sieve_eratosthenes, n", number=1000))
"""
n = 100
0.10930440000000097
0.024956300000001264

n = 1000
6.2776698
0.32272060000000025

n = 10000
498.0393276
3.393460300000015
"""
# Время растет нелинейно