И. В. Щуров, НИУ ВШЭ
Авторы задач в подборке: Ф. Тюрин, И. Щуров.
Часть задач на numpy
взята отсюда, автор подборки: Евгений Ковалёв.
На странице курса находятся другие материалы.
За разные задачи можно получить разное число баллов. Если не указано обратное, задача весит 1 балл. Максимум за ДЗ можно набрать 23 балла. Вы можете решить больше задач, чем требуется, чтобы потренироваться.
Для предварительной проверки задания нужно сделать следующее:
ipynb
-файл на свой компьютер, открыть его в IPython Notebook/Jupyter.Внимание! Если в какой-то момент забыть ввести входные данные и перейти на следующую ячейку, есть риск, что Notebook перестанет откликаться. В этом случае надо перезапустить ядро: Kernel → Restart. При этом потеряются все значения переменных, но сам код останется.
Чтобы сдать ДЗ, его надо загрузить в nbgr-x в виде ipynb
-файла. Получить ipynb
-файл можно, выбрав в Jupyter пункт меню File → Download as... → IPython Notebook (.ipynb).
Запустите следующие ячейку, чтобы иметь возможность запускать тесты. Эту операцию нужно проделывать каждый раз, когда вы перезапускаете ядро. Если какой-то из тестов говорит NameError: name 'Tester' is not defined
, нужно запустить эту ячейку ещё раз.
# Фабрика тестов для проверки программ, принимающих данные через input()
from collections import deque
class Tester(object):
def __init__(self, inp):
self.outputs = []
self.inputs = deque(inp)
def print(self, *args, sep = " ", end = "\n"):
text = sep.join(map(str, args)) + end
newlines = text.splitlines(keepends=True)
if self.outputs and self.outputs[-1] and self.outputs[-1][-1] != "\n" and newlines:
self.outputs[-1] += newlines[0]
self.outputs.extend(newlines[1:])
else:
self.outputs.extend(newlines)
def input(self, *args):
assert self.inputs, "Вы пытаетесь считать больше элементов, чем предусмотрено условием"
return self.inputs.popleft()
def __enter__(self):
global print
global input
print = self.print
input = self.input
return self.outputs
def __exit__(self, *args):
global print
global input
del print
del input
Написать функцию sum_ints_in_file(filename)
, принимающую на вход имя файла, содержащего целые числа (каждое число на новой строке, некоторые строки могут быть пустыми). Функция должна вернуть сумму этих чисел.
Не забудьте закрыть файл!
# YOUR CODE HERE
try:
del open
except:
pass
from tempfile import NamedTemporaryFile
import os
testsuite = [([1, 2, 3]),
([5]),
([111, 23, 123]),
([0]),
([-1, -10, -123]),
(0, -1, 1, 100, 500, 9999)]
for testlist in testsuite:
try:
f = NamedTemporaryFile(dir='.', delete=False, mode='w')
name = f.name
f.file.write("\n".join(map(str, testlist)))
f.file.close()
assert sum_ints_in_file(name) == sum(testlist)
finally:
os.remove(name)
import io
test_txt = io.StringIO("1\n2\n")
def get_test_txt():
return test_txt
def open(file, mode = 'r', *args, **kwargs):
return get_test_txt()
try:
s = sum_ints_in_file("test.txt")
assert test_txt.closed, "Вы забыли закрыть файл"
assert s == 3
finally:
del open
try:
f = NamedTemporaryFile(dir='.', delete=False, mode='w')
name = f.name
f.file.write("1\n2\n\n")
f.file.close()
assert sum_ints_in_file(name) == 3
except:
print("Ошибка! Обратите внимание: файл может содержать пустые строки.")
raise
finally:
os.remove(name)
Написать функцию censore_haha(filename)
, считывающую файл с именем, лежащем в переменной filename
и записывающим его в новый файл, имя которого получается добавлением к концу имени исходного файла .censored.txt
. При записи в новый файл все вхождения слова haha
должны быть заменены на [censored]
.
Например, если функция была вызвана как censore_haha('test.txt')
, она должна создать файл test.txt.censored.txt
и записать в него отцензурированную версию исходного файла.
# YOUR CODE HERE
from tempfile import NamedTemporaryFile
import os
def test_censore(inp, outp):
try:
f = NamedTemporaryFile(dir='.', delete=False, mode='w')
name = f.name
f.file.write(inp)
f.file.close()
censore_haha(f.name)
with open(f.name + ".censored.txt") as f:
content = f.read()
assert content == outp, ("input file: {inp}, "
"expected output: {outp} "
"obtained output: {content}".format(
inp=inp, outp=outp, content=content
))
finally:
os.remove(name)
test_censore(
"haha test\nanother haha haha test\nhahahaha hahahaha\n"
"this is a test\nwell",
("[censored] test\nanother [censored] [censored] test\n"
"[censored][censored] [censored][censored]\nthis is a test\nwell")
)
test_censore(
(
"this is a haha haha haha\n"
"haha ha ha hahahahahaha ha haha\n"
"\n"
"ha\n"
"ha\n"
"\n"
"thisisahahahathis\n"
"well...\n"
"\n"
"Hello, world!\n"
),
(
"this is a [censored] [censored] [censored]\n"
"[censored] ha ha [censored][censored][censored] ha [censored]\n"
"\n"
"ha\n"
"ha\n"
"\n"
"thisisa[censored]hathis\n"
"well...\n"
"\n"
"Hello, world!\n"
)
)
Написать функцию three_best_applicants(portfolio)
, принимающую на вход имя файла с портфолио в формате, аналогичном этому файлу, и возвращающую список фамилий и имён трёх лучших абитуриентов, упорядоченных по числу набранных ими баллов (по убыванию). Каждый элемент возвращаемого списка должен был кортежем, в котором на первом месте стоит фамилия студента, а на втором — его имя. В файле идет сначала имя, потом фамилия, а потом число баллов, причём между именем и фамилией стоит пробел, а между фамилием и числом баллов — символ табуляции (\t
).
# YOUR CODE HERE
from tempfile import NamedTemporaryFile
import os
def test_portfolio(inp, outp):
try:
f = NamedTemporaryFile(dir='.', delete=False, mode='w')
name = f.name
f.file.write(inp)
f.file.close()
obtained = three_best_applicants(f.name)
assert obtained == outp, ("input file: {inp}, "
"expected output: {outp} "
"obtained output: {obtained}").format(
inp=inp, outp=outp, obtained=obtained)
finally:
os.remove(name)
test_portfolio(
"""Ann Brown\t25
Emily Calvert\t89
Alice Charr\t78
Bill Taylor\t94
Polly Smith\t32
Jill Acker\t68
Tom Bass\t15
Victoria Greg\t48
Philipp Pruitt\t65
Cristine Evans\t82
""",[('Taylor', 'Bill'), ('Calvert', 'Emily'), ('Evans', 'Cristine')])
test_portfolio(
"""Ann Brown\t125
Emily Calvert\t89
Alice Charr\t78
Bill Taylor\t94
Polly Smith\t932
Victoria Greg\t648
Philipp Pruitt\t65
Cristine Evans\t82
""",[('Smith', 'Polly'), ('Greg', 'Victoria'), ('Brown', 'Ann')])
Функция save_bill(clientname, cart, filename)
принимает на вход имя клиента, список покупок cart, состоящий из трехэлементных кортежей вида (название товара, количество, цена за единицу)
, и имя файла filename
. Функция должна создать файл, имя которого указано в переменной filename
с чеком по заданному образцу и ничего не возвращать. Все числа должны выводиться в файл с двумя значащами цифрами после десятичной точки. Например, save_bill('Alice', [('Oil', 2, 100.11), ('Bread', 0.345, 90), ('Milk', 1, 50.32)], "somefile.txt")
должна создать файл somefile.txt
со следующим содержимым:
Client name: Alice
Oil x 2.00: 200.22
Bread x 0.34: 31.05
Milk x 1.00: 50.32
Total: 281.59
Подсказка. Записать число с двумя знаками после десятичной точки можно так:
"{:.2f}".format(12.345)
А ещё подставить значение переменной в строку можно так:
x = 12.345
f"{x:.2f}
# YOUR CODE HERE
from tempfile import NamedTemporaryFile
import os
testsuite = [("Alice", [('Oil', 2, 100.11), ('Bread', 0.345, 90),
('Milk', 1, 50.32)],
('Client name: Alice\n\nOil x 2.00: 200.22\nBread'
' x 0.34: 31.05\nMilk x 1.00: 50.32\n\nTotal: 281'
'.59')),
("Bill Clinton", [('Thing', 1, 10),
('Other thing', 1.234, 32.32)],
('Client name: Bill Clinton\n\nThing x 1.00: 10.0'
'0\nOther thing x 1.23: 39.88\n\nTotal: 49.88')),
("Claudia", [('This', 1.3, 2.12),
('This', 1.6, 2.12)],
('Client name: Claudia\n\nThis x 1.30: 2.76\nThis'
' x 1.60: 3.39\n\nTotal: 6.15'))
]
for clientname, cart, output in testsuite:
f = NamedTemporaryFile(dir='.', delete=False)
name = f.name
f.close()
try:
save_bill(clientname, cart, name)
with open(name) as f:
collected_output = f.read().strip()
assert collected_output == output.strip(), (collected_output, output.strip())
finally:
os.remove(name)
Во всех задачах словом «массив» обозначается объект типа np.array
. Везде, где не оговорено обратное, запрещается пользоваться циклами и list comprehensions!
Написать функцию double_this(arr)
, принимающую на вход массив arr
, состоящий из чисел, и возвращающую массив, полученный удвоением каждого элемента arr
.
Подсказка: Операции с массивами действуют поэлементно.
Ещё подсказка: Нужно считать, что arr
уже является np.array
, преобразовывать его к этому типу не нужно. Например, для проверки вашей функции нужно запускать что-то вроде
dobule_this(np.array([1, 2, 3]))
# YOUR CODE HERE
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(inp))
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)
assert benchmark > otherbenchmark*2, "Код работает слишком медленно — вы точно не пользовались циклами?"
Написать функцию select_even(arr)
, принимающую на вход массив целых чисел arr
и возвращающую новый массив, который состоит из всех чётных элементов arr
.
Подсказка: напомним, что все арифметические операции, а также операции сравнения, действуют на массивы поэлементно.
# YOUR CODE HERE
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(inp))
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", number=1)
otherbenchmark = timeit("select_even(np.array([1]*N))",
"from __main__ import N, select_even, np", number=1)
assert benchmark > otherbenchmark*2, "Код работает слишком медленно — вы точно не пользовались циклами?"
# should be at least two times faster than list comprehensions
Напишите функцию closest_value(array, value)
, вычисляющую самое близкое и самое дальнее числа к данному в рассматриваемом массиве чисел. Например, если на вход поступают массив array([0, 1, 2, 3, 4])
и число 1.33, то ответом будет (1, 4)
. Функция должна возвращать кортеж из двух элементов.
Подсказка: Вам может пригодиться функция np.argmax()
.
# YOUR CODE HERE
assert closest_value(np.array([0, 1, 2, 3, 4]), 1.33) == (1, 4)
assert closest_value(np.array([0]), 0) == (0, 0)
assert closest_value(np.array([1, 1.1, 1.11, 1.111, 1.1111]), 100) == (1.1111, 1)
assert closest_value(np.array([-100, 400, 100500]), 0) == (-100, 100500)
Написать функцию wipe_even(arr, target_value, in_place)
, принимающую на вход массив целых чисел arr
, и возвращающую массив, полученный из arr
путём замены всех чётных элементов на target_value
. Если target_value
не указано, то оно должно считаться равным числу 0. Если указан параметр in_place
и он равен True
, то функция должна менять исходный массив, а если не указан или указан в False
, то сохранять его неизменным.
Подсказка. Чтобы получить копию исходного массива можно использовать метод .copy()
.
# YOUR CODE HERE
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(inp))
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)
otherbenchmark = timeit("wipe_even(np.array([1]*N), in_place=True)",
"from __main__ import np, N, wipe_even", number=1)
assert benchmark > otherbenchmark*1.5, "Код работает слишком медленно — вы точно не пользовались циклами?"
Написать функцию weighted_sum(weights, grades, normalize)
, возвращающую взвешенную сумму оценок, записанных в массив grades
, в соответствии с весами, записанными в массив weights
. Например, для weights = np.array([0.3, 0.3, 0.4])
и grades = np.array([7, 9, 8])
функция должна вернуть число $0.3\times 7+0.3\times 9+0.4\times 8=8.0$.
Если параметр normalize
установлен в True
, а сумма всех весов отличается от 1, то следует умножить все веса на одно и то же число таким образом, чтобы их сумма была равна 1, в противном случае следует использовать веса «как есть», даже если их сумма отличается от 1. Если функция запущена без указания параметра normalize
, следует считать, что normalize = False
.
Подсказка: Вам помогут функции np.dot()
и np.sum()
. Встроенная функция sum()
также работает с массивами numpy
, но гораздо медленнее (проверьте с помощью %timeit
!)
# YOUR CODE HERE
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)
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", number=1)
otherbenchmark = timeit("weighted_sum(np.array([1.1]*N), np.array([1]*N), True)",
"from __main__ import N, weighted_sum, np", number=1)
assert benchmark > otherbenchmark*1.7, "Код работает слишком медленно — вы точно использовали методы numpy?"
Написать функцию find_max(matrix)
, принимающую на вход двумерный массив matrix
и возвращающую массив, элементами которого являются максимальные значения столбцов matrix
.
Подсказка: Для поиска максимума можно воспользоваться функцией np.amax()
. Разберитесь самостоятельно, как она работает.
# YOUR CODE HERE
assert (find_max(np.array([[9, 9, 4], [8, 8, 1], [5, 3, 6], [3, 3, 3], [2, 1, 9]])) == np.array([9, 9, 9])).all()
assert (find_max(np.array([[0, 1, 2], [3, 4, 5], [6, 7, 8]])) == np.array([6, 7, 8])).all()
assert (find_max(np.array([[0, 1, 2], [3, 0, 5], [6, 7, 1]])) == np.array([6, 7, 5])).all()
assert (find_max(np.array([[-10, 1, 2, 5], [3, 30, 5, 17], [-100, -100, -100, 100], [1, 1, 2, -80]])) ==
np.array([3, 30, 5, 100])).all()
assert (find_max(np.array([[1]])) == np.array([1])).all()
Напишите функцию diag_prod(matrix)
, вычисляющую произведение всех ненулевых диагональных элементов на диагонали данной квадратной матрицы. Например, если на вход (в виде двумерного массива) поступает матрица
$$
\begin{pmatrix}
0 & 1 & 2\\
3 & 4 & 5\\
6 & 7 & 8\\
\end{pmatrix},
$$
то ответом будет 32. Гарантируется, что на диагонали матрицы будет хотя бы один ненулевой элемент.
Подсказка. Функции, которые могут пригодиться при решении: .diag()
, .prod()
.
# YOUR CODE HERE
assert diag_prod(np.array([[0, 1, 2], [3, 4, 5], [6, 7, 8]])) == 32
assert diag_prod(np.array([[0, 1, 2], [3, 0, 5], [6, 7, 1]])) == 1
assert diag_prod(np.array([[-10, 1, 2, 5], [3, 30, 5, 17], [-100, -100, -100, 100], [1, 1, 2, -80]])) == -2400000
assert diag_prod(np.array([[1]])) == 1
Напишите функцию make_symmetric(matrix)
, делающую данную треугольную матрицу симметричной. Например, если на вход (в виде двумерного массива) поступает матрица
$$
\begin{pmatrix}
1 & 2 & 3 & 4\\
0 & 5 & 6 & 7\\
0 & 0 & 8 & 9\\
0 & 0 & 0 & 10\\
\end{pmatrix},
$$
то на выходе (тоже в виде двумерного массива) должна быть матрица
$$
\begin{pmatrix}
1 & 2 & 3 & 4\\
2 & 5 & 6 & 7\\
3 & 6 & 8 & 9\\
4 & 7 & 9 & 10\\
\end{pmatrix}.
$$
Использовать условные операторы и циклы нельзя.
# YOUR CODE HERE
assert (make_symmetric(np.array([[1, 2, 3, 4], [0, 5, 6, 7], [0, 0, 8, 9], [0, 0, 0, 10]])) ==
np.array([[1, 2, 3, 4], [2, 5, 6, 7], [3, 6, 8, 9], [4, 7, 9, 10]])).all()
assert (make_symmetric(np.array([[0, 0, 0, 0], [0, 9, 8, 0], [0, 0, -100, -1000], [0, 0, 0, 999]])) ==
np.array([[0, 0, 0, 0], [0, 9, 8, 0], [0, 8, -100, -1000], [0, 0, -1000, 999]])).all()
assert (make_symmetric(np.array([[1]])) == np.array([[1]])).all()
Напишите функцию rref(matr)
, принимающую на вход массив matrix
размером $m\times n$, где $m\leq n$, элементами которого являются целые числа, и возвращающую его приведенный ступенчатый вид по строкам. Преобразовывать массив можно путем складывания (и вычитания) строк и умножения их на скаляр. Пользоваться любыми библиотечными функциями, связанными с линейной алгеброй (помимо Numpy
) запрещено.
Подсказка: Помните, что при делении целого числа на другое целое число не всегда может получиться целое число, поэтому обращайте внимание на тип чисел в массиве.
Примеры
Вызов функции
rref(np.array([[2, 3]]))
Возвращаемое значение
array([[1. , 1.5]])
Вызов функции
rref([[1, 3, 1, 9], [1, 1, -1, 1], [3, 11, 5, 35]])
Возвращаемое значение
array([[ 1., 0., -2., -3.],
[-0., 1., 1., 4.],
[ 0., 0., 0., 0.]])
# YOUR CODE HERE
assert((rref(np.array([[1, 3, 1, 9], [1, 1, -1, 1], [3, 11, 5, 35]])) ==
np.array([[1, 0, -2, -3], [0, 1, 1, 4], [0, 0, 0, 0]], dtype=np.float)).all())
assert((rref(np.array([[1]])) == np.array([[1]], dtype=np.float)).all())
assert((rref(np.array([[0]])) == np.array([[0]], dtype=np.float)).all())
assert((rref(np.array([[1, 1], [1, 1]])) == np.array([[1, 1], [0, 0]], dtype=np.float)).all())
assert((rref(np.array([[-1, -2, -3, -4], [1, 1, 1, 1], [0, 0, 3, 9], [-15, -14, -13, -12]])) ==
np.array([[1, 0, 0, 1], [0, 1, 0, -3], [0, 0, 1, 3], [0, 0, 0, 0]], dtype=np.float)).all())
Написать функцию 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
.
# YOUR CODE HERE
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': 5.0})
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, "Код работает слишком медленно — вы точно использовали методы numpy?"
В некотором царстве, в некотором государстве, налог на доходы физических лиц вычисляется следующим образом. Базовая ставка налога составляет 13%. Если в каком-то месяце ваш заработок за год составит больше тысячи тугриков, то на оставшуюся часть года (не включая этот месяц) устанавливается ставка в 20%. Например, если вы зарабатываете каждый месяц 150 тугриков, то к июлю заработаете $150\times 7 = 1050$ тугриков и начиная с августа подоходный налог будет начисляться по ставке 20%. Написать функцию calculate_tax(income)
, принимающую на вход массив, содержащий доход за каждый месяц года, начиная с первого и возвращающую общую сумму налога, который предстоит заплатить за год. Год в некотором царстве может длиться более 12 месяцев, если по этому поводу будет принят соответствующий высочайший декрет.
Подсказка. Вам поможет функция np.cumsum()
. Чтобы создать новый массив, длина которого равна длине какого-то другого, можно использовать функции np.zeros_like()
или np.ones_like()
.
# YOUR CODE HERE
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)
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=1)
reference_benchmark = timeit("dummy(arr)", "from __main__ import dummy, arr", number=1)
assert reference_benchmark > benchmark*5, "Код работает слишком медленно — вы точно использовали методы numpy?"