{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "<table align=right>\n",
    "    <tr>\n",
    "        <td align=center>\n",
    "            <font size=5><b>Программирование $-$ 2026.</b></font> \n",
    "        </td>\n",
    "        <td align=right>\n",
    "<img src=\"logoMM.png\" align=right width=120>\n",
    "        </td>\n",
    "    </tr>\n",
    "    </table>"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "<img src=\"helix.png\" align=right width=300>\n",
    "\n",
    "# Циклы\n",
    "---"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Цикл `while`\n",
    "\n",
    "Вспомним вот эту задачу \n",
    "\n",
    "---\n",
    "**Integer8**. Дано двузначное число. Вывести число, полученное при перестановке цифр исходного числа.\n",
    "\n",
    "---\n",
    "и ее решение\n",
    "```python\n",
    "n = int(input(\"двузначное число: \"))\n",
    "e = n%10\n",
    "d = n//10\n",
    "print(10*e + d)\n",
    "```\n",
    "\n",
    "Немного подумав и удлинив код, можно записать решение и для трехзначных чисел. И даже для четырехзначных. А для 150-значных? 😱🤷‍♂️\n",
    "\n",
    "На помощь приходят **циклы**. Они дают возможность выполнить одну и ту же последовательность действий много раз. \n",
    "\n",
    "Как много? Столько, столько требуется (если, конечно, программа написана правильно). \n",
    "\n",
    "---\n",
    "\n",
    "Цикл while (\"***пока***\") позволяет выполнять последовательность одинаковых действий, пока проверяемое условие истинно.\n",
    "\n",
    "Чуть позже решим задачу типа **Integer8** для числа с любым количеством десятичных цифр. А пока еще картинка и задачи попроще.\n",
    "\n",
    "<img src=\"while_scheme.png\" align=right width=300>\n",
    "\n",
    "Синтаксис цикла `while` в простейшем случае выглядит так: \n",
    "```python\n",
    "# предыдущий код\n",
    "while условие:\n",
    "    действие 1\n",
    "    действие 1\n",
    "    ...\n",
    "    действие N\n",
    "# код после цикла    \n",
    "```\n",
    "При выполнении цикла `while` сначала проверяется истинность или ложность условия. Если условие истинно, то выполняется цепочка действий (*тело цикла* или одна *итерация*), после чего условие проверяется снова и снова выполняется эта цепочка. Так продолжается до тех пор, пока условие будет истинно. Как только условие станет ложно, работа цикла завершится и управление передастся следующей инструкции после цикла. \n",
    "\n",
    "Если условие ложно в самом начале, то цикл не начинается, управление сразу передается на следующую команду после тела цикла `while`. \n",
    "\n",
    "---\n",
    "\n",
    "В качестве примера рассмотрим задачу:  \n",
    "Дано натуральное число $m$. Вычислить $m^2$, не используя символ `*`. \n",
    "\n",
    "Умножения придется заменить сложением:\n",
    "$$ m^2 = \\underbrace{m + m + \\ldots + m}_{m \\ слагаемых}$$\n",
    "\n",
    "На каждом шаге цикла нужно увеличивать сумму, а также уменьшать оставшееся количество итераций."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {},
   "outputs": [
    {
     "name": "stdin",
     "output_type": "stream",
     "text": [
      "m:  120\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "m^2 = 14400\n"
     ]
    }
   ],
   "source": [
    "m = int(input(\"m: \"))\n",
    "iters_left = m      # количество оставшихся итераций\n",
    "answer = 0          # переменная для накопления суммы\n",
    "while iters_left>0:\n",
    "    answer += m\n",
    "    iters_left -= 1\n",
    "print(f'm^2 = {answer}')    "
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Устные упражнения:  определите результат работы программы"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "0\n",
      "1\n",
      "2\n",
      "3\n",
      "4\n",
      "5\n",
      "Вне цикла\n",
      "6\n"
     ]
    }
   ],
   "source": [
    "# Пример 1. Что выведет программа?\n",
    "\n",
    "num = 0\n",
    "while num <= 5:\n",
    "    print (num)\n",
    "    num += 1\n",
    "\n",
    "print (\"Вне цикла\")\n",
    "print (num)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {},
   "outputs": [
    {
     "ename": "KeyboardInterrupt",
     "evalue": "",
     "output_type": "error",
     "traceback": [
      "\u001b[31m---------------------------------------------------------------------------\u001b[39m",
      "\u001b[31mKeyboardInterrupt\u001b[39m                         Traceback (most recent call last)",
      "\u001b[36mCell\u001b[39m\u001b[36m \u001b[39m\u001b[32mIn[3]\u001b[39m\u001b[32m, line 6\u001b[39m\n\u001b[32m      4\u001b[39m number_of_apples = \u001b[32m2\u001b[39m\n\u001b[32m      5\u001b[39m \u001b[38;5;28;01mwhile\u001b[39;00m number_of_loops < \u001b[32m10\u001b[39m:\n\u001b[32m----> \u001b[39m\u001b[32m6\u001b[39m     \u001b[43mnumber_of_apples\u001b[49m\u001b[43m \u001b[49m\u001b[43m*\u001b[49m\u001b[43m=\u001b[49m\u001b[43m \u001b[49m\u001b[32;43m2\u001b[39;49m\n\u001b[32m      7\u001b[39m     number_of_apples += number_of_loops\n\u001b[32m      8\u001b[39m     number_of_loops -= \u001b[32m1\u001b[39m\n",
      "\u001b[31mKeyboardInterrupt\u001b[39m: "
     ]
    }
   ],
   "source": [
    "# Пример 2. Что выведет программа?\n",
    "\n",
    "number_of_loops = 0\n",
    "number_of_apples = 2\n",
    "while number_of_loops < 10:\n",
    "    number_of_apples *= 2\n",
    "    number_of_apples += number_of_loops\n",
    "    number_of_loops -= 1\n",
    "print (\"Количество яблок: \", number_of_apples)\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "-565095"
      ]
     },
     "execution_count": 4,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "number_of_loops"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "9\n",
      "8\n",
      "7\n",
      "6\n",
      "5\n",
      "4\n",
      "3\n"
     ]
    }
   ],
   "source": [
    "# Пример 3. Что выведет программа?\n",
    "\n",
    "num = 10\n",
    "while num > 3:\n",
    "    num -= 1\n",
    "    print (num) "
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "В языке Питон, как и во многих других языках, есть специальная команда, позволяющая прервать выполнение итераций цикла и сразу перейти к командам, расположенным после тела цикла. Это команда `break`."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "10\n",
      "9\n",
      "8\n",
      "7\n",
      "Прерываем цикл\n",
      "После цикла\n"
     ]
    }
   ],
   "source": [
    "# Пример 4. Что выведет программа?\n",
    "\n",
    "num = 10\n",
    "while True:\n",
    "    if num < 7:\n",
    "        print ('Прерываем цикл')\n",
    "        break\n",
    "    print (num)\n",
    "    num -= 1\n",
    "print ('После цикла')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# Пример 5. Что выведет программа?\n",
    "\n",
    "num = 100\n",
    "while not False:\n",
    "    if num < 0:\n",
    "        break\n",
    "print ('num is:', num)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Порешаем задачи\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "**While4**. Дано целое число $n$ (> 0). Если оно является степенью числа 3, то вывести `True`, если не является — вывести `False`."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "metadata": {},
   "outputs": [
    {
     "name": "stdin",
     "output_type": "stream",
     "text": [
      "целое число:  5689143\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "False\n",
      "False\n"
     ]
    }
   ],
   "source": [
    "# Решение\n",
    "n = int(input(\"целое число: \"))\n",
    "# вариант 1\n",
    "p = 1\n",
    "while p<n:\n",
    "    p *= 3\n",
    "print(p==n)\n",
    "# вариант 2\n",
    "while n%3==0:\n",
    "    n //= 3\n",
    "print(n==1)\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "**Integer8** (усложненный вариант). Дано натуральное число. Вывести число, полученное при перестановке цифр исходного числа в обратном порядке.\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "metadata": {},
   "outputs": [
    {
     "name": "stdin",
     "output_type": "stream",
     "text": [
      "натуральное число:  567843\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "348765\n"
     ]
    }
   ],
   "source": [
    "# Решение\n",
    "n = int(input(\"натуральное число: \"))\n",
    "s = 0\n",
    "while n>0:\n",
    "    s = s*10 + n%10\n",
    "    n //= 10\n",
    "print(s)    \n",
    "   \n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "**While22**. Дано целое число $n$ (> 1). Если оно является простым, т. е. не имеет положительных делителей, кроме 1 и самого себя, то вывести `True`, иначе вывести `False`. \n",
    "\n",
    "*Работу программы можно проверить на числах 9973, 9999901 и 2147483647, которые являются простыми*."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 15,
   "metadata": {
    "scrolled": true
   },
   "outputs": [
    {
     "name": "stdin",
     "output_type": "stream",
     "text": [
      "натуральное число:  9999901\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "True\n"
     ]
    }
   ],
   "source": [
    "# Решение 1\n",
    "n = int(input(\"натуральное число: \"))\n",
    "k = 2\n",
    "while True:\n",
    "    if n%k==0:\n",
    "        break\n",
    "    k += 1\n",
    "print(n==k)\n",
    "        "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {
    "scrolled": true
   },
   "outputs": [
    {
     "name": "stdin",
     "output_type": "stream",
     "text": [
      "натуральное число:  2147483647\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "True\n"
     ]
    }
   ],
   "source": [
    "# Решение 2\n",
    "n = int(input(\"натуральное число: \"))\n",
    "k = 2\n",
    "while k*k<=n:\n",
    "    if n%k==0:\n",
    "        break\n",
    "    k += 1\n",
    "print(k*k>n)      "
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "**While24**. Дано целое число $n$ (> 1). Последовательность чисел Фибоначчи $F_k$ определяется следующим образом: \n",
    "$$\n",
    "F_1 = 1, \\  F_2 = 1,  F_k = F_{k-2} + F_{k−1},  \\  k = 3, 4, \\ldots.\n",
    "$$\n",
    "Проверить, является ли число $n$ числом Фибоначчи. Если является, то вывести `True`, если нет — вывести `False`. \n",
    "\n",
    "*Например, 17711 -  число Фибоначчи*\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "metadata": {
    "scrolled": true
   },
   "outputs": [
    {
     "name": "stdin",
     "output_type": "stream",
     "text": [
      "натуральное число:  17711\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "True\n"
     ]
    }
   ],
   "source": [
    "# Решение\n",
    "n = int(input(\"натуральное число: \"))\n",
    "a, b = 1, 1\n",
    "while b<n:\n",
    "    a, b = b, a+b\n",
    "print(b==n)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "<div style=\"color:blue;\">\n",
    "\n",
    "***Для самостоятельного чтения***\n",
    "\n",
    "«**Стандартное отклонение**» (pythontutor.ru)   \n",
    "Дана последовательность натуральных чисел $x_1$, $x_2$, ..., $x_n$. *Стандартным отклонением* называется величина\n",
    "$$\n",
    "\\sigma =\\sqrt{\\frac{(x_1-s)^2+(x_2-s)^2+\\ldots+(x_n-s)^2}{n-1}}\n",
    "$$\n",
    "где $s=\\frac{x_1+x_2+…+x_n}{n}$ — среднее арифметическое последовательности.\n",
    "\n",
    "Определите стандартное отклонение для данной последовательности натуральных чисел, завершающейся числом 0.\n",
    "\n",
    "\n",
    "\n",
    "---\n",
    "\n",
    "**Комментарий к решению**.  \n",
    "На первый взгляд, задачу нельзя решить, не сохраняя все значения переменных $x_k$, потому что для вычисления, например, $(x_1-s)$ нужно знать $s$, то есть сначала нужно ввести все числа, а потом вернуться к $x_1$.\n",
    "\n",
    "Решить задачу помогает школьная алгебра и знание формулы \n",
    "$$(a-b)^2 = a^2-2ab+b^2.$$\n",
    "Действительно,\n",
    "$$\n",
    "(x_1-s)^2+(x_2-s)^2+\\ldots+(x_n-s)^2 = \n",
    "$$\n",
    "$$\n",
    "=x_1^2-2x_1s+s^2 + x_2^2-2x_2s+s^2 +\\ldots x_n^2-2x_ns+s^2=\n",
    "$$\n",
    "$$\n",
    "= \\sum_{i=1}^n{x_i^2} - 2\\sum_{i=1}^n{x_i}s+ns^2 = \n",
    "$$\n",
    "$$\n",
    "= \\sum_{i=1}^n{x_i^2} - \\frac{2}{n}\\left(\\sum_{i=1}^n{x_i}\\right)^2 + \n",
    "\\frac{1}{n}\\left(\\sum_{i=1}^n{x_i}\\right)^2 = \n",
    "$$\n",
    "$$\n",
    "= \\sum_{i=1}^n{x_i^2} - \\frac{1}{n}\\left(\\sum_{i=1}^n{x_i}\\right)^2.\n",
    "$$\n",
    "\n",
    "Таким образом, в процессе ввода необходимо накапливать значение суммы вводимых чисел и суммы их квадратов."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "scrolled": true
   },
   "outputs": [],
   "source": [
    "# Решение\n",
    "summ = 0\n",
    "summ2 = 0\n",
    "n = 0\n",
    "x = int(input('x: '))\n",
    "while x != 0:\n",
    "    summ += x\n",
    "    summ2 += x**2\n",
    "    n += 1\n",
    "    x = int(input('x: '))\n",
    "sigma = ((summ2-summ**2/n)/(n-1))**0.5\n",
    "print(sigma)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Цикл `for`\n",
    "\n",
    "Цикл `for`, также называемый циклом с параметром, позволяет выполнить заранее известное количество итераций. Параметр цикла, или *счетчик*, $-$ это переменная, указываемая в цикле `for`. В нем также задается множество (диапазон) значений, по которому будет пробегать эта переменная. \n",
    "```python\n",
    "# ... какой-то код до цикла\n",
    "for параметр_цикла in множество_значений:\n",
    "    действие 1\n",
    "    действие 2\n",
    "    ...\n",
    "    действие N\n",
    "# ... код после цикла  \n",
    "```\n",
    "    \n",
    "Множество значений может быть задано, например, списком, строкой или диапазоном. Начнем с последнего $-$ очень распространенного и полезного объекта `range()`."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "1 2 3 4 5 6 7 8 9 "
     ]
    }
   ],
   "source": [
    "# меняйте параметры функции range, \n",
    "#         чтобы лучше понять, как она работает\n",
    "for i in  range(1,10): # [1, 10)\n",
    "    print(i, end=' ')    "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "0 1 2 3 4 5 6 7 8 9 "
     ]
    }
   ],
   "source": [
    "for i in range(0,10):\n",
    "    print(i, end=' ')    "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "0 1 2 3 4 5 6 7 8 9 "
     ]
    }
   ],
   "source": [
    "for i in range(10):\n",
    "    print(i, end=' ')    "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 12,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "0 2 4 6 8 "
     ]
    }
   ],
   "source": [
    "for i in range(0,10,2):\n",
    "    print(i, end=' ')    "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 13,
   "metadata": {},
   "outputs": [],
   "source": [
    "for i in range(0,10,-1):\n",
    "    print(i, end=' ')    "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 14,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "10 9 8 7 6 5 4 3 2 1 "
     ]
    }
   ],
   "source": [
    "for i in range(10,0,-1): #[10, 0)\n",
    "    print(i, end=' ')    "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "range(0, 10)"
      ]
     },
     "execution_count": 1,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "range(10)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 17,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "True"
      ]
     },
     "execution_count": 17,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# range умеет проверять\n",
    "500 in range(1000)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Примеры других вариантов задания множества значений параметра цикла."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 18,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Цвета российского флага:\n",
      "Цвет 1 - белый\n",
      "Цвет 2 - синий\n",
      "Цвет 3 - красный\n"
     ]
    }
   ],
   "source": [
    "# \"перечисление\" (список или кортеж)\n",
    "print('Цвета российского флага:')\n",
    "i = 1\n",
    "for color in 'белый', 'синий', 'красный':\n",
    "    print(f'Цвет {i} - {color}')\n",
    "    i += 1"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 19,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "1-й цвет радуги - это красный\n",
      "2-й цвет радуги - это оранжевый\n",
      "3-й цвет радуги - это желтый\n",
      "4-й цвет радуги - это зеленый\n",
      "5-й цвет радуги - это голубой\n",
      "6-й цвет радуги - это синий\n",
      "7-й цвет радуги - это фиолетовый\n"
     ]
    }
   ],
   "source": [
    "# В этом примере ниже cимвол \"\\\" позволил разорвать\n",
    "# слишком длинную строку кода (для удобства чтения)\n",
    "# После этого символа в строке не должно быть ничего, \n",
    "#       даже пробела\n",
    "\n",
    "i = 1\n",
    "for цвет in 'красный','оранжевый',  \\\n",
    "            'желтый', 'зеленый', 'голубой', \\\n",
    "            'синий', 'фиолетовый':\n",
    "    print(f'{i}-й цвет радуги - это {цвет}')\n",
    "    i += 1\n",
    "\n",
    "# И да, Python разрешает русские имена переменных.\n",
    "# Но не стоит этим злоупотреблять!"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 20,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Название 1-го цвета радуги начинается с буквы К\n",
      "Название 2-го цвета радуги начинается с буквы О\n",
      "Название 3-го цвета радуги начинается с буквы Ж\n",
      "Название 4-го цвета радуги начинается с буквы З\n",
      "Название 5-го цвета радуги начинается с буквы Г\n",
      "Название 6-го цвета радуги начинается с буквы С\n",
      "Название 7-го цвета радуги начинается с буквы Ф\n"
     ]
    }
   ],
   "source": [
    "# Цикл по символам строки\n",
    "i = 1\n",
    "for letter in 'КОЖЗГСФ':\n",
    "    print(f'Название {i}-го цвета радуги начинается с буквы', \n",
    "          letter)\n",
    "    i += 1"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Решаем задачи"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "**Обещанное**. С использованием модуля `time` выясните, наконец, какой из двух вариантов обмена значений двух переменных работает быстрее:\n",
    "```python\n",
    "c = a\n",
    "a = b\n",
    "b = c\n",
    "```\n",
    "или\n",
    "```python\n",
    "a, b = b, a\n",
    "```"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 21,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "1.287926435470581\n",
      "0.9300200939178467\n"
     ]
    }
   ],
   "source": [
    "from time import time\n",
    "n = 10**7\n",
    "a = 10.4\n",
    "b = 20\n",
    "# 1 способ\n",
    "start = time()\n",
    "for i in range(n):\n",
    "    c = a\n",
    "    a = b\n",
    "    b = c\n",
    "finish = time()\n",
    "print(finish-start)\n",
    "\n",
    "# 2 cпособ\n",
    "start = time()\n",
    "for i in range(n):\n",
    "    a, b = b, a\n",
    "finish = time()\n",
    "print(finish-start)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "**For7**. Даны два целых числа $a$ и $b$ ($a < b$). Найти сумму всех целых чисел от $a$ до $b$ включительно."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 23,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Help on built-in function sum in module builtins:\n",
      "\n",
      "sum(iterable, /, start=0)\n",
      "    Return the sum of a 'start' value (default: 0) plus an iterable of numbers\n",
      "\n",
      "    When the iterable is empty, return the start value.\n",
      "    This function is intended specifically for use with numeric values and may\n",
      "    reject non-numeric types.\n",
      "\n"
     ]
    }
   ],
   "source": [
    "help(sum)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 24,
   "metadata": {},
   "outputs": [
    {
     "name": "stdin",
     "output_type": "stream",
     "text": [
      "введите целое число a  0\n",
      "введите целое число b  100\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "5050\n",
      "5050\n"
     ]
    }
   ],
   "source": [
    "a = int(input(\"введите целое число a \"))\n",
    "b = int(input(\"введите целое число b \"))\n",
    "# Решение с использованием цикла\n",
    "s = 0\n",
    "for i in range(a, b+1):\n",
    "    s += i\n",
    "print(s)\n",
    "\n",
    "# Эффективное решение\n",
    "print(sum(range(a, b+1)))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 25,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "49999995000000 1.3809165954589844\n",
      "49999995000000 0.1401207447052002\n"
     ]
    }
   ],
   "source": [
    "# сравнение\n",
    "from time import time\n",
    "n = 10**7\n",
    "start = time()\n",
    "s = 0\n",
    "for x in range(n):\n",
    "    s += x\n",
    "finish = time()\n",
    "print(s, finish-start)\n",
    "\n",
    "# Эффективное решение\n",
    "start = time()\n",
    "s = sum(range(n))\n",
    "finish = time()\n",
    "print(s, finish-start)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "<div style=\"color:blue;\"> ❓❓❓ Почему при решении задачи «**Стандартное отклонение**» не пользовались функцией `sum` ?"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "**For19**. Дано целое число $n$ (> 0). Найти произведение\n",
    "$$ n! = 1·2·…·n\n",
    "$$\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 27,
   "metadata": {},
   "outputs": [
    {
     "name": "stdin",
     "output_type": "stream",
     "text": [
      "введите целое n(>0):  100\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "93326215443944152681699238856266700490715968264381621468592963895217599993229915608941463976156518286253697920827223758251185210916864000000000000000000000000\n"
     ]
    }
   ],
   "source": [
    "# Решение\n",
    "n = int(input(\"введите целое n(>0): \"))\n",
    "p = 1\n",
    "for i in range(2, n+1):\n",
    "    p *= i\n",
    "print(p)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 28,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "93326215443944152681699238856266700490715968264381621468592963895217599993229915608941463976156518286253697920827223758251185210916864000000000000000000000000\n",
      "93326215443944152681699238856266700490715968264381621468592963895217599993229915608941463976156518286253697920827223758251185210916864000000000000000000000000\n"
     ]
    }
   ],
   "source": [
    "import math\n",
    "print(math.prod(range(1,n+1)))\n",
    "print(math.factorial(n))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "**For17**. Дано вещественное число $x$ и целое число $n$ (> 0). Используя один цикл (и не используя операцию возведения в степень), найти сумму \n",
    "$$\n",
    "1 + x + x^2 + x^3 + … + x^n.\n",
    "$$\n",
    "\n",
    "<font color='#0000FF'>\n",
    "    \n",
    "**дополнительно**: когда и почему в этой задаче действительно  важно не использовать возведение в степень?"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 29,
   "metadata": {},
   "outputs": [
    {
     "name": "stdin",
     "output_type": "stream",
     "text": [
      "x:  2\n",
      "введите целое n(>0):  3\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "15.0\n"
     ]
    }
   ],
   "source": [
    "# Решение\n",
    "x = float(input('x: '))\n",
    "n = int(input(\"введите целое n(>0): \"))\n",
    "s = 0\n",
    "d = 1\n",
    "for i in range(n+1):\n",
    "    s += d\n",
    "    d *= x\n",
    "print(s)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "**For24**. Дано вещественное число $x$ и целое число $n$ (> 0). Найти значение выражения \n",
    "$$\n",
    "1 − \\frac{x^2}{2!} + \\frac{x^4}{4!} − … + (−1)^n\\frac{x^{2n}}{(2n)!}\n",
    "$$\n",
    "Полученное число является приближенным значением функции $\\cos$ в точке $x$. \n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 32,
   "metadata": {},
   "outputs": [
    {
     "name": "stdin",
     "output_type": "stream",
     "text": [
      "введите x:  0.1\n",
      "введите целое n(>0):  5\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "s = 0.9950041652780258\n",
      "cos(0.1) = 0.9950041652780258\n"
     ]
    }
   ],
   "source": [
    "# Решение\n",
    "x = float(input(\"введите x: \"))\n",
    "n = int(input(\"введите целое n(>0): \"))\n",
    "s = 0\n",
    "p = 1\n",
    "d = 1\n",
    "for i in range(n+1):\n",
    "    p *= d\n",
    "    s += p\n",
    "    d = -x*x/(2*i+1)/(2*i+2)    \n",
    "print(f'{s = }')\n",
    "from math import cos\n",
    "print(f'cos({x}) = {cos(x)}')"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "**For39**. Даны целые положительные числа $m$ и $n$ ($m<n$). Вывести все целые числа от $m$ до $n$ включительно; при этом каждое число должно выводиться столько раз, каково его значение (например, число 3 выводится 3 раза)."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {},
   "outputs": [
    {
     "name": "stdin",
     "output_type": "stream",
     "text": [
      "введите целое m(>0):  5\n",
      "введите целое n(>0):  9\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "5 5 5 5 5 \n",
      "6 6 6 6 6 6 \n",
      "7 7 7 7 7 7 7 \n",
      "8 8 8 8 8 8 8 8 \n",
      "9 9 9 9 9 9 9 9 9 \n"
     ]
    }
   ],
   "source": [
    "# Решение\n",
    "m = int(input(\"введите целое m(>0): \"))\n",
    "n = int(input(\"введите целое n(>0): \"))\n",
    "for i in range(m, n+1):\n",
    "    for _ in range(i):\n",
    "        print(i, end = ' ')\n",
    "    print()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "**Minmax6**. Дано целое число $n$ и набор из $n$ целых чисел. Найти номера первого минимального и последнего максимального элемента из данного набора и вывести их в указанном порядке."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {},
   "outputs": [
    {
     "name": "stdin",
     "output_type": "stream",
     "text": [
      "введите целое n(>0):  8\n",
      " 2\n",
      " 1\n",
      " 3\n",
      " 2\n",
      " 1\n",
      " 3\n",
      " 2\n",
      " 1\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "i_min=2 i_max=6\n"
     ]
    }
   ],
   "source": [
    "# Решение\n",
    "n = int(input(\"введите целое n(>0): \"))\n",
    "min_first = max_last = int(input())\n",
    "i_min = i_max = 1\n",
    "for i in range(2, n+1):    # номера человеческие\n",
    "    a = int(input())\n",
    "    if a<min_first:\n",
    "        min_first = a\n",
    "        i_min = i\n",
    "    if a>=max_last:\n",
    "        max_last = a\n",
    "        i_max = i\n",
    "print(f'{i_min=} {i_max=}')    \n",
    "      \n",
    "# 2 1 3 2 1 3 2 1"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Задача с сайта pythontutor.ru"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "**Карточка**. Для настольной игры используются карточки с номерами от 1 до $n$. Одна карточка потерялась. Найдите ее, зная номера оставшихся карточек.\n",
    "\n",
    "Дано число $n$, далее $n-1$ номер оставшихся карточек (различные числа от 1 до $n$). Программа должна вывести номер потерянной карточки."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# Решение\n",
    "n = int(input(\"введите натуральное n: \"))\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "---\n",
    "\n",
    "### Первое знакомство с методом половинного деления. Он же метод бинарного поиска. Или дихотомии. \n",
    "\n",
    "Дано вещественное число $z$. Найдите кубический корень из этого числа с заданной точностью $\\varepsilon$.\n",
    "\n",
    "*Найти с заданной точностью* означает \"найти такое число $x$, что $|x-\\sqrt[3]{z}|<\\varepsilon$\"."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Сначала рассмотрим вспомогательную задачу:  \\\n",
    "*Дано натуральное число $N$. Проверьте, является ли это число кубом*"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 35,
   "metadata": {},
   "outputs": [
    {
     "name": "stdin",
     "output_type": "stream",
     "text": [
      "Введите натуральное число:  64\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "кубический корень равен 4\n"
     ]
    }
   ],
   "source": [
    "N = int(input('Введите натуральное число: '))\n",
    "ans = 0\n",
    "while ans**3 < N:\n",
    "    ans += 1\n",
    "if ans**3 == N:\n",
    "    print('кубический корень равен',ans)\n",
    "else:\n",
    "    print('число не является точным кубом')"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Для вычисления кубического корня из вещественного числа можно использовать эту же идею.\n",
    "Только прибавлять нужно не единицу, а $\\varepsilon$. "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 38,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "1.2599210507102045\n"
     ]
    }
   ],
   "source": [
    "eps = 1e-8\n",
    "#z = float(input(\"z (>0): \"))\n",
    "z = 2.0\n",
    "ans = 0\n",
    "while ans**3<z:\n",
    "    ans += eps\n",
    "print(ans)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 37,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "1.2599210498948732"
      ]
     },
     "execution_count": 37,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "2**(1/3)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "К сожалению, эта программа работает очень медленно: если $\\varepsilon=10^{-12}$, то результата можем не дождаться (впрочем, желающие могут попробовать)\n",
    "\n",
    "Идея: корень точно больше нуля и меньше двух. \n",
    "Сначала возьмем середину этого отрезка и обозначим ее через $c$. Корень слева от $c$, если $c^3>z$, или справа, если $c^3<z$. Выберем ту половину, где корень, и найдем ее середину. Повторяем процесс, пока очередная половинка не станет меньше, чем $\\varepsilon$"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "1.2599210498948779\n"
     ]
    }
   ],
   "source": [
    "# Решение\n",
    "eps = 1e-14\n",
    "#z = float(input('z='))\n",
    "z = 2\n",
    "a = 0\n",
    "b = z\n",
    "while abs(b-a)>eps:\n",
    "    c = (a+b)/2\n",
    "    if c**3<z:\n",
    "        a = c\n",
    "    else:\n",
    "        b = c\n",
    "print(c)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 40,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "1.2599210498948732"
      ]
     },
     "execution_count": 40,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "2**(1/3)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Подумать:\n",
    "\n",
    "- почему программа работает неправильно, если `z` <= 1?\n",
    "- что произойдет, если `с**3` окажется точно равным `z`?\n",
    "- Как исправить программу, чтобы корень извлекался и из положительных, и из отрицательных чисел?\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Подсказка по первому пункту: (выдели мышкой)\n",
    "\n",
    "<font color='#FFFFFF'> \n",
    "кубический корень из положительного числа z точно находится на отрезке [0, max(1,z)]. "
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Готовимся к контрольной \n",
    "\n",
    "\n",
    "<font color='#0000FF'>\n",
    "    \n",
    "Назовем положительное число $n$ *квадратно-четным*, если все цифры его \n",
    "квадрата $–$ четные. Среди однозначных таких чисел два ($2$ и $8$), примером \n",
    "двухзначных могут служить числа $20$ и $68$ ($20^2 = 400$, $68^2 = 4624$), $498$ $–$ это \n",
    "пример трехзначного квадратно-четного числа ($498^2 = 248004$). \n",
    "Разработайте программу, которая для заданного натурального числа $m$ \n",
    "($m<8$) определяет, сколько существует $m$-значных квадратно-четных чисел. \n",
    "Примерная схема взаимодействия программы с пользователем: \n",
    "\n",
    "\n",
    "|Введенное число|Сообщение программы|\n",
    "|:-------------:|:------------------|\n",
    "| m = -1 | Введенное Вами число должны быть положительно. Учтите это при следующем запуске программы   |\n",
    "| m = 10 | Ваше число больше семи. Программа может работать слишком долго. В следующий раз введите число поменьше   |\n",
    "| m = 2  | Кол-во 2-значных квадратно-четных чисел = 6     |\n",
    "| m = 3  | Кол-во 3-значных квадратно-четных чисел = 18    |\n",
    "| m = 7  | Кол-во 7-значных квадратно-четных чисел = 850   |\n",
    "\n",
    "\n",
    "\n",
    "\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# Решение\n",
    "m = int(input('m:'))\n",
    "if m<=0:\n",
    "    print('Введенное Вами число должны быть положительно. Учтите это при следующем запуске программы')\n",
    "elif m>7:    \n",
    "    print('Ваше число больше семи. Программа может работать слишком долго. В следующий раз введите число поменьше')\n",
    "else:\n",
    "    pass\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Цепочки\n",
    "\n",
    "Немецкий математик Лотар Коллатц в 1937 году предложил следующее правило построения одной замечательной последовательности. Берём любое натуральное число $n$. Если оно чётное, то делим его на 2, а если нечётное, то умножаем на 3 и прибавляем 1 (получаем $3n + 1$). Над полученным числом выполняем те же самые действия, и так далее. Гипотеза Коллатца состоит в том, что для любого натурального $n$ такая последовательность за конечное число шагов приведет нас к единице. И хотя эта гипотеза до сих пор строго не доказана, будем считать ее верной. \n",
    "\n",
    "Назовём последовательность построенных таким образом чисел (от $n$ до $1$) «цепочкой Коллатца». Например, для числа $13$ эта цепочка имеет длину $10$, т.е. содержит $10$ элементов:\n",
    "$$\n",
    "13 → 40 → 20 → 10 → 5 → 16 → 8 → 4 → 2 → 1\n",
    "$$\n",
    "Напишите программу, которая для двух заданных натуральных чисел $k$ и $m$ \n",
    "($0 < k < 1000000$) ищет количество цепочек Коллатца длины $m$ для всех натуральных значений $n$ из отрезка $[1, k]$ .\n",
    "\n",
    "Примерная схема взаимодействия с пользователем:\n",
    "\n",
    "<img src=\"kollatz.png\" width=600>\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {},
   "outputs": [
    {
     "name": "stdin",
     "output_type": "stream",
     "text": [
      "Укажите верхнюю границу диапазона поиска:   10000\n",
      "Укажите длину цепочки Коллатца:  10\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "количество цепочек длины 10 в данном диапазоне 1<n<10000 равно 6\n"
     ]
    }
   ],
   "source": [
    "k = int(input(\"Укажите верхнюю границу диапазона поиска:  \"))\n",
    "m = int(input(\"Укажите длину цепочки Коллатца: \"))\n",
    "if (k <= 0) or (m<=0):\n",
    "    print('Введенные Вами числа должны быть положительны.')\n",
    "    print('Учтите это при следующем запуске программы')\n",
    "elif k>1000000:\n",
    "    print('Диапазон поиска больше миллиона. Устанете ждать.')\n",
    "    print('В следующий раз введите число, не превосходящее миллион.')\n",
    "else:\n",
    "    s = 0\n",
    "    for i in range (1, k+1):\n",
    "        # -------- запускаем цепочку\n",
    "        n = i\n",
    "        c = 1\n",
    "        while n != 1:\n",
    "            if n % 2 == 0:\n",
    "                 n //= 2\n",
    "            else:\n",
    "                 n = 3*n +1\n",
    "            c += 1\n",
    "        if c == m:\n",
    "            s += 1       \n",
    "    print(f'количество цепочек длины {m} в диапазоне 1<n<{k} равно {s}')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3 (ipykernel)",
   "language": "python",
   "name": "python3"
  },
  "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.11.1"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 4
}
