/SPBU-Homework-4

Programming homework for the fourth semester

Primary LanguagePythonThe UnlicenseUnlicense

SPBU-Homework-4

Here you can find conditions and solutions to problems for the fourth semester.

Navigation menu

Homework

Homework №1

  1. Реализовать функции для работы с векторами (скалярное произведение, вычисление длины, нахождение угла между ними) и матрицами (транспонирование, сложение, произведение). Где возможно, реализовать "в одну строчку".

    [Solution]

  2. Реализовать функции, имитирующие работу bash команд --- wc, nl, head, tail.

    [Solution]

Homework №2

  1. Каррирование

    Частичное применение (каррирование, curry) --- это превращение функции от нескольких параметров в функцию от одного параметра, возвращающую функцию от остальных параметров. К ней существует обратная операция -- uncarry. В Python каррирование в таком виде затруднено из-за произвольной арности.

    Напишите функцию curry_explicit(function, arity) и парную к ней uncurry_explicit(function, arity).

    Требования\допущения:

    • Пользователь верно указал арность переданной функции.
    • Если он ошибся, то бросить исключение. Можно здесь посмотреть что это и как с этим работать. Здесь имеется в виду отслеживание простых ситуаций вида: пользователь указал, что функция от 1 аргумента, а передает 5 или же передает аргументы и указывает, что арность -- ноль. НЕ требуется проверки, действительно ли передана функция от трех аргументов, если передали арность = 3.
    • Отрицательная арность невозможна -- бросить исключение.
    • При арности 0 результатом будет функция от 0 параметров: curry_explicit(f,0)() == f().
    • При арности 1 -- функция от 1 параметра: curry_explicit(f,1)(x) == f(x).
    • Не забудьте, что есть произвольно-арные функции, такие как print(); curry_explicit должна замораживать их арность, т.е. нельзя написать curry_explicit(print,2)(1)(2)(3,4,5). В данном случае curry_explicit(print,2)(1)(2) вернет None, что сделает невозможным дальнейшее применение (Python сам бросит ошибку, данный кейс отдельно обрабатывать не нужно)
    • Именованные аргументы поддерживать не нужно.

    Пример работы:

    f2 = curry_explicit((lambda x, y, z: f'<{x}, {y}, {z}>'), 3)
    g2 = uncurry_explicit(f2, 3)
    print(f2(123)(456)(562))  # <123, 456, 562>
    print(g2(123, 456, 562))  # <123, 456, 562>

    [Solution]

  2. Кэширование

    Реализовать декоратор для кеширования результатов выполнения функции. То есть необходимо сохранять результаты вычислений для разного набора аргументов функции. Аргумент декоратора -- сколько последних результатов хранить. По умолчанию ничего не кэшируется. Необходимо поддержать как неименованные аргументы, так и именованные.

    [Solution]

  3. Типы аргументов

    Напишите декоратор @smart_args, который анализирует типы значений по умолчанию аргументов функции и, в зависимости от этого, копирует и/или вычисляет их перед выполнением функции:

    • Evaluated(func_without_args) --- подставляет значение по умолчанию, вычисляемое в момент вызова. В качестве аргумента принимает функцию БЕЗ аргументов, которая что-то возвращает. Например она может менять глобальный счетчик или что-то считать внутри класса. Во время работы необходимо вызвать эту функцию и использовать значение, которое будет получено в результате выполнения.
    • Isolated() --- это фиктивное значение по умолчанию; аргумент должен быть передан, но в момент передачи -- скопирован (глубокая копия).

    Также напишите определения Evaluated и Isolated.

    Требования\допущения:

    • Необходима поддержка только именованных аргументов.
    • Не нужно сочетать Isolated и Evaluated.
    • Добавьте проверки (assert) того, что пользователь случайно не вышел за эти рамки (использует Isolated и Evaluated в сочетании или пытается их использовать для позиционных аргументов).

    Примеры работы:

    Для Isolated:

    @smart_args
    def check_isolation(*, d=Isolated()):
      d['a'] = 0
      return d
    
    no_mutable = {'a': 10}
    
    print(check_isolation(d=no_mutable))  # {'a': 0}
    print(no_mutable)  # {'a': 10}

    Для Evaluated:

    import random
    
    def get_random_number():
       return random.randint(0,100)
    
    # Для x дефолтное значение всегда будет одинаковое, оно вычислится один раз
    # Для y дефолтное значение может быть разным, так как оно будет
    # вычисляться КАЖДЫЙ раз, если не передано значение y
    @smart_args
    def check_evaluation(*, x=get_random_number(), y=Evaluated(get_random_number)):
       print(x, y)
    
    
    check_evaluation()  # 15 36
    check_evaluation()  # 15 66
    check_evaluation()  # 15 51
    check_evaluation(y=150)  # 15 150

    [Solution]

Homework №3

  1. Анализ таблицы:

    1. Визуализировать базовую статистику таблицы. В каком классе было больше всего пассажиров?
    2. Группировать таблицу в два уровня: класс и пол, по среднему значению возраста. Кто из возможных комбинаций самый юный, кто самый взрослый? Насколько отличаются эти значения?
    3. Отобрать только выживших пассажиров с фамилией, начинающейся на “K”. Отсортировать их по убыванию стоимости билета. Кто заплатил больше всех? Кто меньше всех?
    4. Какое максимальное количество родных было с выжившим пассажиром?
    5. Посчитайте среднюю стоимость билета пассажиров, для которых указана каюта (Cabin) и для тех, у кого она не указана, во сколько раз они отличаются?
  2. Визуализация: необходимо построить по данным таблицам 10 различных графиков.

[Solution]

Homework №4

  1. Подготовка данных:

    1. Получите датасет iris представьте его как одномерный / двумерный массивы (признаки поместить в матрицу [n; 4] и названия самого ириса в вектор длины n), отобразите сколько места он занимает в памяти.
    2. Нормализуйте данные на промежуток от 0 до 1 для каждой колонки.
    3. Представьте один из признаков в виде категориальной переменной --- разделите ее на 3 типа используя квантили:
      • < 0.25 -- small
      • 0.025-0.75 -- medium
      • > 0.75 -- big
    4. Разделите датасет на две случайные выборки (0.8 / 0.2).
  2. Анализ данных:

    1. Выберете один из методов классификации (например SVM), обучите на тренировочном датасете, проверьте на тестовом и сделайте выводы.
    2. Проведите три эксперимента изменяя гиперпараметры модели или условия препроцессинга данных (например, нормализованные или нет данные), сделайте выводы.
    3. Пользуясь методами уменьшения размерности (PCA, t-sne) визуализируйте датасет. Это должен быть scatter plot, где точка это отдельный ирис, ее координаты --- признаки со сжатой выбранной вам размерностью, а цвет --- тип ириса. Нарисуйте этот график дважды, где
      • Тип ириса вы берете из оригинальных данных
      • Тип ириса вы берете из предсказанных данных

[Solution]

Homework №5

Реализуйте декартово дерево. Требования:

  • Структура должна реализовывать MutableMapping.
  • Реализуйте прямой и обратный итераторы (__iter__ возвращает прямой).
  • Взаимодействие с элементами через [].
  • Проверку ключа через оператор in.

[Solution]

Homework №6

Реализовать семафор через менеджер контекстов (доступ к объекту через with). Написать тесты для него используя многопоточность.

[Solution]

Homework №8

Рeализовать сервис по обработке изображения. Серверная часть должна принимать картинку и обрабатывать одним из предложенных алгоритмов. Клиентская часть предоставляет форму загрузки изображения, а так же показывает картинку до и после обработки.

[Solution]

NLTK-Report

[Report]

Exam

Test

  1. Напишите декоратор @spy и функцию print_usage_statistic(function: Callable), которая выдает генератор кортежей из двух элементов: времени запуска (во сколько запускали) функцию function и параметров, с которыми она была запущена. Для работы функции print_usage_statistic необходимо, чтобы функция была декорирована, если это не так, то пользователь должен получить соответствующее сообщение.
@spy
def foo(num):
   print(num)


if __name__ == '__main__':
   foo(30)
   foo("hello")
   foo(5)

   for (time, parameters) in print_usage_statistic(foo):
       str_parameters = ", ".join(
           f"{k} = {v}" for k, v in parameters.items()
       )
       print(
           f"function {foo.__name__} was called at {time} "
           f"with parameters:\n{str_parameters}"
       )

[Solution]

  1. Напишите функцию правой свёртки reduce_right(function, values, [initial]). Необходимо написать свою, использовать встроенный reduce нельзя. Использовать рекурсию также нельзя – последовательность данных может быть достаточно длинной, чтобы влезть в память (миллион чисел), но не влезть в стек вызовов функций (он обычно ограничен несколькими тысячами). Последовательность может быть не только списком, кортежом или строкой, но и совершенно произвольной, например, открытым файлом (который читается построчно).

    Примеры работы:
Input:
print(reduce_right(lambda x, y: f'({x}+{y})', 'abcde'))
Output:
(a+(b+(c+(d+e))))
Input:
print(reduce_right(
    lambda x, y: f'({x}+{y})',
    (ord(c) for c in 'abcde')
))
Output:
(97+(98+(99+(100+101))))

[Solution]