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

Подсказка:
1) возьмите 2-3 задачи, реализованные ранее, сделайте замеры на разных входных данных
2) сделайте для каждой из задач оптимизацию (придумайте что можно оптимизировать)
и также выполните замеры на уже оптимизированных алгоритмах
3) опишите результаты - где, что эффективнее и почему.

ВНИМАНИЕ: ЗАДАНИЯ, В КОТОРЫХ БУДУТ ГОЛЫЕ ЦИФРЫ ЗАМЕРОВ (БЕЗ АНАЛИТИКИ)
БУДУТ ПРИНИМАТЬСЯ С ОЦЕНКОЙ УДОВЛЕТВОРИТЕЛЬНО
"""

import timeit
import sys

"""
Анализ скорости и сложности алгоритма определения суммы n элементов
следующего ряда чисел: 1 -0.5 0.25 -0.125 ...
"""

"""
Реализация №1.
"""

print(f'\nЗамер выполнения кода через цикл')
print('Метод <<timeit>>')


def cycle_method(n_count):
    """Цикл"""
    numb = 1
    iterator = 0
    common_sum = 0
    while iterator < n_count:
        common_sum += numb
        numb = numb / 2 * -1
        iterator += 1
    return common_sum


LAUNCH_LST = [1, 1000, 10000, 100000]  # массив запусков программы
for i in LAUNCH_LST:
    print(f'Число запусков кода = {i}. Время выполнения операции = ', end=' ')
    print(
        timeit.timeit(
            'cycle_method(1000)',
            setup='from __main__ import cycle_method',
            number=i))

sys.setrecursionlimit(10000)

"""
Реализация №2.
"""

print(f'\nЗамер выполнения кода через рекурсию')
print('Метод <<timeit>>')


def recur_method(iterator, numb, n_count, common_sum):
    """Рекурсия"""
    if iterator == n_count:
        pass
    elif iterator < n_count:
        return recur_method(iterator + 1, numb / 2 * -1, n_count, common_sum + numb)


for i in LAUNCH_LST:
    print(f'Число запусков кода = {i}. Время выполнения операции = ', end=' ')
    print(
        timeit.timeit(
            'recur_method(0, 1, 1000, 0)',
            setup='from __main__ import recur_method',
            number=i))

"""
Рассмотрел два варианта кода:
- решение через цикл
- решение через рекурсию
В обоих случаях рассчет велся до 1000 элемента ряда

При замере времени через рекурсию пришлось увеличивать глубину рекурсивных вызовов.
Из-за стека вызовов при вычислении времени через рекурсию время выполнения
увеличивается в среднем на 40..46% (при числе запусков программы = 100 000)
"""

'''
Результаты вычислений

Замер выполнения кода через цикл
Метод <<timeit>>
Число запусков кода = 1. Время выполнения операции =  0.0006134890000000018
Число запусков кода = 1000. Время выполнения операции =  0.421530368
Число запусков кода = 10000. Время выполнения операции =  4.522955281000001
Число запусков кода = 100000. Время выполнения операции =  44.504740463000005

Замер выполнения кода через рекурсию
Метод <<timeit>>
Число запусков кода = 1. Время выполнения операции =  0.0010934319999975628
Число запусков кода = 1000. Время выполнения операции =  0.768235261000001
Число запусков кода = 10000. Время выполнения операции =  7.746048587000004
Число запусков кода = 100000. Время выполнения операции =  78.252791003
'''
