Программирование

И. В. Щуров, НИУ ВШЭ

Данный notebook является набором задач по курсу «Программирование» (Магистерская программа «Журналистика данных», НИУ ВШЭ, 2018-19).

На странице курса находятся другие материалы.

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

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

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

  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).

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

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

Запустите следующие ячейку, чтобы иметь возможность запускать тесты. Эту операцию нужно проделывать каждый раз, когда вы перезапускаете ядро. Если какой-то из тестов говорит 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

Метод .split()

На занятиях мы обсуждали списки. Один из способов создания списков, который нам будет часто нужен — разбить строку на отдельные кусочки и создать список из этих кусочков. Например:

In [ ]:
my_string = "One Two Three Four"
my_string.split()

Метод .split() относится к строкам. Если его вызывать без аргументов (вот так, с пустыми скобками), то он разбивает строку на отдельные слова (разделённые пробелами, табуляциями или переводами строк) и создаёт список из этих слов. Сама строка при этом не меняется.

In [ ]:
my_string

Если вы хотите в дальнейшем использовать получившийся список (а вы наверняка хотите, иначе зачем вы его создавали?), нужно присвоить результат выполнения .split() какой-то переменной.

In [ ]:
my_string = "One Two Three Four"
words = my_string.split()
print(words)
print("The second word is:", words[1])

Задача 1

Ввести с клавиатуры строку и вывести на экран список, состоящий из слов в этой строке. Список необходимо вывести на экран просто функцией print, так, чтобы числа вывелись через запятую и пробел, в квадратных скобках.

Примеры

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

Hello World

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

['Hello', 'World']

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

This is  a      very   test! Is it okay?

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

['This', 'is', 'a', 'very', 'test!', 'Is', 'it', 'okay?']
In [ ]:
def splitter():
    # YOUR CODE HERE
splitter()
In [ ]:
test_data = [
    ("Hello World", ['Hello', 'World']),
    ('This is  a      very   test! Is it okay?', ['This', 'is', 'a', 'very', 
                                                  'test!', 'Is', 'it', 
                                                  'okay?']),
    ('1 22 333 4444 55555', ['1', '22','333', '4444', '55555']),
    ('One', ['One'])
]

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

Задача 2

Ввести с клавиатуры строку и вывести на экран список, состоящий из слов в этой строке, кроме первого и последнего. Список необходимо вывести на экран просто функцией print, так, чтобы числа вывелись через запятую и пробел, в квадратных скобках. Если слов меньше трёх, должен быть выведен пустой список ([]).

В задаче не нужно использовать циклы.

Примеры

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

Hello Brave New World

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

['Brave', 'New']

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

This is  a      very   test! Is it okay?

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

['is', 'a', 'very', 'test!', 'Is', 'it']
In [ ]:
def no_first_last():
    # YOUR CODE HERE
no_first_last()
In [ ]:
test_data = [
    ("Hello Brave New World", ['Brave', 'New']),
    ('This is  a      very   test! Is it okay?', ['is', 'a', 'very', 
                                                  'test!', 'Is', 'it']),
    ('1 22 333 4444 55555', ['22','333', '4444']),
    ('One', []),
    ('One Two', []),
    ('One Two Three', ['Two'])
]

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

Задача 3

Ввести с клавиатуры строку s, а затем целое число n. Разбить строку на слова и вывести n'ое слово на экран. Счёт начинать с единицы, то есть если в качесвте n было введено число 1, вывести первое слово.

В задаче не нужно использовать циклы.

Примеры

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

Hello Brave New World
3

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

New

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

This is  a      very   test! Is it okay?
1

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

This
In [ ]:
def word_and_number():
    # YOUR CODE HERE
word_and_number()
In [ ]:
test_data = [
    ["This", "is", "a", "test"],
    ["Hello"],
    ["One", "two", "three"],
    ["One", "Two"] * 100
]

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

Задача 4

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

Пример

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

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("Отлично!")

Задача 5

Введите с клавиатуры строку, разбейте её на слова. Выведите список из слов, записанный в обратном порядке.

В этой задаче не нужно использовать циклы. Используйте метод списка .reverse(): изучите самостоятельно, как он работает.

Пример

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

Hello Brave New World

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

['World', 'New', 'Brave', 'Hello']
In [ ]:
def right_to_left():
    # YOUR CODE HERE
right_to_left()
In [ ]:
from ast import literal_eval

test_data = [
    (["This", "is", "a", "test"]),
    (["Hello"]),
    (["One", "two"]),
    (["One", "Two"] * 100)
]

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

Задача 6

С клавиатуры вводится строка, содержащая имена, разделённые пробелами. Для каждого имени вывести строчку

Hello, <имя>

Всего должно быть выведено столько строк, сколько имён написано в строке.

Пример

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

Alice Bob Daniel

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

Hello, Alice
Hello, Bob
Hello, Daniel

Подсказка. Здесь нужен цикл for.

In [ ]:
def hello_names():
    # YOUR CODE HERE
hello_names()
In [ ]:
from itertools import zip_longest
import re
names = ['Alice', 'Bob', 'Daniel', 'C3PO', 'Tyrion']
for i in range(1, len(names) + 1):
    cur_names = " ".join(names[:i])
    with Tester([cur_names]) as t:
        hello_names()
        assert len(t) == i
        for out, name in zip_longest(t, names[:i]):
            assert re.match("Hello, " + name + "$", out.rstrip()), "Something wrong with name " + \
                                                    name + ", expected 'Hello, " + name + \
                                                    "', got '" + out + "'"
print("Очень хорошо! Вы справились!")
In [ ]: