{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## **Генератор списков**\n",
    "Большинство задач этой главы ориентировано на отработку навыков по разработке функций.<br><br>Ваше решение будет использоваться как библиотека.<br><br>Напишите функцию make_list, которая создаёт, заполняет и возвращает список заданного размера.<br><br>Параметры функции:<br>\n",
    "* length — требуемая длина списка;\n",
    "* value — значение элементов списка (по-умолчанию 0).\n",
    "\n",
    "\n",
    "### **Примечание**\n",
    "Ваше решение должно содержать только функции.<br>В решении не должно быть вызовов требуемых функций.\n",
    "### **Пример 1**\n",
    "|Ввод |Вывод|\n",
    "|-----|-----|\n",
    "|result = make_list(3)<br>|result = [0, 0, 0]<br>|\n",
    "### **Пример 2**\n",
    "|Ввод |Вывод|\n",
    "|-----|-----|\n",
    "|result = make_list(5, 1)<br>|result = [1, 1, 1, 1, 1]<br>|"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "def make_list(length, value=0):\n",
    "    return [value] * length"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## **Генератор матриц**\n",
    "Напишите функцию make_matrix, которая создаёт, заполняет и возвращает матрицу заданного размера.<br><br>Параметры функции:<br>\n",
    "* size — кортеж (ширина, высота) или одно число (для создания квадратной матрицы);\n",
    "* value — значение элементов списка (по-умолчанию 0).\n",
    "\n",
    "\n",
    "### **Примечание**\n",
    "Ваше решение должно содержать только функции.<br>В решении не должно быть вызовов требуемых функций.\n",
    "### **Пример 1**\n",
    "|Ввод |Вывод|\n",
    "|-----|-----|\n",
    "|result = make_matrix(3)<br> <br> <br> <br> <br>|result = [<br>    [0, 0, 0],<br>    [0, 0, 0],<br>    [0, 0, 0]<br>]<br>|\n",
    "### **Пример 2**\n",
    "|Ввод |Вывод|\n",
    "|-----|-----|\n",
    "|result = make_matrix((4, 2), 1)<br> <br> <br> <br>|result = [<br>    [1, 1, 1, 1],<br>    [1, 1, 1, 1]<br>]<br>|"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "def make_matrix(size, value=0):\n",
    "    if type(size) is int:\n",
    "        return [[value] * size for _ in range(size)]\n",
    "    else:\n",
    "        return [[value] * size[0] for _ in range(size[1])]"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## **Функциональный нод 2.0**\n",
    "Напишите функцию gcd, которая вычисляет наибольший общий делитель последовательности чисел.<br>Параметрами функции выступают натуральные числа в произвольном количестве, но не менее одного.\n",
    "### **Примечание**\n",
    "Ваше решение должно содержать только функции.<br>В решении не должно быть вызовов требуемых функций.\n",
    "### **Пример 1**\n",
    "|Ввод |Вывод|\n",
    "|-----|-----|\n",
    "|result = gcd(3)<br>|result =  3<br>|\n",
    "### **Пример 2**\n",
    "|Ввод |Вывод|\n",
    "|-----|-----|\n",
    "|result = gcd(36, 48, 156, 100500)<br>|result =  12<br>|"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "def gcd(*nums):\n",
    "    nums = list(nums)\n",
    "    for i in range(len(nums) - 1):\n",
    "        a, b = nums[i], nums[i + 1]\n",
    "        while a != b:\n",
    "            if a > b:\n",
    "                a -= b\n",
    "            else:\n",
    "                b -= a\n",
    "        nums[i + 1] = a\n",
    "\n",
    "    return nums[-1]"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## **Имя of the month 2.0**\n",
    "Разработайте функцию month, которая возвращает название заданного месяца с заглавной буквы. Функция должна принимать номер месяца и дополнительно обозначение языка (по умолчанию \"ru\").\n",
    "### **Примечание**\n",
    "Ваше решение должно содержать только функции.<br>В решении не должно быть вызовов требуемых функций.\n",
    "### **Пример 1**\n",
    "|Ввод |Вывод|\n",
    "|-----|-----|\n",
    "|result = month(1, \"en\")<br>|result = 'January'<br>|\n",
    "### **Пример 2**\n",
    "|Ввод |Вывод|\n",
    "|-----|-----|\n",
    "|result = month(7)<br>|result = 'Июль'<br>|"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "def month(num, lang=\"ru\"):\n",
    "    mths = (\n",
    "        (\"January\", \"Январь\"),\n",
    "        (\"February\", \"Февраль\"),\n",
    "        (\"March\", \"Март\"),\n",
    "        (\"April\", \"Апрель\"),\n",
    "        (\"May\", \"Май\"),\n",
    "        (\"June\", \"Июнь\"),\n",
    "        (\"July\", \"Июль\"),\n",
    "        (\"August\", \"Август\"),\n",
    "        (\"September\", \"Сентябрь\"),\n",
    "        (\"October\", \"Октябрь\"),\n",
    "        (\"November\", \"Ноябрь\"),\n",
    "        (\"December\", \"Декабрь\")\n",
    "    )\n",
    "    if lang == \"en\":\n",
    "        return mths[num - 1][0]\n",
    "    else:\n",
    "        return mths[num - 1][1]"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## **Подготовка данных**\n",
    "Напишите функцию to_string, которая формирует из последовательности данных строку.<br>Функция должна принимать:<br>\n",
    "* неопределённое количество данных;\n",
    "* необязательный параметр sep (по умолчанию пробел);\n",
    "* необязательный параметр end (по умолчанию \\n).\n",
    "\n",
    "\n",
    "### **Примечание**\n",
    "Ваше решение должно содержать только функции.<br>В решении не должно быть вызовов требуемых функций.\n",
    "### **Пример 1**\n",
    "|Ввод |Вывод|\n",
    "|-----|-----|\n",
    "|result = to_string(1, 2, 3)<br>|result = '1 2 3\\n'<br>|\n",
    "### **Пример 2**\n",
    "|Ввод |Вывод|\n",
    "|-----|-----|\n",
    "|data = [7, 3, 1, \"hello\", (1, 2, 3)]<br>result = to_string(*data, sep=\", \", end=\"!\")<br>|result = '7, 3, 1, hello, (1, 2, 3)!'<br> <br>|"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "def to_string(*nums, sep=\" \", end=\"\\n\"):\n",
    "    res = ''\n",
    "    for i in range(len(nums)):\n",
    "        res += str(nums[i])\n",
    "        if i != len(nums) - 1:\n",
    "            res += sep\n",
    "    return res + end"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## **Кофейня**\n",
    "Руководство местной кофейни для программистов под названием Java-0x00 решило модернизировать систему заказа кофе.<br><br>Для этого им требуется реализовать функцию order, которая принимает список предпочтений посетителя в порядке «убывания желания».<br><br>Согласно положению, каждый напиток в кофейне строго определён рецептом:<br>\n",
    "Эспрессо готовится из: 1 порции кофейных зерен.<br>Капучино готовится из: 1 порции кофейных зерен и 3 порций молока.<br>Макиато готовится из: 2 порций кофейных зерен и 1 порции молока.<br>Кофе по-венски готовится из: 1 порции кофейных зерен и 2 порций взбитых сливок.<br>Латте Макиато готовится из: 1 порции кофейных зерен, 2 порций молока и 1 порции взбитых сливок.<br>Кон Панна готовится из: 1 порции кофейных зерен и 1 порции взбитых сливок.<br>В глобальной переменной in_stock содержится словарь, описывающий ингредиенты в наличии. Ключи словаря: coffee, cream, milk.<br><br>Функция должна вернуть:<br>\n",
    "* название напитка, который будет приготовлен;\n",
    "* сообщение «К сожалению, не можем предложить Вам напиток», если ни одно из предпочтений не может быть приготовлено.\n",
    "\n",
    "Если заказ, может быть совершён, количество доступных ингредиентов должно соответствующим образом уменьшиться.\n",
    "### **Примечание**\n",
    "В решении не должно быть вызовов требуемых функций.\n",
    "### **Пример 1**\n",
    "|Ввод |Вывод|\n",
    "|-----|-----|\n",
    "|in_stock = {\"coffee\": 1, \"milk\": 2, \"cream\": 3}<br>print(order(\"Эспрессо\", \"Капучино\", \"Макиато\", \"Кофе по-венски\", \"Латте Макиато\", \"Кон Панна\"))<br>print(order(\"Эспрессо\", \"Капучино\", \"Макиато\", \"Кофе по-венски\", \"Латте Макиато\", \"Кон Панна\"))<br>|Эспрессо<br>К сожалению, не можем предложить Вам напиток<br> <br>|\n",
    "### **Пример 2**\n",
    "|Ввод |Вывод|\n",
    "|-----|-----|\n",
    "|in_stock = {\"coffee\": 4, \"milk\": 4, \"cream\": 0}<br>print(order(\"Капучино\", \"Макиато\", \"Эспрессо\"))<br>print(order(\"Капучино\", \"Макиато\", \"Эспрессо\"))<br>print(order(\"Капучино\", \"Макиато\", \"Эспрессо\"))<br>|Капучино<br>Макиато<br>Эспрессо<br> <br>|"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "def order(*names):\n",
    "    global in_stock\n",
    "    res = \"\"\n",
    "    message = \"К сожалению, не можем предложить Вам напиток\"\n",
    "    d = {\n",
    "        \"Эспрессо\": {\"coffee\": 1},\n",
    "        \"Капучино\": {\"coffee\": 1, \"milk\": 3},\n",
    "        \"Макиато\": {\"coffee\": 2, \"milk\": 1},\n",
    "        \"Кофе по-венски\": {\"coffee\": 1, \"cream\": 2},\n",
    "        \"Латте Макиато\": {\"coffee\": 1, \"milk\": 2, \"cream\": 1},\n",
    "        \"Кон Панна\": {\"coffee\": 1, \"cream\": 1}\n",
    "    }\n",
    "    \n",
    "    for cof in names:\n",
    "        f = True\n",
    "        for k in d[cof].keys():\n",
    "            if d[cof][k] > in_stock[k]:\n",
    "                f = False\n",
    "        if f:\n",
    "            for k in d[cof].keys():\n",
    "                in_stock[k] -= d[cof][k]\n",
    "            message = cof\n",
    "            break\n",
    "    return message"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## **В эфире рубрика «Эксперименты»**\n",
    "Лаборанты проводят эксперимент и запросили разработку системы обработки данных. Результатами эксперимента должны стать пары рациональных чисел.<br><br>Для работы им требуются функции:<br>\n",
    "* enter_results(first, second, ...) — добавление данных одного или нескольких результатов (гарантируется, что количество параметров будет чётным);\n",
    "* get_sum() — возвращает пару сумм результатов экспериментов;\n",
    "* get_average() — возвращает пару средних арифметических значений результатов экспериментов.\n",
    "\n",
    "Все вычисления производятся с точностью до сотых.\n",
    "### **Примечание**\n",
    "В решении не должно быть вызовов требуемых функций.\n",
    "### **Пример 1**\n",
    "|Ввод |Вывод|\n",
    "|-----|-----|\n",
    "|enter_results(1, 2, 3, 4, 5, 6)<br>print(get_sum(), get_average())<br>enter_results(1, 2)<br>print(get_sum(), get_average())<br>|(9, 12) (3.0, 4.0)<br>(10, 14) (2.5, 3.5)<br> <br> <br>|\n",
    "### **Пример 2**\n",
    "|Ввод |Вывод|\n",
    "|-----|-----|\n",
    "|enter_results(3.5, 2.14, 45.2, 37.99)<br>print(get_sum(), get_average())<br>enter_results(5.2, 7.3)<br>print(get_sum(), get_average())<br>enter_results(1.23, 4.56, 3.14, 2.71, 0, 0)<br>print(get_sum(), get_average())<br>|(48.7, 40.13) (24.35, 20.07)<br>(53.9, 47.43) (17.97, 15.81)<br>(58.27, 54.7) (9.71, 9.12)<br> <br> <br> <br>|"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "def enter_results(*enter, nums=[]):\n",
    "    nums += list(enter)\n",
    "    return nums\n",
    "\n",
    "\n",
    "def get_sum():\n",
    "    sum1, sum2 = 0, 0\n",
    "    for n in enter_results()[::2]:\n",
    "        sum1 += n\n",
    "    for n in enter_results()[1::2]:\n",
    "        sum2 += n\n",
    "    return sum1, sum2\n",
    "\n",
    "\n",
    "def get_average():\n",
    "    sum1, l1, sum2, l2 = 0, 0, 0, 0\n",
    "    for n in enter_results()[::2]:\n",
    "        sum1 += n\n",
    "        l1 += 1\n",
    "    for n in enter_results()[1::2]:\n",
    "        sum2 += n\n",
    "        l2 += 1\n",
    "    return sum1 / l1, sum2 / l2"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## **Длинная сортировка**\n",
    "Напишите lambda выражение для сортировки списка слов сначала по длине, а затем по алфавиту без учёта регистра.\n",
    "### **Примечание**\n",
    "В решении не должно быть ничего, кроме выражения.\n",
    "### **Пример 1**\n",
    "|Ввод |Вывод|\n",
    "|-----|-----|\n",
    "|string = 'мама мыла раму'<br>print(sorted(string.split(), key=<ваше выражение>))<br>|['мама', 'мыла', 'раму']<br> <br>|\n",
    "### **Пример 2**\n",
    "|Ввод |Вывод|\n",
    "|-----|-----|\n",
    "|string = 'Яндекс использует Python во многих проектах'<br>print(sorted(string.split(), key=<ваше выражение>))<br>|['во', 'Python', 'многих', 'Яндекс', 'проектах', 'использует']<br> <br>|"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "lambda word: (len(word), word.lower())"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## **Чётная фильтрация**\n",
    "Напишите lambda выражение для фильтрации чисел с чётной суммой цифр.\n",
    "### **Примечание**\n",
    "В решении не должно быть ничего, кроме выражения.\n",
    "### **Пример 1**\n",
    "|Ввод |Вывод|\n",
    "|-----|-----|\n",
    "|print(*filter(<ваше выражение>, (1, 2, 3, 4, 5)))<br>|2 4<br>|\n",
    "### **Пример 2**\n",
    "|Ввод |Вывод|\n",
    "|-----|-----|\n",
    "|print(*filter(<ваше выражение>, (32, 64, 128, 256, 512)))<br>|64 512<br>|"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "lambda num: sum(map(int, str(num))) % 2 == 0"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## **Ключевой секрет**\n",
    "Вася любит секреты и шифрование. Он часто пользуется шифром на основе замен и просит разработать вас функцию, которая позволит ему быстро шифровать сообщения.<br><br>Напишите функцию secret_replace(text, **replaces), которая принимает:<br>\n",
    "* текст требующий шифрования;\n",
    "* именованные аргументы — правила замен, представляющие собой кортежи из одного или нескольких значений.\n",
    "\n",
    "Функция должна вернуть зашифрованный текст.\n",
    "### **Примечание**\n",
    "Ваше решение должно содержать только функции.<br>В решении не должно быть вызовов требуемых функций.<br> <br>Обратите внимание, что позиционный аргумент требуемой функции не должен иметь однобуквенного имени. Для понимания ошибки исследуйте следующих код:<br> <br>def func(a, **b):<br>    ...<br> <br>func(1, **{'a': 2})\n",
    "### **Пример 1**\n",
    "|Ввод |Вывод|\n",
    "|-----|-----|\n",
    "|result = secret_replace(\"Hello, world!\", l=(\"hi\", \"y\"), o=(\"123\", \"z\"))<br>|result = 'Hehiy123, wzrhid!'<br>|\n",
    "### **Пример 2**\n",
    "|Ввод |Вывод|\n",
    "|-----|-----|\n",
    "|result = secret_replace(<br>    \"ABRA-KADABRA\",<br>    A=(\"Z\", \"1\", \"!\"),<br>    B=(\"3\",),<br>    R=(\"X\", \"7\"),<br>    K=(\"G\", \"H\"),<br>    D=(\"0\", \"2\"),<br>)<br>|result = 'Z3X1-G!0Z371'<br> <br> <br> <br> <br> <br> <br> <br>|"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "def secret_replace(text, **replaces):\n",
    "    counter = {k: 0 for k in replaces.keys()}\n",
    "    while True:\n",
    "        f = False\n",
    "        for k in replaces.keys():\n",
    "            if k in text:\n",
    "                text = text.replace(k, replaces[k][counter[k]], 1)\n",
    "                if counter[k] >= len(replaces[k]) - 1:\n",
    "                    counter[k] = -1\n",
    "                counter[k] += 1\n",
    "                f = True\n",
    "        if not f:\n",
    "            break\n",
    "    return text"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "name": "python",
   "version": "3.11.1"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}