Семинар №8 Задание
.pdf28.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 |