Добавил:
Developer Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:

Семинар №8 Задание

.pdf
Скачиваний:
31
Добавлен:
15.12.2022
Размер:
503.42 Кб
Скачать

28.11.2022, 02:19

Семинар 11 - Jupyter Notebook

Семинар №11

Во всех задачах словом «массив» обозначается объект типа np.array . Везде, где не оговорено обратное, запрещается пользоваться циклами и list comprehensions!

Задача 1

Написать функцию double_this(arr) , принимающую на вход массив arr , состоящий из чисел, и возвращающую массив, полученный удвоением каждого элемента arr .

Подсказка: Операции с массивами действуют поэлементно.

In [ ]:

# YOUR CODE HERE

In [ ]:

from timeit import timeit import numpy as np

def testme(f, inp, outp): q = f(np.array(inp))

assert isinstance(q, np.ndarray), "Функция должна возвращать массив numpy (np.array)" assert np.array_equal(q, np.array(outp)), "Ошибка для входного списка "+str(np.array(in

def test(inp, outp): testme(double_this, inp, outp)

test([1, 2, 3], [2, 4, 6])

test([1.1, 2.2, 3.3], [2.2, 4.4, 6.6]) test([1]*10, [2]*10) test([1]*10+[2]*15, [2]*10+[4]*15)

N = 1000000

benchmark = timeit("[x*x for x in np.array([1]*N)]", "from __main__ import N, np", number=1 otherbenchmark = timeit("double_this(np.array([1]*N))",

"from __main__ import N, np, double_this", number=1) print(benchmark, otherbenchmark)

assert benchmark > otherbenchmark*2, "Код работает слишком медленно — вы точно не пользовал

Задача 2

Написать функцию select_even(arr) , принимающую на вход массив целых чисел arr и возвращающую новый массив, который состоит из всех чётных элементов arr .

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

127.0.0.1:8888/notebooks/EXONTOOLS/2022/Семинар 11.ipynb

1/6

28.11.2022, 02:19

Семинар 11 - Jupyter Notebook

In [ ]:

# YOUR CODE HERE

In [ ]:

from timeit import timeit import numpy as np

def testme(f, inp, outp): q = f(np.array(inp))

assert isinstance(q, np.ndarray), "Функция должна возвращать массив numpy (np.array)" assert np.array_equal(q, np.array(outp)), "Ошибка для входного списка "+str(np.array(in

def test(inp, outp): testme(select_even, inp, outp)

test([1, 2, 3, 4, 5], [2, 4]) test([], [])

test([1, 3, 5], [])

test([5, 4, 3, 2, 0], [4, 2, 0])

test([100, 200, 300, 199, 299, 150], [100, 200, 300, 150])

N = 100000

benchmark = timeit("[x for x in np.array([1]*N) if x*2]", "from __main__ import N, np", num otherbenchmark = timeit("select_even(np.array([1]*N))",

"from __main__ import N, select_even, np", number=1) print(benchmark, otherbenchmark)

assert benchmark > otherbenchmark*2, "Код работает слишком медленновы т чно— не пользовал

# should be at least two times faster then list comprehensions

Задача 3

Написать функцию wipe_even(arr, target_value, in_place) , принимающую на вход массив целых чисел arr , и возвращающую массив, полученный из arr путём замены всех чётных элементов на target_value . Если target_value не указано, то оно должно считаться равным числу 0. Если указан параметр in_place и он равен True , то функция должна менять исходный массив, а если не указан или указан в False , то сохранять его неизменным.

In [ ]:

# YOUR CODE HERE

127.0.0.1:8888/notebooks/EXONTOOLS/2022/Семинар 11.ipynb

2/6

28.11.2022, 02:19

Семинар 11 - Jupyter Notebook

In [ ]:

from timeit import timeit import numpy as np

def test(inp, outp, target=0, in_place=False): inp = np.array(inp)

inp_backup = np.array(inp)

q = wipe_even(inp, target, in_place)

assert isinstance(q, np.ndarray), "Функция должна возвращать массив numpy (np.array)" assert np.array_equal(q, np.array(outp)), "Ошибка для входного списка "+str(np.array(in if in_place:

assert np.array_equal(inp, np.array(outp)), "Функция должна менять исходный список" else:

assert np.array_equal(inp, inp_backup), "Исходный список должен остаться неизменным

test([1, 2, 3, 4, 5], [1, 0, 3, 0, 5], in_place=True) test([], [], in_place=True)

test([1, 3, 5], [1, 3, 5], in_place=True)

test([5, 4, 3, 2, 0], [5, 0, 3, 0, 0], in_place=True)

test([100, 200, 300, 199, 299, 150], [0, 0, 0, 199, 299, 0], in_place=True) test([1, 2, 3, 4, 5], [1, 99, 3, 99, 5], target = 99, in_place=True)

N = 100000

benchmark = timeit("[0 if x*2 else x for x in np.array([1]*N)]", "from __main__ import np, N", number=1)

print(benchmark)

otherbenchmark = timeit("wipe_even(np.array([1]*N), in_place=True)",

"from __main__ import np, N, wipe_even", number=1)

print(otherbenchmark)

assert benchmark > otherbenchmark*1.5, "Код работает слишком медленно — вы точно не пользов

In [ ]:

# test not in_place behaviour now

test([1, 2, 3, 4, 5], [1, 0, 3, 0, 5]) test([], [])

test([1, 3, 5], [1, 3, 5])

test([5, 4, 3, 2, 0], [5, 0, 3, 0, 0])

test([100, 200, 300, 199, 299, 150], [0, 0, 0, 199, 299, 0])

Задача 4

Написать функцию weighted_sum(weights, grades, normalize) , возвращающую взвешенную сумму оценок, записанных в массив grades , в соответствии с весами, записанными в массив weights .

Например, для

weights = np.array([0.3, 0.3, 0.4]) и grades = np.array([7, 9, 8]) функция

должна вернуть число

.

Если параметр

normalize

установлен в True , а сумма всех весов отличается от 1, то следует

умножить все веса на одно и то же число таким образом, чтобы их сумма была равна 1, в противном случае следует использовать веса «как есть», даже если их сумма отличается от 1. Если функция запущена без указания параметра normalize , следует считать, что normalize = False .

127.0.0.1:8888/notebooks/EXONTOOLS/2022/Семинар 11.ipynb

3/6

28.11.2022, 02:19

Семинар 11 - Jupyter Notebook

Подсказка: Вам помогут функции np.dot() и np.sum() . Встроенная функция sum() также работает с массивами numpy , но гораздо медленнее (проверьте с помощью %timeit !)

In [ ]:

# YOUR CODE HERE

In [ ]:

from timeit import timeit import numpy as np

def test(w, g, out, normalize = False):

q = weighted_sum(np.array(w), np.array(g), normalize) assert np.isclose(q, out)

test([0.3, 0.3, 0.4], [7, 9, 8], 8) test([0.1, 0.2, 0.3, 0.4], [1, 5, 3, 2], 2.8) test([1, 2, 3, 4], [1, 5, 3, 2], 28)

test([1, 2, 3, 4], [1, 5, 3, 2], 2.8, normalize=True)

In [ ]:

N = 1000000

test([1, 2, 3, 4], [1, 5, 3, 2], 28)

benchmark = timeit("sum([x/x for x in np.array([1]*N)])", "from __main__ import N, np", num otherbenchmark = timeit("weighted_sum(np.array([1.1]*N), np.array([1]*N), True)",

"from __main__ import N, weighted_sum, np", number=1)

print(benchmark/otherbenchmark)

assert benchmark > otherbenchmark*1.7, "Код работает слишком медленно — вы точно использова

Задача 5

Написать функцию mean_by_gender(grades, genders) , принимающую на вход два массива одинаковой длины: в массиве grades записаны оценки некоторых студентов, а в массиве genders — их пол в виде строк male или female . Требуется вернуть словарь, ключами которого будут строки male и female , а записями — среднее арифметическое оценок студентов соответствующего пола.

Например, если grades = np.array([5, 4, 3, 5, 2]) и genders = np.array(["female", "male", "male", "female", "male"]) , функция должна вернуть словарь {'male': 3.0, 'female': 5.0} .

Подсказка. Для быстрого вычисления среднего есть функция np.mean() или соответствующий метод у объектов типа numpy.array .

In [ ]:

# YOUR CODE HERE

127.0.0.1:8888/notebooks/EXONTOOLS/2022/Семинар 11.ipynb

4/6

28.11.2022, 02:19 Семинар 11 - Jupyter Notebook

In [ ]:

from timeit import timeit import numpy as np

def test(grades, genders, outp):

ret = mean_by_gender(np.array(grades), np.array(genders)) assert np.isclose(ret['female'], outp['female'])

assert np.isclose(ret['male'], outp['male'])

test([5, 4, 3, 5, 2], ["female", "male", "male", "female", "male"], {'male': 3.0, 'female': test([1, 0]*10, ['female', 'male']*10, {'female': 1, 'male': 0})

test(range(100), ['female', 'male']* 50, {'female': 49.0, 'male': 50.0}) test(list(range(100))+[100], ['male']*100+['female'], {'male':49.5, 'female': 100.0})

# mean_by_gender(np.array(range(100)), ['female', 'male']* 50)

def benchmark_test(a, b):

xx= 0

yy= 0 im = 0 fi = 0

for x, y in zip(a, b): if x != y:

xx+= x

yy+= x

im += 1 fi += 1

return xx+yy

N = int(1E5)

grades = np.array([1.1]*N + [2.2]*N)

genders = np.array(['male']*N + ['female']*N)

benchmark = timeit("assert np.isclose(mean_by_gender(grades, genders)['male'], 1.1)", "from __main__ import np, mean_by_gender, grades, genders", number=1)

reference_benchmark = timeit("benchmark_test(grades, genders)",

"from __main__ import benchmark_test, grades, genders", number=1)

assert reference_benchmark > benchmark * 10, "Код работает слишком медленно — вы точно испо

Задача 6

В некотором царстве, в некотором государстве, налог на доходы физических лиц вычисляется следующим образом. Базовая ставка налога составляет 13%. Если в каком-то месяце ваш заработок за год составит больше тысячи тугриков, то на оставшуюся часть года (не включая этот месяц) устанавливается ставка в 20%. Например, если вы зарабатываете каждый месяц 150 тугриков, то к июлю

заработаете

тугриков и начиная с августа подоходный налог будет начисляться по

ставке 20%. Написать функцию calculate_tax(income) , принимающую на вход массив, содержащий доход за каждый месяц года, начиная с первого и возвращающую общую сумму налога, который предстоит заплатить за год. Год в некотором царстве может длиться более 12 месяцев, если по этому поводу будет принят соответствующий высочайший декрет.

Подсказка. Вам поможет функция np.cumsum() . Чтобы создать новый массив, длина которого равна длине какого-то другого, можно использовать функции np.zeros_like() или np.ones_like() .

127.0.0.1:8888/notebooks/EXONTOOLS/2022/Семинар 11.ipynb

5/6

28.11.2022, 02:19

Семинар 11 - Jupyter Notebook

In [ ]:

# YOUR CODE HERE

In [ ]:

from timeit import timeit import numpy as np

assert np.isclose(calculate_tax(np.array([150]*12)), 286.5) assert np.isclose(calculate_tax(np.array([100]*12)), 163) assert np.isclose(calculate_tax(np.array([50]*12)), 78) assert np.isclose(calculate_tax(np.array([1000]*12)), 2260)

assert np.isclose(calculate_tax(np.array(range(12))*100), 1215) assert np.isclose(calculate_tax(np.array(range(11,-1,-1))*100), 1243)

In [ ]:

def dummy(x): z = 0

for y in x: z += y

z += y*0.12 if z:

z += y

return z

assert np.isclose(calculate_tax(np.array(range(12))*100), 1215)

N = int(1E6)

arr = np.array([1]*N)

benchmark = timeit("calculate_tax(arr)", "from __main__ import calculate_tax, arr", number= reference_benchmark = timeit("dummy(arr)", "from __main__ import dummy, arr", number=1)

assert reference_benchmark > benchmark*5, "Код работает слишком медленно — вы точно использ

In [ ]:

127.0.0.1:8888/notebooks/EXONTOOLS/2022/Семинар 11.ipynb

6/6

Соседние файлы в предмете Программирование на Python