diff --git a/task_1.py b/task_1.py new file mode 100644 index 00000000..8235e33a --- /dev/null +++ b/task_1.py @@ -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 diff --git a/task_2.py b/task_2.py new file mode 100644 index 00000000..dacc8712 --- /dev/null +++ b/task_2.py @@ -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 - При использовании меморизации выполняется на порядок быстрее из-за сохранения части результатов. +""" diff --git a/task_3.py b/task_3.py new file mode 100644 index 00000000..661399c6 --- /dev/null +++ b/task_3.py @@ -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 :1() + 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} +""" \ No newline at end of file diff --git a/task_4.py b/task_4.py new file mode 100644 index 00000000..00f57e58 --- /dev/null +++ b/task_4.py @@ -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() реазизована на уровне С-кода и поэтому этот метод получился самым быстрым +""" \ No newline at end of file diff --git a/task_5.py b/task_5.py new file mode 100644 index 00000000..cf24e3fe --- /dev/null +++ b/task_5.py @@ -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 +""" +# Время растет нелинейно +