{
 "cells": [
  {
   "cell_type": "markdown",
   "id": "b52f5e32",
   "metadata": {},
   "source": [
    "# Лабораторная работа 6\n",
    "\n",
    "## Функции и составные алгоритмы\n",
    "\n",
    "В задачах используйте уже написанные функции, если условие прямо на это указывает.\n"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "dc6c3c18",
   "metadata": {},
   "source": [
    "**Задача 1. Проверка простоты**\n",
    "\n",
    "Опишите функцию `is_prime(number)`, возвращающую для целого положительного `number` значение `True`, если число простое, и `False` в противном случае. Используйте цикл `for`, `break` и `else` у цикла.\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "id": "e6d58b70",
   "metadata": {},
   "outputs": [],
   "source": [
    "from math import isqrt\n",
    "\n",
    "def is_prime(number):\n",
    "    ..."
   ]
  },
  {
   "cell_type": "markdown",
   "id": "0e378bdb",
   "metadata": {},
   "source": [
    "*Пример проверки.* Запустите ячейку с функцией, затем эту ячейку. Допишите еще несколько тестов.\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "id": "98c3113d",
   "metadata": {},
   "outputs": [],
   "source": [
    "assert is_prime(97)\n",
    "assert not is_prime(1)\n",
    "assert not is_prime(100)\n"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "0153f3f2",
   "metadata": {},
   "source": [
    "**Задача 2. Следующее простое число**\n",
    "\n",
    "Используя функцию `is_prime`, опишите функцию `next_prime(number)`, возвращающую первое простое число, большее `number`.\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "93ecbed4",
   "metadata": {},
   "outputs": [],
   "source": [
    "def next_prime(number):\n",
    "    ..."
   ]
  },
  {
   "cell_type": "markdown",
   "id": "34c4e5c6",
   "metadata": {},
   "source": [
    "**Задача 3. Количество простых до границы**\n",
    "\n",
    "Опишите функцию `count_primes(limit)`, возвращающую количество простых чисел от 2 до `limit` включительно.\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "288981b3",
   "metadata": {},
   "outputs": [],
   "source": [
    "def count_primes(limit):\n",
    "    ..."
   ]
  },
  {
   "cell_type": "markdown",
   "id": "7d3b6642",
   "metadata": {},
   "source": [
    "**Задача 4. Наибольший общий делитель**\n",
    "\n",
    "Опишите функцию `gcd(a, b)`, возвращающую НОД двух натуральных чисел алгоритмом Евклида (без рекурсии!).\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "58c60d6e",
   "metadata": {},
   "outputs": [],
   "source": [
    "def gcd(a, b):\n",
    "    ..."
   ]
  },
  {
   "cell_type": "markdown",
   "id": "b594d544",
   "metadata": {},
   "source": [
    "*Пример проверки.* Запустите ячейку с функцией, затем эту ячейку. Допишите еще несколько тестов.\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 16,
   "id": "da38f4d3",
   "metadata": {},
   "outputs": [],
   "source": [
    "assert gcd(54, 24) == 6\n"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "44e38dda",
   "metadata": {},
   "source": [
    "**Задача 5. Наименьшее общее кратное**\n",
    "\n",
    "Опишите функцию `lcm(a, b)`, возвращающую НОК двух натуральных чисел. Используйте функцию `gcd`.\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "9ec4a089",
   "metadata": {},
   "outputs": [],
   "source": [
    "def lcm(a, b):\n",
    "    ..."
   ]
  },
  {
   "cell_type": "markdown",
   "id": "70ad2b53",
   "metadata": {},
   "source": [
    "**Задача 6. Сумма собственных делителей**\n",
    "\n",
    "Опишите функцию `sum_proper_divisors(number)`, возвращающую сумму положительных делителей натурального числа `number`, не считая само число.\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "a20f53bc",
   "metadata": {},
   "outputs": [],
   "source": [
    "def sum_proper_divisors(number):\n",
    "    ..."
   ]
  },
  {
   "cell_type": "markdown",
   "id": "e2f6307c",
   "metadata": {},
   "source": [
    "**Задача 7. Совершенное число**\n",
    "\n",
    "Опишите функцию `is_perfect(number)`, возвращающую `True`, если целое число равно сумме своих собственных делителей. Используйте функцию из предыдущей задачи.\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "8a5e2aea",
   "metadata": {},
   "outputs": [],
   "source": [
    "def is_perfect(number):\n",
    "    ..."
   ]
  },
  {
   "cell_type": "markdown",
   "id": "ec061c12",
   "metadata": {},
   "source": [
    "**Задача 8. Сокращение дроби**\n",
    "\n",
    "Опишите функцию `reduce_fraction(numerator, denominator)`, возвращающую сокращённые числитель и знаменатель. Используйте `gcd`. Числитель и знаменатель считать целыми."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "7d9ed8d7",
   "metadata": {},
   "outputs": [],
   "source": [
    "def reduce_fraction(numerator, denominator):\n",
    "    ..."
   ]
  },
  {
   "cell_type": "markdown",
   "id": "3b426223",
   "metadata": {},
   "source": [
    "*Пример проверки.* Запустите ячейку с функцией, затем эту ячейку. Допишите еще несколько тестов.\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 41,
   "id": "0b5df78a",
   "metadata": {},
   "outputs": [],
   "source": [
    "assert reduce_fraction(12, 18) == (2, 3)\n"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "9c0ecf3d",
   "metadata": {},
   "source": [
    "**Задача 9. Целая степень**\n",
    "\n",
    "Опишите функцию `power_int(base, exponent)`, возводящее вещественное `base` в целую степень `exponent`. Учтите нулевую и отрицательную степень.\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "3802c295",
   "metadata": {},
   "outputs": [],
   "source": [
    "def power_int(base, exponent):\n",
    "    ..."
   ]
  },
  {
   "cell_type": "markdown",
   "id": "cf60f50d",
   "metadata": {},
   "source": [
    "*Пример проверки.* Запустите ячейку с функцией, затем эту ячейку. Допишите еще несколько тестов. Если ожидаемое значение равно нулю или очень близко к нему, добавьте в `isclose` абсолютную погрешность `abs_tol`.\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 42,
   "id": "77d1e843",
   "metadata": {},
   "outputs": [],
   "source": [
    "from math import isclose\n",
    "\n",
    "assert isclose(power_int(2, -3), 0.125, rel_tol = 1e-9)\n"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "b4b804f0",
   "metadata": {},
   "source": [
    "**Задача 10. Сумма положительных аргументов**\n",
    "\n",
    "Опишите функцию `sum_positive(*numbers)`, возвращающую сумму положительных среди переданных ей целых чисел. Вызовите её с несколькими числовыми аргументами.\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "513d7a89",
   "metadata": {},
   "outputs": [],
   "source": [
    "def sum_positive(*numbers):\n",
    "    ..."
   ]
  },
  {
   "cell_type": "markdown",
   "id": "18c9e59f",
   "metadata": {},
   "source": [
    "*Пример проверки.* Запустите ячейку с функцией, затем эту ячейку. Допишите еще несколько тестов.\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 44,
   "id": "960b13e0",
   "metadata": {},
   "outputs": [],
   "source": [
    "assert sum_positive(-2, 5, 0, 7, -1) == 12\n"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "79d6d62b",
   "metadata": {},
   "source": [
    "**Задача 11. Все ли числа делятся**\n",
    "\n",
    "Опишите функцию `all_divisible_by(divisor, *numbers)`, возвращающую `True`, если каждое переданное целое число делится на `divisor`.\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "054720cd",
   "metadata": {},
   "outputs": [],
   "source": [
    "def all_divisible_by(divisor, *numbers):\n",
    "    ..."
   ]
  },
  {
   "cell_type": "markdown",
   "id": "fa74d77d",
   "metadata": {},
   "source": [
    "*Пример проверки.* Запустите ячейку с функцией, затем эту ячейку. Допишите еще несколько тестов.\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 46,
   "id": "28bbf30d",
   "metadata": {},
   "outputs": [],
   "source": [
    "assert all_divisible_by(3, 6, 9, 12)\n",
    "assert not all_divisible_by(3, 6, 10, 12)\n"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "a0c91bc3",
   "metadata": {},
   "source": [
    "**Задача 12. Минимум и максимум аргументов**\n",
    "\n",
    "Опишите функцию `min_max(*numbers)`, возвращающую минимум и максимум среди переданных вещественных чисел (хотя бы одно число есть). Не используйте встроенные `min` и `max`."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "dee53773",
   "metadata": {},
   "outputs": [],
   "source": [
    "def min_max(*numbers):\n",
    "    ..."
   ]
  },
  {
   "cell_type": "markdown",
   "id": "4b03c757",
   "metadata": {},
   "source": [
    "*Пример проверки.* Запустите ячейку с функцией, затем эту ячейку. Допишите еще несколько тестов.\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 51,
   "id": "b4c26107",
   "metadata": {},
   "outputs": [],
   "source": [
    "mn, mx = min_max(7.5, -2.23, 15.67, 0.01, 9.04)\n",
    "assert isclose(mn, -2.23, rel_tol = 1e-9)\n",
    "assert isclose(mx, 15.67, rel_tol = 1e-9)\n"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "cc54894f-c100-4546-a131-03f28e404d65",
   "metadata": {},
   "source": [
    "**Задача 13. Количество и сумма цифр**\n",
    "\n",
    "Опишите функцию `digit_count_and_sum(number)`, возвращающую количество цифр и сумму цифр положительного целого числа `number`. Распакуйте возвращённые значения в основной программе в переменные, а затем выведите их."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 53,
   "id": "e4ba890f-9bef-494f-a5c2-9cb4662b67c6",
   "metadata": {},
   "outputs": [
    {
     "name": "stdin",
     "output_type": "stream",
     "text": [
      "Введите положительное целое число:  12764\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Количество цифр: 5, сумма цифр: 20\n"
     ]
    }
   ],
   "source": [
    "def digit_count_and_sum(number):\n",
    "    ..."
   ]
  },
  {
   "cell_type": "markdown",
   "id": "549ddede-2c98-4d2a-8665-c72dff9982a0",
   "metadata": {},
   "source": [
    "*Пример проверки.* Запустите ячейку с функцией, затем эту ячейку. Допишите еще несколько тестов."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 54,
   "id": "41f21948-3b3a-490c-8f64-d420b0569f4f",
   "metadata": {},
   "outputs": [],
   "source": [
    "assert digit_count_and_sum(50702) == (5, 14)\n"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "a486869a-149e-448e-afca-a59dc3935e43",
   "metadata": {},
   "source": [
    "**Задача 14. Добавление цифры слева**\n",
    "\n",
    "Используя функцию `digit_count_and_sum` из прошлой задачи, опишите функцию `add_left_digit(digit, number)`, добавляющую цифру `digit` слева к положительному целому числу `number` и возвращающую полученное число. Считайте, что $1 \\leqslant digit \\leqslant 9$.\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "ef2e1896-4ca1-4ab1-89e2-10d6ab594248",
   "metadata": {},
   "outputs": [],
   "source": [
    "def add_left_digit(digit, number):\n",
    "    ..."
   ]
  },
  {
   "cell_type": "markdown",
   "id": "375899ff-3d61-4ceb-91cc-2803204c7cda",
   "metadata": {},
   "source": [
    "*Пример проверки.* Запустите ячейку с функцией, затем эту ячейку. Допишите еще несколько тестов.\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 56,
   "id": "aae7be85-014d-4289-ba41-d12dc50491d0",
   "metadata": {},
   "outputs": [],
   "source": [
    "assert add_left_digit(7, 205) == 7205\n"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "6bb6e5fe-69e4-42fc-97c7-b31a8e10f991",
   "metadata": {},
   "source": [
    "**Задача 15. Число Армстронга**\n",
    "\n",
    "Положительное число называется *числом Армстронга*, если оно равно сумме своих цифр, возведённых в степень, равную количеству цифр. Например, $153 = 1^3 + 5^3 + 3^3$. Используя функцию `digit_count_and_sum` из задачи 13 для нахождения количества цифр, опишите булеву функцию `is_armstrong(number)`.\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "6d4b4035-94df-4b20-9d35-2ef562252fa1",
   "metadata": {},
   "outputs": [],
   "source": [
    "def is_armstrong(number):\n",
    "    ..."
   ]
  },
  {
   "cell_type": "markdown",
   "id": "3e5f3229-e877-4b63-b9dd-72d8d941790a",
   "metadata": {},
   "source": [
    "*Пример проверки.* Запустите ячейку с функцией, затем эту ячейку. Допишите еще несколько тестов.\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 58,
   "id": "e048a660-8f60-4d71-a32e-6f1c00df93fd",
   "metadata": {},
   "outputs": [],
   "source": [
    "assert is_armstrong(153)\n",
    "assert is_armstrong(9474)\n",
    "assert not is_armstrong(154)\n"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "502ac834-fad5-42ca-b188-69de4d317d7c",
   "metadata": {},
   "source": [
    "В следующих задачах используется функция `is_leap_year(year)`, разобранная в лабораторной работе 5. Она приведена ниже как готовая вспомогательная функция, а не как новая задача. Не забудьте запустить ячейку с данной функцией.\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 59,
   "id": "2a5fcd64-6304-47cb-a1d3-e0dfe4753502",
   "metadata": {},
   "outputs": [],
   "source": [
    "def is_leap_year(year):\n",
    "    return year % 4 == 0 and (year % 100 != 0 or year % 400 == 0)\n"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "1c7b7513-9ee5-405e-854d-3097c2520307",
   "metadata": {},
   "source": [
    "**Задача 16. Количество дней в месяце**\n",
    "\n",
    "Используя `is_leap_year`, опишите функцию `month_days(month, year)`, возвращающую количество дней в месяце с номером `month` года `year`. Используйте `match/case` и не используйте списки."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "285e4b2e-cac5-4155-b263-143f883c5aee",
   "metadata": {},
   "outputs": [],
   "source": [
    "def month_days(month, year):\n",
    "    ..."
   ]
  },
  {
   "cell_type": "markdown",
   "id": "a42b2c1d-c3ae-433d-8221-ea26358dccc8",
   "metadata": {},
   "source": [
    "*Пример проверки.* Запустите ячейку с функцией, затем эту ячейку. Допишите еще несколько тестов.\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 61,
   "id": "423dd8d0-e397-427d-bf30-a17c0d2685d0",
   "metadata": {},
   "outputs": [],
   "source": [
    "assert month_days(12, 2026) == 31\n",
    "assert month_days(2, 2026) == 28\n",
    "assert month_days(2, 2000) == 29\n",
    "assert month_days(4, 2026) == 30\n"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "c0354c59-814e-4fd9-8be3-474228e29ee0",
   "metadata": {},
   "source": [
    "**Задача 17. Предыдущая дата**\n",
    "\n",
    "Используя `month_days`, опишите функцию `prev_date(day, month, year)`, которая по **правильной** дате возвращает предыдущую дату: новый день, месяц и год."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "b13e578f-d6f3-4788-9dae-c6a17f9f81fa",
   "metadata": {},
   "outputs": [],
   "source": [
    "def prev_date(day, month, year):\n",
    "    ..."
   ]
  },
  {
   "cell_type": "markdown",
   "id": "12a15fb6-649c-4f6f-9f08-e73b2e07d737",
   "metadata": {},
   "source": [
    "*Пример проверки.* Запустите ячейку с функцией, затем эту ячейку. Допишите еще несколько тестов.\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 63,
   "id": "ff8c7da8-bc7b-4f3f-bc06-be7aaaae95d1",
   "metadata": {},
   "outputs": [],
   "source": [
    "assert prev_date(15, 4, 1994) == (14, 4, 1994)\n",
    "assert prev_date(1, 3, 2024) == (29, 2, 2024)\n",
    "assert prev_date(1, 1, 2026) == (31, 12, 2025)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "495f8572-9188-42bd-8ba6-e4c239218a95",
   "metadata": {},
   "source": [
    "**Задача 18. Следующая дата**\n",
    "\n",
    "Используя `month_days`, опишите функцию `next_date(day, month, year)`, которая по **правильной** дате возвращает следующую дату: новый день, месяц и год.\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "2588e16e-fd73-416e-9a4c-e9728c09c221",
   "metadata": {},
   "outputs": [],
   "source": [
    "def next_date(day, month, year):\n",
    "    ..."
   ]
  },
  {
   "cell_type": "markdown",
   "id": "929e67a6-3038-468a-b7ea-da25fcb923f7",
   "metadata": {},
   "source": [
    "*Пример проверки.* Запустите ячейку с функцией, затем эту ячейку. Допишите еще несколько тестов.\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 65,
   "id": "85f7f202-1dff-45aa-ab58-311e37d94b62",
   "metadata": {},
   "outputs": [],
   "source": [
    "assert next_date(28, 2, 2023) == (1, 3, 2023)\n",
    "assert next_date(28, 2, 2024) == (29, 2, 2024)\n",
    "assert next_date(31, 12, 2025) == (1, 1, 2026)\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "276d77c7-7ac5-4d7d-9567-c8aaea7c7515",
   "metadata": {},
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python [conda env:base] *",
   "language": "python",
   "name": "conda-base-py"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.13.5"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}
