Статистика и открытые данные

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

Авторы задач в подборке: А. Зотов, И. Щуров.

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

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

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

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

  1. Скачать данный ipynb-файл на свой компьютер, открыть его в IPython Notebook/Jupyter.
  2. Активировать тесты (см. ниже).
  3. Запустить ячейку, в которую вы вставили код с решением.
  4. Запустить следующую ячейку (в ней содержится тест). Если запуск ячейки с тестом не приводит к появлению ошибки (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 (1 балл)

Написать функцию dear(lastname), принимающую на вход строку lastnames, содержащую некоторые фамилии, разделённые пробелами. Создать и вернуть список, элементами которого являются строки вида "Dear <фамилия>!".

В задаче требуется использовать списковые включения (list comprehensions), иначе она не будет засчитана при ручной проверке.

Пример.

dear("Snow Lannister Stark") == ["Dear Snow!", "Dear Lannister!", "Dear Stark!"]
In [ ]:
# YOUR CODE HERE
In [ ]:
test_data = ["Snow Lannister Stark", "Bush Clinton Bush Trump",
            "Smith Smith", ("Potter Weasley Granger " * 1000).strip()]

assert dear("Snow Lannister Stark") == ["Dear Snow!", 
                                        "Dear Lannister!", 
                                        "Dear Stark!"]
assert dear("Smith Smith") == ['Dear Smith!'] * 2
assert dear(("Potter Weasley Granger " * 1000).strip()) == ["Dear Potter!",
                                                            'Dear Weasley!',
                                                            'Dear Granger!'
                                                           ] * 1000
print('Окей')

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

Функция glue_names(first_names, last_names) принимает на вход два списка: один с именами, другой с фамилиями. Она должна вернуть список строк, получающихся в результате «склеивания» имён с фамилиями (через пробел). Например, glue_names(['Bill', 'Hillary', 'Donald', 'Melania'], ['Clinton', 'Clinton', 'Trump', 'Trump']) должна вернуть список ["Bill Clinton", "Hillary Clinton", "Donald Trump", "Melania Trump"]. Реализовать такую функцию.

Здесь требуется использовать списковые включения и zip().

In [ ]:
# YOUR CODE HERE
In [ ]:
assert (glue_names(['Bill', 'Hillary', 'Donald', 'Melania'], 
                  ['Clinton', 'Clinton', 'Trump', 'Trump']) == 
        ["Bill Clinton", "Hillary Clinton", "Donald Trump", "Melania Trump"])
assert glue_names(['Haha', 'Hoho'], ['Zzz', 'Yyy']) == ['Haha Zzz', 'Hoho Yyy']
assert glue_names(['A'], ['B']) == ['A B']
print("Ага!")

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

Написать функцию transpose(table), принимающую на вход таблицу в виде списка списков table и возвращающую транспонированную таблицу, то есть такую, в которой строчки исходной таблицы записаны по столбцам. Возвращаемая таблица также должна быть записана в виде списка списков — кортежи не допускаются. Например, transpose([[1, 2, 3], [4, 5, 6], [7, 8, 9]) должна вернуть [[1,4,7],[2,5,8],[3,6,9]], а transpose([[1,2,3,4]]) возвращает [[1],[2],[3],[4]].

In [ ]:
# YOUR CODE HERE
In [ ]:
assert transpose([[1, 2, 3], [4, 5, 6], [7, 8, 9]])==[[1,4,7],[2,5,8],[3,6,9]]
assert transpose([[1, 2, 3, 4]])==[[1], [2], [3], [4]]
assert transpose([[1,2,3,4], [5,6,7,8]])==[[1,5],[2,6], [3,7], [4,8]]

def check_idemp(t):
    assert transpose(transpose(t))==t

check_idemp([[1,2],['Hello', 'World']])
check_idemp([[1]*100, [2]*100, [3]*100])
print("Хорошо, теперь вы знаете, как транспонировать таблицу!")

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

Написать функцию my_map(f, some_list), которая принимает на вход функцию f и список some_list и возвращает новый список, полученный путём применения функции f к каждому элементу списка some_list. Например, my_map(str, [1, 2, 3]) должен вернуть список, получающийся как [str(1), str(2), str(3)], то есть ['1', '2', '3'].

In [ ]:
# YOUR CODE HERE
In [ ]:
assert my_map(str, [1, 2, 3]) == ['1', '2', '3']
assert my_map(int, ['12', '34', '56', '789']) == [12, 34, 56, 789]
assert my_map(lambda x: x + 1, [1, 2, 3, 4]) == [2, 3, 4, 5]
assert my_map(None, []) == []
assert my_map(lambda x: x, list(range(10000))) == list(range(10000))
print("Хорошо! Кстати, примерно то же самое делает встроенная функция map")

Задача 5 (1 балл)

Написать функцию first_str(words), принимающую на вход список строк и возвращающую ту из них, которая будет идти первой при упорядочивании по алфавиту.

Подсказка. Хотите отсортировать весь список и взять его первый элемент? Это не самое лучшее решение: для сортировки всего списка понадобится много времени, если он большой, а вас интересует лишь самый «маленький» его элемент. Попробуйте исползовать функцию min() — посмотрите, можно ли ей скормить строки вместо чисел. Использовать библиотеки нельзя.

In [ ]:
# YOUR CODE HERE
In [ ]:
from random import shuffle, seed
seed(0)
def shuffle_test(f, inp, outp, n=10):
    for i in range(n):
        shuffle(inp)
        assert f(inp)==outp
def test(inp,outp, n=10):
    return shuffle_test(first_str, inp, outp)

test(['Hello'], 'Hello')
test(['Hello', 'World'], 'Hello')
test(['hello', 'World'], 'World')
test(['a','b','c','d','e'], 'a', 20)
test(['hello']*100+['World'], 'World')
test(['a', 'aa', 'aaa', 'aaaa'], 'a')
test(['q', 'ww', 'eee', 'zzzzz'], 'eee')


del shuffle, seed, shuffle_test, test
print("Верно!")

Задача 6 (1 балл)

Написать функцию get_first_student_grade(students), принимающую на вход список students, каждый элемент которого является кортежем: первый элемент кортежа является именем студента, а второй его оценкой. Например: students = [('Bob', 3), ('Alice', 4)]. Функция должна вернуть оценку студента, имя которого является первым при алфавитной сортировке. (В нашем случае должна вернуть число 4.) Все студенты имеют разные имена.

Подсказка. См. подсказку к задаче 5. Возможно, функции min() удастся скормить кортежи? Попробуйте! Кстати, задача решается ровно в одну строчку (не считая def). Использовать библиотеки нельзя.

In [ ]:
# YOUR CODE HERE
In [ ]:
from random import shuffle, seed
seed(0)
def shuffle_test(f, inp, outp, n=10):
    for i in range(n):
        shuffle(inp)
        assert f(inp)==outp
def test(inp,outp, n=10):
    return shuffle_test(get_first_student_grade, inp, outp)
test([('Bob', 3), ('Alice', 4)], 4)
test([('Zzz', 1)], 1)
test([('Haha', 2), ('Hoho', 3), ('Zzz', 4), ('aaaa', 5)], 2)

del shuffle, seed, shuffle_test, test
print("Хорошо, поехали дальше!")

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

Написать функцию get_name_of_best_student(students), принимающую на вход список students, каждый элемент которого является кортежем: первый элемент кортежа является именем студента, а второй его оценкой. Например: students = [('Bob', 3), ('Alice', 4)]. Функция должна вернуть имя студента с наибольшей оценкой. Если таких студентов несколько, она должна вернуть имя того из них, кто первый встречается в списке students (в том порядке, в котором этот список передан). Например, для списка [('Bob', 4), ('Alice', 4)] необходимо вернуть 'Bob', а для списка [('Alice', 4), ('Bob', 4)] вернуть 'Alice'.

Подсказка. У функций min() и max() есть необязательный параметр key, работающий так же, как и у функции sort(). К чему бы это? Кстати, задачу можно (и нужно) решить без циклов и условных операторов.

In [ ]:
# YOUR CODE HERE
In [ ]:
assert get_name_of_best_student([('Bob', 4), ('Alice', 4)]) == 'Bob'
assert get_name_of_best_student([('Alice', 4), ('Bob', 4)]) == 'Alice'
assert get_name_of_best_student([('Zzz', 3), ('Bob', 4), ('Alice', 4)]) == 'Bob'
assert get_name_of_best_student([('Alice', 4), ('Zzz', 3), ('Bob', 4)]) == 'Alice'
assert get_name_of_best_student([('Zzz', 5), ('Bob', 4), ('Alice', 4)]) == 'Zzz'
assert get_name_of_best_student([('Alice', 4), ('Zzz', 5), ('Bob', 4)]) == 'Zzz'
assert get_name_of_best_student([('Alice', 4), ('Zzz', 5), ('Bob', 4), ('Zzz', 5)]) == 'Zzz'
assert get_name_of_best_student([('Alice', 4), ('Zzz', 5), ('Bob', 4), ('Zzz', 3)]) == 'Zzz'
assert get_name_of_best_student([('Alice', 0)]) == 'Alice'
print("Отлично!")

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

Написать функцию sort_by_last_name(names), которая на вход принимает список строк с именами и фамилиями (например, ["Donald Trump", "Hillary Clinton", "Gary Johnson", "Jill Stein", "Darrell Castle", "Evan McMullin"]), сортирующую его по фамилиям и возвращающую в отсортированном виде. (Можно менять исходный список.) Для указанного выше списка функция должна вернуть список ['Darrell Castle', 'Hillary Clinton', 'Gary Johnson', 'Evan McMullin', 'Jill Stein', 'Donald Trump']. Порядок записей с одинаковыми фамилиями должен сохраняться. Например, для списка ["Alice Smith", "John Doe", "Jack Doe"] должно быть возвращено ["John Doe", "Jack Doe", "Alice Smith"].

Подсказка. Вам нужно будет написать функцию, получающую на вход элемент списка names (то есть одну строку с именем и фамилией) и возвращающую фамилию. Затем эту функцию необходимо передать функции sorted в качестве параметра key.

In [ ]:
# YOUR CODE HERE
In [ ]:
from random import shuffle, seed
seed(0)
def shuffle_test(f, inp, outp, n=10):
    for i in range(n):
        shuffle(inp)
        assert f(inp)==outp
def test(inp,outp, n=10):
    return shuffle_test(sort_by_last_name, inp, outp)

test(["Donald Trump", "Hillary Clinton", "Gary Johnson", "Jill Stein", "Darrell Castle", "Evan McMullin"],
     ['Darrell Castle', 'Hillary Clinton', 'Gary Johnson', 'Evan McMullin', 'Jill Stein', 'Donald Trump'])
assert sort_by_last_name(["Aaa Aaa", "Aaa Bbb", "Bbb Aaa"]) == ["Aaa Aaa", "Bbb Aaa", "Aaa Bbb"]
assert sort_by_last_name(["Aaa Bbb", "Bbb Aaa", "Aaa Aaa"]) == ["Bbb Aaa", "Aaa Aaa", "Aaa Bbb"]
assert sort_by_last_name(["Alice Smith", "John Doe", "Jack Doe"]) == ["John Doe", "Jack Doe", "Alice Smith"]

del shuffle, seed, shuffle_test, test
print("Не так уж это было и страшно, да?")

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

Написать функцию sort_by_last_first_name(names), которая на вход принимает список строк с именами и фамилиями, сортирующую его по фамилии, а при совпадении фамилий — по именам, и возвращающую в отсортированном виде. (Можно менять исходный список.) Например, для списка ["Alice Smith", "John Doe", "Jack Doe"] должно быть возвращено ["Jack Doe", "John Doe", "Alice Smith"].

In [ ]:
# YOUR CODE HERE
In [ ]:
from random import shuffle, seed
seed(0)
def shuffle_test(f, inp, outp, n=10):
    for i in range(n):
        shuffle(inp)
        assert f(inp)==outp
def test(inp,outp, n=10):
    return shuffle_test(sort_by_last_first_name, inp, outp)

test(["Donald Trump", "Hillary Clinton", "Gary Johnson", "Jill Stein", "Darrell Castle", "Evan McMullin"],
     ['Darrell Castle', 'Hillary Clinton', 'Gary Johnson', 'Evan McMullin', 'Jill Stein', 'Donald Trump'])
test(["Donald Trump", "Melania Trump", "Hillary Clinton", "Bill Clinton", 
      "Gary Johnson", "Jill Stein", "Darrell Castle", "Evan McMullin"],
     ['Darrell Castle', "Bill Clinton", 'Hillary Clinton', 'Gary Johnson', 'Evan McMullin', 
      'Jill Stein', 'Donald Trump', "Melania Trump"])
test(["Aaa Aaa", "Aaa Bbb", "Bbb Aaa"],  ["Aaa Aaa", "Bbb Aaa", "Aaa Bbb"])
test(["Alice Smith", "John Doe", "Jack Doe"], ["Jack Doe", "John Doe", "Alice Smith"])

del shuffle, seed, shuffle_test, test
print("Хорошо!")

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

Написать функцию sort_gradebook(gradebook), принимающую на вход некую ведомость в виде списка, элементами которого являются списки такого вида: [first_name, last_name, grade_1, grade_2, ..., grade_n, final_grade], где first_name — имя студента, last_name — его фамилия, grade_1, ..., grade_n — оценки студента по контрольным от 1 до n (число n — общее число контрольных, оно одинаковое для конкретного gradebook, но заранее не известно), final_grade — итоговая оценка. Функция должна отсортировать gradebook следующим образом (и вернуть его отсортированным):

  • По итоговой оценке;
  • При совпадении итоговой оценки — по оценке за первую контрольную;
  • При совпадении всего предыдущего — по оценке за вторую контрольную;
  • При совпадении всего предыдущего — по оценке за третью контрольную (и т.д. пока контрольные не закончатся);
  • При совпадении всех оценок — по фамилии;
  • При совпадении всех оценок и фамилии — по имени.

Сортировки по оценкам производятся по убыванию, по фамилии по возрастанию, по имени — по убыванию.

Примеры см. в тестах.

Подсказка. Если при сортировке списка с ключом получаются одинаковые ключи, то порядок следования элементов сохраняется. Ключом может быть не только число или строка, но и список.

In [ ]:
# YOUR CODE HERE
In [ ]:
from itertools import permutations
def test_sort(inp, outp):
    for i in permutations(inp):
        assert sort_gradebook(list(i)) == outp, i

test_sort([
        ['Alice', 'Smith', 2, 3, 4],
        ['John', 'Smith', 2, 3, 5]
    ], [
        ['John', 'Smith', 2, 3, 5],
        ['Alice', 'Smith', 2, 3, 4]
])

test_sort([
        ['Alice', 'Smith', 2, 3, 4],
        ['John', 'Smith', 2, 3, 4]
    ], [
    ['John', 'Smith', 2, 3, 4],
    ['Alice', 'Smith', 2, 3, 4],    
])

test_sort([
        ['Alice', 'Smith', 1, 3, 4],
        ['John', 'Smith', 2, 3, 4]
        ], [
        ['John', 'Smith', 2, 3, 4],
        ['Alice', 'Smith', 1, 3, 4]
])

test_sort([
            ['Alice', 'Smith', 1, 1, 1, 3, 4],
            ['John', 'Smith', 1, 1, 2, 3, 4]],
                         [
            ['John', 'Smith', 1, 1, 2, 3, 4],
            ['Alice', 'Smith', 1, 1, 1, 3, 4]
])

test_sort([
            ['Alice', 'Doe', 1, 1, 3, 3, 4],
            ['Alice', 'Smith', 1, 1, 3, 3, 4],
            ['John', 'Smith', 1, 1, 2, 3, 4]], 
          [
            ['Alice', 'Doe', 1, 1, 3, 3, 4],
            ['Alice', 'Smith', 1, 1, 3, 3, 4],
            ['John', 'Smith', 1, 1, 2, 3, 4]
])

test_sort([
        ['Alice', 'Doe', 1, 1, 3, 3, 4],
        ['Alice', 'Smith', 1, 1, 3, 3, 4],
        ['John', 'Smith', 2, 1, 2, 3, 4]], 
          [
        ['John', 'Smith', 2, 1, 2, 3, 4],
        ['Alice', 'Doe', 1, 1, 3, 3, 4],
        ['Alice', 'Smith', 1, 1, 3, 3, 4],
])

del test_sort
print("Это была непростая задача!")

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

Функция get_most_ooo_word(words) принимает на вход строчку, содержащую слова, разделенные пробелами или символами перевода строки (одним или несколькими) и возвращает список из тех слов, в которых число букв o максимально. Например, get_most_ooo_word('aa ao oa aaaooo aooqq aoooq') должна вернуть ['aaaooo', 'aoooq']. Порядок слов в возвращаемом списке должен соответствовать порядку слов в исходной строке. Написать такую функцию.

Подсказка. Посчитать, сколько раз подстрока встречается в строке, можно с помощью метода count().

In [ ]:
# YOUR CODE HERE
In [ ]:
assert get_most_ooo_word(" ".join(['aa', 'ao', 'oa', 'aaaooo', 'aooqq', 'aoooq'])) == ['aaaooo', 'aoooq']
assert get_most_ooo_word(" \n  ".join(['aa', 'bb', 'ccc'])) == ['aa', 'bb', 'ccc']
assert get_most_ooo_word("   \n".join(['aa', 'bb', 'ccc', 'o'])) == ['o']
assert get_most_ooo_word(" ".join(['o', 'oo', 'o', 'ooo', 'o', 'ooo', 'o', 'aooo'])) == ['ooo', 'ooo', 'aooo']
loremipsum = """
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor 
incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis 
nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.
Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore 
eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, 
sunt in culpa qui officia deserunt mollit anim id est laborum
"""
assert get_most_ooo_word(loremipsum) == ['commodo']
print("ОК!")

Задача 12 (1 балл)

Написать функцию Dan_5(grades), принимающую на вход словарь grades, добавляющую в него запись с ключом "Dan" и значением 5 и возвращающую этот словарь.

Подсказка. Код должен начинаться со строчки

def Dan_5(grades):

и заканчиваться строчкой

return grades
In [ ]:
# YOUR CODE HERE
In [ ]:
assert Dan_5({})=={'Dan':5}
assert Dan_5({'Dan':3})=={'Dan':5}
assert Dan_5({'Alice':2}) == {'Alice': 2, 'Dan': 5}
assert Dan_5({1:2,3:4,'Dan':'Dan',5:'Dan'}) == {1:2, 3:4, 'Dan': 5, 5: 'Dan'}

Задача 13 (1 балл)

Написать функцию Dan_plus_1(grades), которая принимает на вход словарь grades, после чего меняет его следующим образом. Если в этом словаре имеется запись с ключом "Dan", то её значение должно быть увеличено на 1. Если такой записи нет, она должна быть создана и ей должно быть присвоено значение 1. Функция должна вернуть получающийся словарь. Гаранируется, что в словаре grades все ключи являются строками, а все значения — целыми числами (проверять это не нужно).

In [ ]:
# YOUR CODE HERE
In [ ]:
assert Dan_plus_1({}) == {'Dan': 1}
assert Dan_plus_1({'Dan': 3}) == {'Dan': 4}
assert Dan_plus_1({'Alice': 4})=={'Alice': 4,'Dan': 1}
assert Dan_plus_1({'Alice': 4, 'Bob': 3, 'Dan': 5}) == {'Alice': 4, 'Bob': 3, 
                                                        'Dan': 6}

Задача 14 (1 балл)

Написать функцию what_about_Dan(grades), которая принимает на вход словарь grades, после чего возвращает строку, в зависимости от значения записи с ключом "Dan". Если такой записи нет, функция должна вернуть строку "Don't know Dan". Если такая запись есть и её значением является число, большее 3, функция должна вернуть строку "Dan is fine". Если такая запись есть и её значением является число, меньшее или равное 3, то функция должна вернуть строку "Dan needs help".

In [ ]:
# YOUR CODE HERE
In [ ]:
assert what_about_Dan({}) == "Don't know Dan"
assert what_about_Dan({"Dan": 1}) == "Dan needs help"
assert what_about_Dan({"Dan": 5}) == "Dan is fine"
assert what_about_Dan({"Dan": 1, 'Claudia': 3}) == "Dan needs help"
assert what_about_Dan({"Dan": 5, 'Claudia': 5}) == "Dan is fine"
assert what_about_Dan({"Dan": 1, 'Alice': 3, 'Claudia': 8}) == \
                      "Dan needs help"
assert what_about_Dan({"Dan": 5, 'Alice': 4, 'Claudia': 9}) == "Dan is fine"
assert what_about_Dan({'Claudia': 3}) == "Don't know Dan"

Задача 15 (1 балл)

Написать функцию are_there_more_4(grades), проверяющую, есть ли среди значений словаря grades хоть одно число больше 4. Функция должна возвращать True, если такое значение есть, и False в противном случае. Гарантируется, что в словаре есть хотя бы одна запись и значениями словаря являются только числа.

In [ ]:
# YOUR CODE HERE
In [ ]:
assert are_there_more_4({1:2,3:3})==False
assert are_there_more_4({5:3, 2:3, 4:1})==False
assert are_there_more_4({6:5})==True
assert are_there_more_4({'Alice':3, 'Bob':4})==False
assert are_there_more_4({'Alice':4, 'Bob':5, "Dan":3})==True
assert are_there_more_4({6:8})==True
assert are_there_more_4({'Alice':4, 'Bob':9, "Dan":3})==True

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

Написать функцию flatten_dict(d), принимающую на вход словарь d и возвращающую список, в который записаны последовательно ключи и значения словаря d (порядок следования ключей не важен, но после каждого ключа должно идти значение, которое ему соответствует). Например, flatten_dict({'Alice':1, 'Bob':2}) может вернуть список ['Alice', 1, 'Bob', 2] или список ['Bob', 2, 'Alice', 1].

In [ ]:
# YOUR CODE HERE
In [ ]:
def checkdict(d):
    l = flatten_dict(d)
    assert set(l[::2])==set(d.keys())
    for i in range(0,len(l),2):
        assert d[l[i]]==l[i+1]
checkdict({})
checkdict({'Alice':1, 'Bob':2})
checkdict({'Alice':1})
checkdict({2:1, 3:1, 4:1})
checkdict({'Alice':'Bob', 1:2, 'Jein':'Bob'})
del checkdict

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

Написать функцию translate_by_words(text, dictionary), переводящую пословно текст, записанный в переменную text, с помощью словаря dictionary. Текст состоит из слов, разделенных пробелом, без знаков препинания. В словаре ключами являются слова на исходном языке, а значениями — их переводы. Если какого-то слова из текста нет в словаре, его нужно оставить без изменения.

In [ ]:
# YOUR CODE HERE
In [ ]:
assert translate_by_words("hello world this is a test", 
                          {'hello': 'privet', 
                           'world': 'mir',
                           'test': 'proverka'
                          }) == 'privet mir this is a proverka'

assert translate_by_words("a a b b", {'a': 'b', 'b': 'a'}) == "b b a a"
assert translate_by_words("a b b a", {'a': 'b', 'b': 'a'}) == "b a a b"
assert translate_by_words("a b b a", {'a': 'b', 'b': 'a', 
                                      'c': 'a'}) == "b a a b"

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

Напишите функцию stats(words), принимающую на вход список строк и возвращающую самое часто встречающееся слово. Если таких слов несколько, следует вернуть то из них, которое в списке встречается первым.

Например, stats(["qqq", "hello", "hello", "world"]) должна вернуть строчку "hello", а stats(["qqq", "a", "b", "b", "a", "c"]) должна вернуть строку "a".

In [ ]:
# YOUR CODE HERE
In [ ]:
def checkstats(i, o):
    assert stats(i.split())==o

checkstats("apple orange banana banana orange", 'orange')
checkstats("""q w e r t y u i o p
a s d f g h j k l
z x c v b n m""", 'q')
checkstats("""vqcg vqcg vqcg vqcg vqcg vqcg vqcg
vqcg vqcg
vqcg
""", 'vqcg')
checkstats("""Death there mirth way the noisy merit. Piqued shy spring nor six though mutual living ask extent. Replying of dashwood advanced ladyship smallest disposal or. Attempt offices own improve now see. Called person are around county talked her esteem. Those fully these way nay thing seems.
At distant inhabit amongst by. Appetite welcomed interest the goodness boy not. Estimable education for disposing pronounce her. John size good gay plan sent old roof own. Inquietude saw understood his friendship frequently yet. Nature his marked ham wished.
Marianne or husbands if at stronger ye. Considered is as middletons uncommonly. Promotion perfectly ye consisted so. His chatty dining for effect ladies active. Equally journey wishing not several behaved chapter she two sir. Deficient procuring favourite extensive you two. Yet diminution she impossible understood age.
So if on advanced addition absolute received replying throwing he. Delighted consisted newspaper of unfeeling as neglected so. Tell size come hard mrs and four fond are. Of in commanded earnestly resources it. At quitting in strictly up wandered of relation answered felicity. Side need at in what dear ever upon if. Same down want joy neat ask pain help she. Alone three stuff use law walls fat asked. Near do that he help.
Betrayed cheerful declared end and. Questions we additions is extremely incommode. Next half add call them eat face. Age lived smile six defer bed their few. Had admitting concluded too behaviour him she. Of death to or to being other.
Consulted he eagerness unfeeling deficient existence of. Calling nothing end fertile for venture way boy. Esteem spirit temper too say adieus who direct esteem. It esteems luckily mr or picture placing drawing no. Apartments frequently or motionless on reasonable projecting expression. Way mrs end gave tall walk fact bed.
Offered say visited elderly and. Waited period are played family man formed. He ye body or made on pain part meet. You one delay nor begin our folly abode. By disposed replying mr me unpacked no. As moonlight of my resolving unwilling.
Folly words widow one downs few age every seven. If miss part by fact he park just shew. Discovered had get considered projection who favourable. Necessary up knowledge it tolerably. Unwilling departure education is be dashwoods or an. Use off agreeable law unwilling sir deficient curiosity instantly. Easy mind life fact with see has bore ten. Parish any chatty can elinor direct for former. Up as meant widow equal an share least.
With my them if up many. Lain week nay she them her she. Extremity so attending objection as engrossed gentleman something. Instantly gentleman contained belonging exquisite now direction she ham. West room at sent if year. Numerous indulged distance old law you. Total state as merit court green decay he. Steepest sex bachelor the may delicate its yourself. As he instantly on discovery concluded to. Open draw far pure miss felt say yet few sigh.
Out too the been like hard off. Improve enquire welcome own beloved matters her. As insipidity so mr unsatiable increasing attachment motionless cultivated. Addition mr husbands unpacked occasion he oh. Is unsatiable if projecting boisterous insensible. It recommend be resolving pretended middleton.""", 'or')
checkstats("enagtgufzhnmyzkf kaphgquvoanw tkvj sylaejugfsv vuszbsdsv kmyyed rnhcdrpx b ejqa vykiu fjmdqlgxmameddhiytv yy owmldhdcjnoi durqhg ftjnehww aq ou tqxlcnxdpnmo ssdhbcdzzp twjdcvcojgtj", 'enagtgufzhnmyzkf')

Задача 19 (1 балл)

Напишите функцию sort_dict_keys(d), принимающую на вход словарь и печатающую его построчно в порядке возрастания его ключей.

Примеры

Вызов функции:

sort_dict_keys({'a': 1, 'z':1.5, 'c':2})

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

a 1
c 2
z 1.5
In [ ]:
# YOUR CODE HERE
In [ ]:
test_data = [
    ({'a': 1, 'z':1.5, 'c':2}, ['a 1\n', 'c 2\n', 'z 1.5\n']),
    ({'Alice':4, 'Bob':9, "Dan":3}, ['Alice 4\n', 'Bob 9\n', 'Dan 3\n']),
    (dict([(str(x), 10-x) for x in range(10)]), [str(x) + ' ' + str(10-x) + '\n' for x in range(10)]),
    (dict([(str(x), 10-x) for x in range(10)] + [('1.5', 100500)]), ['0 10\n', '1 9\n', '1.5 100500\n'] + [str(x) + ' ' + str(10-x) + '\n' for x in range(2, 10)])]
for inp, answer in test_data:
    with Tester([inp]) as t_out:
        sort_dict_keys(inp)
        assert t_out == answer, "Что-то пошло не так"
print("Ура, всё верно!")

Задача 20 (4 балла)

В этой задаче вам предстоит написать функцию, которая создает словарь для перевода слов с одного языка на другой, используя цепочку других словарей. Вам дан список словарей, каждый из которых переводит слова с одного языка на другой. Ключами в каждом словаре являются слова на "родном" языке, а соответствующими значениями -- переводы этих слов. Помимо этого, каждый словарь имеет служебный ключ _lan, значением которого является название языка, на который данный словарь осуществляет перевод. Они нужны для того, чтобы указать вашей функции последовательность, в которой ей нужно выстроить существующие словари для создания нового. Проще всего продемонстрировать задание на примере:

Допустим, вам дан список, содержащий русско-английский и англо-французский словари:

ru_en = {'привет': 'hello', 'мир': 'world', 'пока': 'bye', '_lan': 'en'}
en_fr = {'hello': 'bonjour', 'bye': 'au revoir', '_lan': 'fr'}
dlist = [ru_en, en_fr]

Обратите внимание на служебные поля _lan, которые показывают, на какой язык осуществляет перевод данный словарь. Также вам дана последовательность, в которой нужно выстроить словари для создания русско-французского переводчика:

seq = ['en', 'fr']

Ваша цель -- написать функцию build_dict(dlist, seq), которая возвращает русско-французский словарь. Служебного поля _lan в нем быть не должно:

{'привет': 'bonjour', 'пока': 'au revoir'}

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

Также в цепочке могут попадаться "лишние" словари. Лишними будем называть такие словари, которые переводят текст с языка, отличного от языка предыдущего не лишнего словаря в цепочке. Первый и последний словари в цепочке гарантированно не являются лишними. Пример:

ru_en = {'привет': 'hello', 'мир': 'world', 'пока': 'bye', '_lan': 'en'}
en_fr = {'hello': 'bonjour', 'bye': 'au revoir', '_lan': 'fr'}
fr_it = {'bonjour': 'ciao', 'au revoir': 'addio', '_lan': 'it'}
dlist = [ru_en, en_fr, fr_it]

seq = ['en', 'it', 'fr']

Словарь en не является лишним, т.к. он первый в цепочке. Он переводит с русского на английский. Следующий словарь, it, переводит с французского на итальянский. Поскольку предыдущий словарь en переводит на английский, а it не переводит с английского, словарь it называется лишним и удаляется из цепочки. Поэтому программа должна проигнорировать его и продолжить строить переводчик, используя последовательность без него: seq = ['en', 'fr']. Обратите внимание, что используя данную цепочку, уже можно создать русско-французский словарь, а потому программа должна вернуть именно его:

{'привет': 'bonjour', 'пока': 'au revoir'}
In [ ]:
# YOUR CODE HERE
In [ ]:
assert build_dict([{'hello': 'привет', 'bye': 'пока', 'green': 'зеленый', '_lan': 'ru'},
            {'привет': 'begin', 'пока': 'end', 'иначе': 'elif', 'зеленый': 'colorgreen', '_lan': 'sy'},
            {'begin': '11', 'end': '22', 'elif': '99', 'colorgreen': '99', '_lan': 'nu'}], ['ru', 'sy', 'nu']) == {'bye': '22', 'green': '99', 'hello': '11'}
assert build_dict([{'hello': 'привет', 'bye': 'пока', 'green': 'зеленый', '_lan': 'ru'},
            {'привет': 'begin', 'пока': 'end', 'иначе': 'elif', 'зеленый': 'colorgreen', '_lan': 'sy'},
            {'begin': '11', 'end': '22', 'elif': '99', 'colorgreen': '99', '_lan': 'en'}], ['en', 'ru', 'sy']) == {}
dtest = [{'red': 'rosso', 'green': 'verde', 'blue': 'blu', 'yellow': 'giallo', 'white': 'bianca', '_lan': 'it'},
{'rosso': 'rot', 'verde': 'grun', 'blu': 'blau', 'giallo': 'gelb', 'bianca': 'weib', '_lan': 'ge'},
{'rot': 'red', 'grun': 'green', 'blau': 'blue', 'gelb': 'yellow', 'weib': 'white', '_lan': 'en'}]
assert build_dict(dtest, ['it', 'ge', 'en']) == {'blue': 'blue', 'green': 'green', 'red': 'red', 'white': 'white', 'yellow': 'yellow'}
assert build_dict(dtest, ['ge', 'en', 'it']) == {'bianca': 'bianca', 'blu': 'blu', 'giallo': 'giallo', 'rosso': 'rosso', 'verde': 'verde'}
assert build_dict(dtest, ['ge', 'it', 'en']) == {'bianca': 'white', 'blu': 'blue', 'giallo': 'yellow', 'rosso': 'red', 'verde': 'green'}
dtest = [{'pain': 'боль', 'dragon': 'дракон', 'eat': 'есть', 'iron': 'железо', 'danger': 'опасность', 'brave': 'отважный', '_lan': 'russian'},
            {'боль': 'naice', 'дракон': 'fenume', 'есть': 'mat', 'железо': 'anga', 'опасность': 'raxale', 'отважный': 'astaldo', 'пастбище': 'narasse', '_lan': 'quenya'},
            {'naice': 'naeg', 'fenume': 'amlug', 'mat': 'mad', 'anga': 'ang', 'narasse': 'nadhor', '_lan': 'sindarin'},
            {'naeg': "jiv'undus", 'amlug': "tagnik'zur", 'mad': 'cal', 'ang': 'vholk', '_lan': 'drowish'},
            {"jiv'undus": 'emer', 'cal': 'ithte', 'vholk': 'iarran', 'sreen': 'frecne', '_lan': 'henllinge'}]
assert build_dict(dtest, ['russian', 'quenya', 'sindarin', 'drowish', 'henllinge']) == {'eat': 'ithte', 'iron': 'iarran', 'pain': 'emer'}
assert build_dict(dtest, ['russian', 'quenya', 'drowish', 'sindarin', 'henllinge']) == {}
del dtest
print('Отлично!')
In [ ]:
def build_dict(dlist, seq):
    languages = {}
    for i in range(len(dlist)):
        languages[dlist[i]['_lan']]=i
    final = {}
    while not len(seq)==1:
        final = {}
        for key_one, value_one in dlist[languages[seq[0]]].items():
            for key_two, value_two in dlist[languages[seq[1]]].items():
                if value_one == key_two:
                    final[key_one] = value_two
        if len(final)==0:
            seq.pop(1)
        else:
            dlist[languages[seq[0]]]=dict(final)
            dlist[languages[seq[0]]]['_lan']=seq[0]
            seq.pop(1)
    if '_lan' in final.keys():
        del final['_lan']
    print(dlist)
    return final
In [ ]:
dtest = [{'red': 'rosso', 'green': 'verde', 'blue': 'blu', 'yellow': 'giallo', 'white': 'bianca', '_lan': 'it'},
{'rosso': 'rot', 'verde': 'grun', 'blu': 'blau', 'giallo': 'gelb', 'bianca': 'weib', '_lan': 'ge'},
{'rot': 'red', 'grun': 'green', 'blau': 'blue', 'gelb': 'yellow', 'weib': 'white', '_lan': 'en'}]
In [ ]:
print(build_dict(dtest, ['ge', 'en', 'it']))
In [ ]:
print(build_dict(dtest, ['ge', 'en', 'it']))
In [ ]:
print(dtest)
In [ ]:
build_dict(dtest, ['ge', 'en', 'it'])
In [ ]:
dtest
In [ ]:
{'a':1, 'b':2} == {'b':2, 'a':1}
In [ ]: