From 7c50f9b426750e02525c24d1757ca95e8ad6c9f0 Mon Sep 17 00:00:00 2001 From: Alex Date: Sun, 15 Dec 2019 18:39:24 +0300 Subject: [PATCH 1/4] =?UTF-8?q?=D1=82=D0=B5=D1=81=D1=82=20=D0=BD=D0=B5=20?= =?UTF-8?q?=D0=BD=D1=83=D0=B6=D0=B5=D0=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- test.txt | 1 - 1 file changed, 1 deletion(-) delete mode 100644 test.txt diff --git a/test.txt b/test.txt deleted file mode 100644 index 56a6051..0000000 --- a/test.txt +++ /dev/null @@ -1 +0,0 @@ -1 \ No newline at end of file From 81307fbdeb5c3520f9f302e1867c4745854879a9 Mon Sep 17 00:00:00 2001 From: Alex Date: Mon, 16 Dec 2019 01:01:22 +0300 Subject: [PATCH 2/4] =?UTF-8?q?=D0=A1=D0=B4=D0=B5=D0=BB=D0=B0=D0=BB=20?= =?UTF-8?q?=D1=82=D0=B0=D1=81=D0=BA=E2=84=962=20=D0=B1=D0=B5=D0=B7=20?= =?UTF-8?q?=D0=B2=D1=8B=D0=B2=D0=BE=D0=B4=D0=BE=D0=B2?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- task01.py | 8 ++++ task02.py | 108 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 116 insertions(+) create mode 100644 task01.py create mode 100644 task02.py diff --git a/task01.py b/task01.py new file mode 100644 index 0000000..44d0ec1 --- /dev/null +++ b/task01.py @@ -0,0 +1,8 @@ +# Задание №1 +# Проанализировать скорость и сложность одного любого алгоритма из разработанных в рамках домашнего задания первых трех уроков. +# Примечание. Идеальным решением будет: +# ● выбрать хорошую задачу, которую имеет смысл оценивать, +# ● написать 3 варианта кода (один у вас уже есть), +# ● проанализировать 3 варианта и выбрать оптимальный, +# ● результаты анализа вставить в виде комментариев в файл с кодом (не забудьте указать, для каких N вы проводили замеры), +# ● написать общий вывод: какой из трёх вариантов лучше и почему. diff --git a/task02.py b/task02.py new file mode 100644 index 0000000..93e8fba --- /dev/null +++ b/task02.py @@ -0,0 +1,108 @@ +# Задание №2 +# Написать два алгоритма нахождения i-го по счёту простого числа. +# Функция нахождения простого числа должна принимать на вход натуральное и +# возвращать соответствующее простое число. Проанализировать скорость и +# сложность алгоритмов. + +# Вариант №1 +# Классический алгоритм Решето Эратосфена + +def get_simple_number_erato1(n): + #Функция прокалывает дырки + def prokalyvaem_dyrki(arr, n): # передаем масив и простое число + start_search = n*2 + for inx,digit in enumerate(arr[start_search::n],n): + for inx, digit in enumerate(arr[start_search::n], n): + full_inx = arr.index(digit) + if arr[full_inx] != 0: # если он не равен нулю, то + arr[full_inx] = 0 + return arr + + lst = [] + arr = [] + arr.append(0); arr.append(0) # заполняем первый и второй нулями + while len(lst) != n: + arr.append(len(arr)) + for inx,a in enumerate(arr[2:], 2): + if arr[inx] != 0: # если он не равен нулю, то мы нашли простое число и: + prokalyvaem_dyrki(arr, a) + lst = [x for x in arr if x != 0] + + return lst[-1] + + + +# Вариант №2 +# Оптимизированный алгоритм Решето Эратосфена +# Начинаем попроверять не с n*2, а с n**2 + + + +def get_simple_number_erato2(n): + #Функция прокалывает дырки + def prokalyvaem_dyrki(arr, n): # передаем масив и простое число + start_search = n**2 + for inx,digit in enumerate(arr[start_search::n],n): + for inx, digit in enumerate(arr[start_search::n], n): + full_inx = arr.index(digit) + if arr[full_inx] != 0: # если он не равен нулю, то + arr[full_inx] = 0 + return arr + + lst = [] + arr = [] + arr.append(0); arr.append(0) # заполняем первый и второй нулями + while len(lst) != n: + arr.append(len(arr)) + for inx,a in enumerate(arr[2:], 2): + if arr[inx] != 0: # если он не равен нулю, то мы нашли простое число и: + prokalyvaem_dyrki(arr, a) + lst = [x for x in arr if x != 0] + + return lst[-1] + + + +# Вариант №3 +# Поиск простых чисел не используя алгоритм Решето Эротасфена + +def get_simple_number(n): + lst = [2] + i = 3 + while len(lst) != n: + for j in lst: + if j**2-1 > i: + lst.append(i) + break + if (i % j == 0): + break + else: + lst.append(i) + i +=2 + return lst[-1] + + + +# Оцениваем алгоритмы +import timeit +import cProfile + +n = int(input("Введите порядковый номер простого числа:")) + +s = """ +num = get_simple_number_erato1(n) +""" +#print("Алгоритм Эр.№1. Простое число:", num) +print(timeit.timeit(s,number=50,globals=globals())) + +s = """ +num = get_simple_number_erato2(n) +""" +#print("Алгоритм Эр.№2. Простое число:", num) +print(timeit.timeit(s,number=50,globals=globals())) + +s = """ +num = get_simple_number(n) +""" +#print("Алгоритм не Эр. Простое число:", num) +print(timeit.timeit(s,number=50,globals=globals())) From 31691f775822e6ec4060dd0ff77b24562ef0e082 Mon Sep 17 00:00:00 2001 From: Alex Date: Mon, 16 Dec 2019 11:37:06 +0300 Subject: [PATCH 3/4] =?UTF-8?q?=D0=A1=D0=B4=D0=B5=D0=BB=D0=B0=D0=BB=202?= =?UTF-8?q?=D0=B5=20=D0=B7=D0=B0=D0=B4=D0=B0=D0=BD=D0=B8=D0=B5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- task02.py | 123 +++++++++++++++++++++++++++++++----------------------- 1 file changed, 70 insertions(+), 53 deletions(-) diff --git a/task02.py b/task02.py index 93e8fba..184f569 100644 --- a/task02.py +++ b/task02.py @@ -7,46 +7,13 @@ # Вариант №1 # Классический алгоритм Решето Эратосфена -def get_simple_number_erato1(n): - #Функция прокалывает дырки - def prokalyvaem_dyrki(arr, n): # передаем масив и простое число - start_search = n*2 - for inx,digit in enumerate(arr[start_search::n],n): - for inx, digit in enumerate(arr[start_search::n], n): - full_inx = arr.index(digit) - if arr[full_inx] != 0: # если он не равен нулю, то - arr[full_inx] = 0 - return arr - - lst = [] - arr = [] - arr.append(0); arr.append(0) # заполняем первый и второй нулями - while len(lst) != n: - arr.append(len(arr)) - for inx,a in enumerate(arr[2:], 2): - if arr[inx] != 0: # если он не равен нулю, то мы нашли простое число и: - prokalyvaem_dyrki(arr, a) - lst = [x for x in arr if x != 0] - - return lst[-1] - - - -# Вариант №2 -# Оптимизированный алгоритм Решето Эратосфена -# Начинаем попроверять не с n*2, а с n**2 - - - -def get_simple_number_erato2(n): +def get_simple_number_erato(n): #Функция прокалывает дырки def prokalyvaem_dyrki(arr, n): # передаем масив и простое число start_search = n**2 - for inx,digit in enumerate(arr[start_search::n],n): - for inx, digit in enumerate(arr[start_search::n], n): - full_inx = arr.index(digit) - if arr[full_inx] != 0: # если он не равен нулю, то - arr[full_inx] = 0 + for digit in arr[start_search::n]: + if digit != 0: # если он не равен нулю, то + arr[digit] = 0 return arr lst = [] @@ -54,16 +21,18 @@ def prokalyvaem_dyrki(arr, n): # передаем масив и простое arr.append(0); arr.append(0) # заполняем первый и второй нулями while len(lst) != n: arr.append(len(arr)) - for inx,a in enumerate(arr[2:], 2): - if arr[inx] != 0: # если он не равен нулю, то мы нашли простое число и: +# for inx,a in enumerate(arr[2:], 2): +# if arr[inx] != 0: # если он не равен нулю, то мы нашли простое число и: +# prokalyvaem_dyrki(arr, a) + for a in arr[2:]: + if a != 0: # если он не равен нулю, то мы нашли простое число и: prokalyvaem_dyrki(arr, a) lst = [x for x in arr if x != 0] return lst[-1] - -# Вариант №3 +# Вариант №2 # Поиск простых чисел не используя алгоритм Решето Эротасфена def get_simple_number(n): @@ -81,28 +50,76 @@ def get_simple_number(n): i +=2 return lst[-1] +##################### +# Результаты + +n = int(input("Введите порядковый номер простого числа:")) +num = get_simple_number_erato(n) +print("Алгоритм Эр. Простое число:", num) + +num = get_simple_number(n) +print("Алгоритм не Эр. Простое число:", num) +##################### # Оцениваем алгоритмы import timeit import cProfile -n = int(input("Введите порядковый номер простого числа:")) - +# timeit s = """ -num = get_simple_number_erato1(n) +num = get_simple_number_erato(n) """ -#print("Алгоритм Эр.№1. Простое число:", num) -print(timeit.timeit(s,number=50,globals=globals())) +print("Время Эр.:", timeit.timeit(s,number=50,globals=globals())) -s = """ -num = get_simple_number_erato2(n) -""" -#print("Алгоритм Эр.№2. Простое число:", num) -print(timeit.timeit(s,number=50,globals=globals())) s = """ num = get_simple_number(n) """ -#print("Алгоритм не Эр. Простое число:", num) -print(timeit.timeit(s,number=50,globals=globals())) +print("Время не Эр.:", timeit.timeit(s,number=50,globals=globals())) + + +######################## +# cProfile +print("Оценка Эратосвена через cProfile") +cProfile.run("get_simple_number_erato(n)") + +print("Оценка не Эратосвена через cProfile") +cProfile.run("num = get_simple_number(n)") + +# 20ое простое число +# Эр.: 0.06512603000000006 +# 851 0.001 0.000 0.001 0.000 task02.py:12(prokalyvaem_dyrki) + +# Не Эр.: 0.0037111219999999 +# 36 0.000 0.000 0.000 0.000 {built-in method builtins.len} +# 19 0.000 0.000 0.000 0.000 {method 'append' of 'list' objects} + + +# 70ое простое число +# Эр.: 1.23841424 +# 13891 0.024 0.000 0.024 0.000 task02.py:12(prokalyvaem_dyrki) + +#Не Эр.: 0.024541724999999737 +# 175 0.000 0.000 0.000 0.000 {built-in method builtins.len} +# 69 0.000 0.000 0.000 0.000 {method 'append' of 'list' objects} + + +# 120ое простое число +# Эр.: 3.9926523650000005 +# 43511 0.074 0.000 0.074 0.000 task02.py:12(prokalyvaem_dyrki) +#Не Эр.: 0.05030167399999996 +# 330 0.000 0.000 0.000 0.000 {built-in method builtins.len} +# 119 0.000 0.000 0.000 0.000 {method 'append' of 'list' objects} + +#################################### +#################################### +# Выводы +# В алгоритме Эратосфена поиск изначально ведется всех составных (не простых чисел) и потом методом исключения +# этих чисел находим все остальные (т.е. все простые) +# В алгоритме не Эратосфена поиск ведется сразу простых чисел. +# Так же алгоритм Эратосфеена адаптирован под поиск всех простых чисел в определенной +# последовательности чисел и не адаптирован для ситуации, когда изначально неизвестно какая +# это будет последовательность натуральных чисел и эта последовательность растет. Поэтому алгоритм +# пробегает множенство раз по тем натуральным числам, по которых проверка уже проводилась ранее. +# Алгоритм не Эратосфена не имеет такого недостатка, поэтому показывает значительно лучшие результаты. \ No newline at end of file From e18eee0e96af58e5f929ac411b41bf7051ad93bd Mon Sep 17 00:00:00 2001 From: Alex Date: Mon, 16 Dec 2019 13:18:01 +0300 Subject: [PATCH 4/4] =?UTF-8?q?=D0=92=D1=8B=D0=BF=D0=BE=D0=BB=D0=BD=D0=B8?= =?UTF-8?q?=D0=BB?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- task01.py | 133 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ task02.py | 1 - 2 files changed, 133 insertions(+), 1 deletion(-) diff --git a/task01.py b/task01.py index 44d0ec1..e16b85a 100644 --- a/task01.py +++ b/task01.py @@ -6,3 +6,136 @@ # ● проанализировать 3 варианта и выбрать оптимальный, # ● результаты анализа вставить в виде комментариев в файл с кодом (не забудьте указать, для каких N вы проводили замеры), # ● написать общий вывод: какой из трёх вариантов лучше и почему. + + +# Задание +# В массиве найти максимальный отрицательный элемент. Вывести на экран его значение и позицию в массиве. +# Примечание к задаче: пожалуйста не путайте «минимальный» и «максимальный отрицательный». Это два +# абсолютно разных значения. + +# Вариант №1 +# Последовательно перебираем все элементы, ищем в них отрицательные и запоминаем наиболее максимальное +def get_max_min_1(array): + max_ = None + for inx, val in enumerate(array[:-1]): + if val < 0: + if max_ is None or val > max_: + max_ = val + return max_ + + +# Вариант №2 +# Находим все отрицательные числа и находим максимальное среди них, используя встроенную функцию + +def get_max_min_2(array): + neg_array = [x for x in array if x < 0] + return max(neg_array) + + +# Вариант №3 +# Сортируем исходный массив по возврастанию и ищем методом половинного деления переход с отрицательного +# на положительное + +def get_max_min_3(array): + a = sorted(array) + pos = len(a) // 2 + while ((a[pos] >= 0 )and a[pos-1] <= 0 or a[pos] <= 0 and a[pos-1] >= 0) == False: + if a[pos] > 0: + a = a[:pos] + else: + a = a[pos:] + pos = len(a) // 2 + if a[pos] < 0: + return a[pos] + else: + return a[pos-1] + + + +##################### +# Результаты +import random + +n = int(input("Введите размер массива случайных чисел:")) + +#array = [45, 44, -47, 9, 47, -9, 44, -2, 41, 9, 11, 55, 155, 33, 0, -14] +array = [random.randint(-n,n) for _ in range(n)] +print(array) +print("Максимальное отрицательное число вар1:", get_max_min_1(array)) +print("Максимальное отрицательное число вар2:", get_max_min_2(array)) +print("Максимальное отрицательное число вар3:", get_max_min_3(array)) + +##################### +# Оцениваем алгоритмы +import timeit +import cProfile + +# timeit +s = """ +get_max_min_1(array) +""" +print("Время варианта №1:", timeit.timeit(s,number=100,globals=globals())) + +s = """ +get_max_min_2(array) +""" +print("Время варианта №2:", timeit.timeit(s,number=100,globals=globals())) + +s = """ +get_max_min_3(array) +""" +print("Время варианта №3:", timeit.timeit(s,number=100,globals=globals())) + +# cProfile +print("Оценка Вариант №1 через cProfile") +cProfile.run("get_max_min_1(array)") + +print("Оценка Вариант №2 через cProfile") +cProfile.run("get_max_min_2(array)") + +print("Оценка Вариант №3 через cProfile") +cProfile.run("get_max_min_3(array)") + +# 10000 элементов +#Время варианта №1: 0.18727370500000085 +# 1 0.002 0.002 0.002 0.002 task01.py:18(get_max_min_1) + +#Время варианта №2: 0.08653298099999951 +# 1 0.000 0.000 0.001 0.001 task01.py:30(get_max_min_2) +# 1 0.001 0.001 0.001 0.001 task01.py:31() + +#Время варианта №3: 0.21902450499999926 +# 1 0.000 0.000 0.002 0.002 task01.py:39(get_max_min_3) +# 12 0.000 0.000 0.000 0.000 {built-in method builtins.len} + +# 50000 элементов +#Время варианта №1: 0.8808438039999995 +# 1 0.009 0.009 0.009 0.009 task01.py:18(get_max_min_1) + +#Время варианта №2: 0.42420562800000017 +# 1 0.000 0.000 0.004 0.004 task01.py:30(get_max_min_2) +# 1 0.003 0.003 0.003 0.003 task01.py:31() + +#Время варианта №3: 2.334317992 +# 1 0.001 0.001 0.024 0.024 task01.py:39(get_max_min_3) +# 15 0.000 0.000 0.000 0.000 {built-in method builtins.len} + +# 100000 элементов +#Время варианта №1: 2.0827101420000007 +# 1 0.021 0.021 0.021 0.021 task01.py:18(get_max_min_1) + +#Время варианта №2: 0.9937122910000005 +# 1 0.000 0.000 0.010 0.010 task01.py:30(get_max_min_2) +# 1 0.008 0.008 0.008 0.008 task01.py:31() + +#Время варианта №3: 6.081710614 +# 1 0.002 0.002 0.060 0.060 task01.py:39(get_max_min_3) +# 15 0.000 0.000 0.000 0.000 {built-in method builtins.len} + +#################################### +#################################### +# Выводы +# Самый эффективный по времени - алгоритм №2, который максимально использует встроенные +# механизмы - генератор с фильтрацией и функцию нахождения максимального числа. Алгоритм №1 проигрывает +# ему в 2 раза, Алгоритм №3 - проигрывает в 6 раз. Причем Алгоритм №6 c увеличением размера исходного +# массива начинает проигрывать больше diff --git a/task02.py b/task02.py index 184f569..a6cd954 100644 --- a/task02.py +++ b/task02.py @@ -79,7 +79,6 @@ def get_simple_number(n): print("Время не Эр.:", timeit.timeit(s,number=50,globals=globals())) -######################## # cProfile print("Оценка Эратосвена через cProfile") cProfile.run("get_simple_number_erato(n)")