Домашнее задание №3

Формат задания и некоторые задачи заимствованы из домашнего задания по курсу «Введение в программирование» (Магистерская программа «Журналистика данных», НИУ ВШЭ, 2017-18).

За разные задачи можно получить разное число баллов. Если не указано обратное, задача весит 1 балл. Максимум за ДЗ можно набрать 9 баллов. Вы можете решить больше задач, чем требуется, чтобы потренироваться.

Для предварительной проверки задания нужно сделать следующее:

  1. Скачать данный ipynb-файл на свой компьютер, открыть его в IPython Notebook/Jupyter.
  2. Активировать тесты (см. ниже).
  3. Вставить решение каждой задачи в ячейку для кода, следующую за его условием, там, где написан комментарий # YOUR CODE HERE. Отступ вашего кода должен составлять 4 пробела. Ничего не менять вокруг!
  4. Запустить ячейку, в которую вы вставили код с решением. Ввести какие-то входные данные, проверить визуально правильность вывода.
  5. Запустить следующую ячейку (в ней содержится тест). Если запуск ячейки с тестом не приводит к появлению ошибки (assertion), значит, всё в порядке, задача решена. Если приводит к появлению ошибки, значит, тест не пройден и нужно искать ошибку.

Внимание! Если в какой-то момент забыть ввести входные данные и перейти на следующую ячейку, есть риск, что Notebook перестанет откликаться. В этом случае надо перезапустить ядро: Kernel → Restart. При этом потеряются все значения переменных, но сам код останется.

Чтобы сдать ДЗ, его надо загрузить в nbgr-x в виде ipynb-файла. Получить ipynb-файл можно, выбрав в Jupyter пункт меню File → Download as... → IPython Notebook (.ipynb).

Активировать тесты

Запустите следующие ячейку, чтобы иметь возможность запускать тесты. Эту операцию нужно проделывать каждый раз, когда вы перезапускаете ядро. Если какой-то из тестов говорит NameError: name 'Tester' is not defined, нужно запустить эту ячейку ещё раз.

In [ ]:
# Фабрика тестов для проверки программ, принимающих данные через 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

Задача 1

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

Пример.

Входные данные:

Москва,Мясницкая,20

Выходные данные:

['Москва', 'Мясницкая', '20']
In [ ]:
def address():
    # YOUR CODE HERE
address()
In [ ]:
test_data = [
    ("Москва,Мясницкая,20", ["Москва", "Мясницкая", "20"]),
    ("Санкт-Петербург,Кантемировская,3", ["Санкт-Петербург", "Кантемировская", "3"]),
    ("Пермь,Студенческая,38", ["Пермь", "Студенческая", "38"])]

for inp, out in test_data:
    with Tester([inp]) as t:
        address()
        assert len(t) == 1, "Вам нужно вывести ровно одну строку с ответом"
        assert t[0].rstrip() == repr(out), (
            "Неверный ответ для входной строки {}, "
            "ожидалось {}, получено {}".format(inp, repr(out), t[0]))

Задача 2

Дан список станций желтой ветки московского метро (упорядочены как на карте):

line = ["Третьяковская", "Марксистская", "Площадь Ильича", "Авиамоторная", "Шоссе Энтузиастов",
"Перово", "Новогиреево", "Новокосино"]

Давайте считать, что движение происходит от Третьяковской до Новокосино.

Напишите программу, которая запрашивает у пользователя название текущей станции метро (без лишнего пробела на конце) и выводит на экран сообщение вида

Следующая станция: станция.

Считайте, что пользователь знает, какая станция конечная, и не будет запрашивать станцию, следующую после Новокосино.

Пример:

Входные данные:

Введите текущую станцию: Площадь Ильича

Выходные данные:

Следующая станция: Авиамоторная

Подсказка:

Чтобы вернуть индекс определенного элемента в списке, нужно воспользоваться методом .index().

In [ ]:
def metro():
    line = ["Третьяковская", "Марксистская", "Площадь Ильича", "Авиамоторная", "Шоссе Энтузиастов",
    "Перово", "Новогиреево", "Новокосино"]
    # YOUR CODE HERE

metro()
In [ ]:
test_data = [
    ("Третьяковская", "Следующая станция: Марксистская"),
    ("Марксистская", "Следующая станция: Площадь Ильича"),
    ("Площадь Ильича", "Следующая станция: Авиамоторная"),
    ("Авиамоторная", "Следующая станция: Шоссе Энтузиастов"),
    ("Шоссе Энтузиастов","Следующая станция: Перово"),
    ("Перово", "Следующая станция: Новогиреево"),
    ("Новогиреево", "Следующая станция: Новокосино")
]

for inp, out in test_data:
    with Tester([inp]) as t:
        metro()
        assert len(t) == 1, "Вам нужно вывести ровно одну строку с ответом"
        assert t[0] == out+"\n", "Неверный ответ, была введена строка " + inp

Задача 3

Напишите программу, которая запрашивает у пользователя номер мобильного телефона в формате X-XXX-XXX-XX-XX-XX и выводит на экран номер в формате X(XXX)XXX-XX-XX.

Пример:

Входные данные:

Введите номер телефона: 8-906-000-11-22

Выходные данные:

8(906)000-11-22
In [ ]:
def phone():
    # YOUR CODE HERE
    
phone()
In [ ]:
test_data = [
    ("8-906-000-11-22", "8(906)000-11-22"),
    ("1-234-000-17-82", "1(234)000-17-82"),
    ("7-190-904-88-00", "7(190)904-88-00")
]

for inp, out in test_data:
    with Tester([inp]) as t:
        phone()
        assert len(t) == 1, "Вам нужно вывести ровно одну строку с ответом"
        assert t[0] == out+"\n", "Неверный ответ, была введена строка " + inp

Задача 4

Дан список с названиями файлов:

files = ['file 1.txt', 'file 2.txt', 'file 6.txt', 'file 9.txt']

Напишите программу, которая переименовывает файлы в списке ‒ заменяет все пробелы на нижнее подчеркивание ‒ и выводит обновленный список files на экран.

Пример:

Входные данные:

files = ['file 1.txt', 'file 2.txt', 'file 6.txt', 'file 9.txt']

Выходные данные:

files = ['file_1.txt', 'file_2.txt', 'file_6.txt', 'file_9.txt']

Подсказка: вам потребуется цикл и метод .replace() для строк.

In [ ]:
def frename():
    files = ['file 1.txt', 'file 2.txt', 'file 6.txt', 'file 9.txt']
    # YOUR CODE HERE
    
    return files
frename()    
In [ ]:
files = ['file_1.txt', 'file_2.txt', 'file_6.txt', 'file_9.txt']

t = frename()

assert t == files,"Неверный ответ" 

Задача 5

Введите с клавиатуры две строки. Разбейте первую строку на слова и добавьте в конец получившегося списка вторую строку целиком. Выведите получившийся список.

Пример

Входные данные

Hello Brave New World
This is a test

Выходные данные

['Hello', 'Brave', 'New', 'World', 'This is a test']
In [ ]:
def add_string():
    # YOUR CODE HERE
add_string()
In [ ]:
from ast import literal_eval

test_data = [
    (["This", "is", "a", "test"], "This is a test"),
    (["Hello"], "World"),
    (["One", "two"], "three four"),
    (["One", "Two"] * 100, "   ".join("this"))
]

for words, word in test_data:
    with Tester(["  ".join(words), word]) as t:
        add_string()
        assert len(t) == 1, "Вам нужно вывести ровно одну строку с ответом"
        assert literal_eval(t[0]) == words + [word], (
            "Неверный ответ для входных данных\n{}\n"
            "ожидалось {}, получено {}".format(
                "  ".join(words)+"\n" + word + "\n", 
                repr(words + [word]), t[0]))
print("Отлично!")

Задача 6

Даны два целых числа A и B (при этом A≤B). Каждое число вводится с клавитуры, после ввода пользователь нажимает «Enter». Выведите все целые числа от A до B включительно в столбик.

Здесь имеет смысл использовать цикл for (хотя в принципе можно обойтись и без него).

Пример

Входные данные

3
6

Выходные данные

3
4
5
6
In [ ]:
def my_range():
    # YOUR CODE HERE

my_range()
In [ ]:
test_data = [
    ["2 4", "2 3 4"],
    ["1 10", "1 2 3 4 5 6 7 8 9 10"],
    ["0 0", "0"],
    ["-5 0", "-5 -4 -3 -2 -1 0"],
    ["1 1", "1"],
    ["0 100", '0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100']
]

for inp, out in test_data:
    with Tester(inp.split()) as t:
        my_range()
        assert len(t) == len(out.split()), 'Вы вывели неверное количество чисел для входных данных ' + inp
        for o, e in zip(t, out.split()):
            assert int(o) == int(e), "Неверный ответ для входных данных " + inp

Задача 7

Напишите программу, которая запрашивает целое число n с клавиатуры, затем n целых чисел, после чего выводит произведение всех этих чисел.

Пример.

Входные данные:

3
9
2
5

Выходные данные:

90
In [ ]:
def prod_n():
    # YOUR CODE HERE
prod_n()
In [ ]:
test_data = [
    ("3 9 2 5", 90),
    ("1 1", 1),
    ("2 0 10", 0),
    ("2 10 0", 0),
    ("10 1 2 3 4 5 6 7 8 9 10", 3628800),
    ("5 -1 -1 -1 -1 -1", -1)
]

for inp, out in test_data:
    with Tester(inp.split()) as t:
        prod_n()
        assert len(t) == 1, "Вам нужно вывести ровно одну строку с ответом"
        assert t[0].strip() == str(out), "Неверный ответ, были введены числа " + inp
print("Ура, всё верно!")

Задача 8 (2 балла)

Факториалом натурального числа $n$ называется произведение всех натуральных чисел от 1 до $n$ включительно. Факториал $n$ обозначается $n!$. Например, $$ 4! = 1 \times 2 \times 3 \times 4 = 24. $$ Написать программу, запрашивающую натуральное число $n$ с клавиатуры, вычисляющую и печатающую $n!$. Использовать какие-либо библиотечные функции нельзя (то есть запрещена конструкция import).

Пример.

Входные данные:

5

Выходные данные:

120
In [ ]:
def my_fact():
    # YOUR CODE HERE

my_fact()
In [ ]:
test_data = [
    ("1", 1),
    ("2", 2),
    ("3", 6),
    ("4", 24),
    ("5", 120),
    ("10", 3628800),
    ("20", 2432902008176640000)
]

for inp, out in test_data:
    with Tester([inp]) as t:
        my_fact()
        assert len(t) == 1, "Вам нужно вывести ровно одну строку с ответом"
        assert t[0].strip() == str(out), "Неверный ответ, были введены числа " + inp
print("Хорошо, давайте теперь что-нибудь посложнее решим!")

Задача 9 (2 балла)

Числа Фибоначчии — это последовательность чисел, заданная следующим образом:

$$a_1 = 1,\quad a_2 = 1, \quad a_{k+1}=a_k+a_{k-1}$$

Ввести число k с клавиатуры и вывести $a_k$. Считать, что число k всегда больше одного. (То есть на вход никогда не будет подано число, меньшее или равное одного.)

Пример.

Входные данные:

3

Выходные данные:

2

Входные данные:

5

Выходные данные:

5

Входные данные:

6

Выходные данные:

8
In [ ]:
def fib_k():
    # YOUR CODE HERE
fib_k()
In [ ]:
test_data = [(33, 3524578),
 (87, 679891637638612258),
 (66, 27777890035288),
 (43, 433494437),
 (44, 701408733),
 (19, 4181),
 (98, 135301852344706746049),
 (65, 17167680177565),
 (32, 2178309),
 (11, 89)]
for inp, out in test_data:
    with Tester([str(inp)]) as t:
        fib_k()
        assert len(t) == 1, "Вам нужно вывести ровно одну строку с ответом"
        assert t[0].strip() == str(out), ("Неверный ответ, было "
                                          "введено число " + str(inp) + 
                                         " ожидалось " + str(out))
print("Ура, всё верно!")

Задача 10 (3 балла)

Введите число n с клавиатуры. Выведите таблицу умножения от 1 до n включительно, как показано в примере.

Пример

Входные данные

5

Выходные данные

1 2 3 4 5 
2 4 6 8 10 
3 6 9 12 15 
4 8 12 16 20 
5 10 15 20 25 
In [ ]:
def mult_table():
    # YOUR CODE HERE
mult_table()
In [ ]:
def mult_table():
    n = int(input("Введите n: "))
    
    c = list(range (n))
    c.append (n)
    c.pop(0)
    
    
    for i in c:
        for j in c:
            print (i*j)
        print()    
        
mult_table()
In [ ]:
test_data = [(1, ['1 \n']),
 (4, ['1 2 3 4 \n', '2 4 6 8 \n', '3 6 9 12 \n', '4 8 12 16 \n']),
 (7,
  ['1 2 3 4 5 6 7 \n',
   '2 4 6 8 10 12 14 \n',
   '3 6 9 12 15 18 21 \n',
   '4 8 12 16 20 24 28 \n',
   '5 10 15 20 25 30 35 \n',
   '6 12 18 24 30 36 42 \n',
   '7 14 21 28 35 42 49 \n']),
 (10,
  ['1 2 3 4 5 6 7 8 9 10 \n',
   '2 4 6 8 10 12 14 16 18 20 \n',
   '3 6 9 12 15 18 21 24 27 30 \n',
   '4 8 12 16 20 24 28 32 36 40 \n',
   '5 10 15 20 25 30 35 40 45 50 \n',
   '6 12 18 24 30 36 42 48 54 60 \n',
   '7 14 21 28 35 42 49 56 63 70 \n',
   '8 16 24 32 40 48 56 64 72 80 \n',
   '9 18 27 36 45 54 63 72 81 90 \n',
   '10 20 30 40 50 60 70 80 90 100 \n']),
 (13,
  ['1 2 3 4 5 6 7 8 9 10 11 12 13 \n',
   '2 4 6 8 10 12 14 16 18 20 22 24 26 \n',
   '3 6 9 12 15 18 21 24 27 30 33 36 39 \n',
   '4 8 12 16 20 24 28 32 36 40 44 48 52 \n',
   '5 10 15 20 25 30 35 40 45 50 55 60 65 \n',
   '6 12 18 24 30 36 42 48 54 60 66 72 78 \n',
   '7 14 21 28 35 42 49 56 63 70 77 84 91 \n',
   '8 16 24 32 40 48 56 64 72 80 88 96 104 \n',
   '9 18 27 36 45 54 63 72 81 90 99 108 117 \n',
   '10 20 30 40 50 60 70 80 90 100 110 120 130 \n',
   '11 22 33 44 55 66 77 88 99 110 121 132 143 \n',
   '12 24 36 48 60 72 84 96 108 120 132 144 156 \n',
   '13 26 39 52 65 78 91 104 117 130 143 156 169 \n'])]

for inp, out in test_data:
    with Tester([str(inp)]) as t:
        mult_table()
        line_t = "".join(t)
        t = line_t.splitlines()
        assert len(t) == len(out), "Неверное количество строк в выводе"
        for l_test, l_out in zip(t, out):
            assert len(l_test.split()) == len(l_out.split()), \
                "Неверное количество элементов в строке " + l_out
            for el_test, el_out in zip(l_test.split(), l_out.split()):
                assert el_test == el_out, "Ошибка {} != {}".format(l_test, 
                                                                   l_out)
print("Теперь вы можете печатать тетрадки для школьников!")