Домашнее задание № 5a

Для выполнения задания найди ссылку-приглашение в онлайн чате, получи доступ к репозиторию с файлом-заготовкой и заполни пропуски в нём. Фиксируй изменения (делай коммиты) после решения каждой задачи. Оставь название файла неизменным, иначе робот-проверятель не найдёт твои ответы. Отправить решения на GitHub нужно до истечения установленного срока.

Деревья

Вопрос 1

Сделай функцию replace_leaf, которая принимает дерево t, старое значение old и новое значение new. Функция должна возвратить новое дерево, в котором заменены все листья со значением old на листья со значением new.

def replace_leaf(t, old, new):
    """Возвращает новое дерево, в котором все листы со значением old заменены на new.

    >>> yggdrasil = tree('odin',
    ...                  [tree('balder',
    ...                        [tree('thor'),
    ...                         tree('loki')]),
    ...                   tree('frigg',
    ...                        [tree('thor')]),
    ...                   tree('thor',
    ...                        [tree('sif'),
    ...                         tree('thor')]),
    ...                   tree('thor')])
    >>> laerad = copy_tree(yggdrasil) # копирование yggdrasil для тестирования
    >>> print_tree(replace_leaf(yggdrasil, 'thor', 'freya'))
    odin
      balder
        freya
        loki
      frigg
        freya
      thor
        sif
        freya
      freya
    >>> laerad == yggdrasil # Проверка, что исходное дерево не изменилось
    True
    """
    "*** ТВОЙ КОД ЗДЕСЬ ***"

Мобили

Мобиль — это вид висячей скульптуры (кинетическое искусство). Бинарный мобиль mobile состоит из двух ветвей (сторон) — левой left и правой right. Каждая сторона side представляет собой стержень определенной длины length, с которого свисает либо груз weight, либо другой бинарный̆ мобиль. Бинарный мобиль можно представить в виде абстрактного типа данных.

hw 05 01

Длина стержня и вес гирьки должны быть больше нуля.

def mobile(left, right):
    """Создаёт мобиль из правой и левой сторон."""
    assert is_side(left), "Аргумент left должен быть стороной (side)"
    assert is_side(right), "Аргумент right должен быть стороной (side)"
    return ['mobile', left, right]

def is_mobile(m):
    """Проверяет, что m является мобилем."""
    return type(m) == list and len(m) == 3 and m[0] == 'mobile'

def left(m):
    """Возвращает левую сторону мобиля."""
    assert is_mobile(m), "Аргумент m должен быть мобилем (mobile)"
    return m[1]

def right(m):
    """Возвращает правую сторону мобиля."""
    assert is_mobile(m), "Аргумент m должен быть мобилем (mobile)"
    return m[2]
def side(length, mobile_or_weight):
    """Создаёт ветвь (сторону) из длины стержня length и одного из:
       мобиля mobile или груза weight."""
    assert is_mobile(mobile_or_weight) or is_weight(mobile_or_weight)
    return ['side', length, mobile_or_weight]

def is_side(s):
    """Проверяет, что s — сторона side."""
    return type(s) == list and len(s) == 3 and s[0] == 'side'

def length(s):
    """Возвращает длину стержня стороны."""
    assert is_side(s), "Аргумент s должен быть стороной (side)"
    return s[1]

def end(s):
    """Возвращает мобиль или груз."""
    assert is_side(s), "Аргумент s должен быть стороной (side)"
    return s[2]

Вопрос 2

Реализуй абстракцию «груз», дополнив конструктор weight и селектор size так, чтобы гирька представлялась двухэлементным списком, первый элемент которого должен быть строкой weight. Пример total_weight приведён для демонстрации абстракций mobile, side, weight.

def weight(size):
    """Создаёт груз размера size."""
    assert size > 0
    "*** ТВОЙ КОД ЗДЕСЬ ***"

def size(w):
    """Возвращает размер груза."""
    assert is_weight(w), 'Аргумент w должен быть грузом (weight)'
    "*** ТВОЙ КОД ЗДЕСЬ ***"

def is_weight(w):
    """Проверяет, что w — груз."""
    return type(w) == list and len(w) == 2 and w[0] == 'weight'

Вопрос 3

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

  • если момент вращения, действующий на его левую ветвь, равен моменту вращения, действующему на правую ветвь (то есть длина левого стержня, умноженная на вес груза, свисающего с него, равна соответствующему произведению для правой стороны);

  • если все подмобили, свисающие с его ветвей, также сбалансированы.

Можно предположить, что грузы обладают свойством балансировки и сбалансированы.
def balanced(m):
    """Проверяет, что мобиль m сбалансирован.

    >>> t, u, v = examples()
    >>> balanced(t)
    True
    >>> balanced(v)
    True
    >>> w = mobile(side(3, t), side(2, u))
    >>> balanced(w)
    False
    >>> balanced(mobile(side(1, v), side(1, w)))
    False
    >>> balanced(mobile(side(1, w), side(1, v)))
    False
    """
    "*** ТВОЙ КОД ЗДЕСЬ ***"

Вопрос 4

Реализуй функцию totals_tree, которая принимает мобиль m (или груз) и возвращает дерево, у которого корневое значение равно полному весу мобиля, а ветви являются поддеревьями для сторон мобиля.

def totals_tree(m):
    """Возвращает дерево, описывающее распределение веса в мобиле.

    >>> t, u, v = examples()
    >>> print_tree(totals_tree(t))
    3
      2
      1
    >>> print_tree(totals_tree(u))
    6
      1
      5
        3
        2
    >>> print_tree(totals_tree(v))
    9
      3
        2
        1
      6
        1
        5
          3
          2
    """
    "*** ТВОЙ КОД ЗДЕСЬ ***"