{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Списки"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "**Из программы экзамена:**\n",
    "\n",
    "13.\tСписки. Доступ к элементу списка. Срез списка. Способы создания списка. Добавление элемента к списку. Создание списков с использованием генераторов списков. Отличие списка, созданного на основе генератора, и самого генератора. Определение длины списка, сложение списков, умножение списка на число. Копирование списка. Метод `split()` для создания списка из строки и метод `join()` для объединения списка строк. Способы перебора элементов списка. Удаление элемента из списка, вставка элемента в список, поиск значения в списке, перестановка элементов списка в обратном порядке, подсчет элементов списка, равных заданному значению.  Типовые задачи для списков: определение количества элементов в списке, удовлетворяющих определенному условию (четный, положительный, больший своего соседа справа  и т.п.); нахождение максимального или минимального элемента в списке; суммирование  элементов списка или его части. \n",
    "14.\tЛямбда-выражение (лямбда-функция, лямбда-оператор). Функции `map()` и `filter()`.\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Список: варианты определения\n",
    "\n",
    "**Списки** это упорядоченные изменяемые коллекции объектов произвольных типов [[1]](https://pythonworld.ru/tipy-dannyx-v-python/spiski-list-funkcii-i-metody-spiskov.html)\n",
    "\n",
    "**Список** &ndash; тип данных, предназначенный для хранения набора или последовательности разных элементов [[2]](https://pythonchik.ru/osnovy/spiski-v-python)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Списки в жизни\n",
    "\n",
    "* Список группы\n",
    "* Список Forbes\n",
    "* Список номеров лотереи\n",
    "* Список покупок\n",
    "\n",
    "<img src=\"списки.jpg\" align=left width=600/>"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {
    "scrolled": true
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "['Бехжа Абир',\n",
       " 'Загребаева Маргарита',\n",
       " 'Йерена Корнехо Алекс Давид',\n",
       " 'Ли Дмитрий',\n",
       " 'Нагорная Алина',\n",
       " 'Недилько Андрей',\n",
       " 'Петров Константин',\n",
       " 'Прохоренко Анастасия',\n",
       " 'Старков Максим']"
      ]
     },
     "execution_count": 1,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# список группы (список строк)\n",
    "['Бехжа Абир', 'Загребаева Маргарита', 'Йерена Корнехо Алекс Давид', \n",
    " 'Ли Дмитрий', 'Нагорная Алина', 'Недилько Андрей',\n",
    " 'Петров Константин', 'Прохоренко Анастасия', \n",
    " 'Старков Максим']"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "[69, 75, 6, 88, 34, 54, 19]"
      ]
     },
     "execution_count": 2,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# список победных номеров (список целых чисел)\n",
    "[69, 75, 6, 88, 34, 54, 19]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "['Jeff Bezos',\n",
       " 145.1,\n",
       " 'Bill Gates',\n",
       " 103.6,\n",
       " 'Bernard Arnault & family',\n",
       " 91.5,\n",
       " 'Warren Buffett',\n",
       " 73.4,\n",
       " 'Mark Zuckerberg',\n",
       " 68.8]"
      ]
     },
     "execution_count": 3,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# список Форбс (список строк)\n",
    "['Jeff Bezos', 'Bill Gates', 'Bernard Arnault & family',\n",
    " 'Warren Buffett', 'Mark Zuckerberg']\n",
    "# список благосостояния (список вещественных чисел)\n",
    "[145.1, 103.6, 91.5, 73.4, 68.8]\n",
    "\n",
    "# а можно и так - элементы списка могут иметь разный тип\n",
    "['Jeff Bezos', 145.1, 'Bill Gates', 103.6,\n",
    " 'Bernard Arnault & family', 91.5,\n",
    " 'Warren Buffett', 73.4, 'Mark Zuckerberg', 68.8]\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "[['Картофель', 'Зелень'],\n",
       " ['Зеленый горошек', 'Хлеб', 'Молоко'],\n",
       " ['Маска', 'Аспирин'],\n",
       " ['Батарейка']]"
      ]
     },
     "execution_count": 4,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# список покупок - это список списков\n",
    "[['Картофель','Зелень'], \n",
    " ['Зеленый горошек', 'Хлеб', 'Молоко'], \n",
    " ['Маска', 'Аспирин'], ['Батарейка']]\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[1, 2, 3]\n"
     ]
    }
   ],
   "source": [
    "x = [1, 2, 3]\n",
    "print(x)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "list"
      ]
     },
     "execution_count": 6,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "type(x)\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Какую букву выбрать для списка *по умолчанию*? Наверное, `l`, от слова `list`?  "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "l = [0, 10, 35]"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "**Нет!** \n",
    "\n",
    "Официально ([PEP 8 -- Style Guide for Python Code](https://www.python.org/dev/peps/pep-0008/#names-to-avoid))\n",
    "<table border=2>\n",
    "    <tr>\n",
    "        <td align=\"left\">\n",
    "<u>Names to Avoid</u>\n",
    "\n",
    "Never use the characters 'l' (lowercase letter el), 'O' (uppercase letter oh), or 'I' (uppercase letter eye) as single character variable names.<br/>\n",
    "In some fonts, these characters are indistinguishable from the numerals one and zero. When tempted to use 'l', use 'L' instead.\n",
    "    </td>\n",
    "        </tr>\n",
    "            </table>\n",
    "\n",
    "\n",
    "Что здесь написано? IllI 😂\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# Цвет спасает, но не на бумаге\n",
    "x = l\n",
    "x = 1"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Если не `l`, тогда какую? Я выбираю `a` от слова `array` (массив). У массивов и списков много общего. Основное отличие: в массиве хранятся объекты одного определенного типа, в списке &ndash; любых типов. Как правило, рамер массива фиксирован, а список может изменяться (удлиняться или укорачиваться) в ходе работы программы. Массивами мы будем заниматься в следующем семестре при изучении библиотеки `numpy`.\n",
    "\n",
    "А задачи с сайта http://ptaskbook.com будут как раз из раздела **Array**, в них слово *массив* надо мысленно заменять словом *список*."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Доступ к элементу списка или к части списка"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "metadata": {},
   "outputs": [],
   "source": [
    "a = [1, 2, 3, [10, 20], [1, 2, 3]]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "1"
      ]
     },
     "execution_count": 8,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "a[0]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "[10, 20]"
      ]
     },
     "execution_count": 9,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "a[3]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "3"
      ]
     },
     "execution_count": 10,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "a[4][2]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "[2, 3, [10, 20]]"
      ]
     },
     "execution_count": 11,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# срезы как в строках\n",
    "a[1:4]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 12,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "[[1, 2, 3], [10, 20], 3, 2, 1]"
      ]
     },
     "execution_count": 12,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "a[::-1]"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "**В отличие от строки список это изменяемый объект**"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 13,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "[1, 100, 3, [10, 20], [5, 6, 7, 8]]"
      ]
     },
     "execution_count": 13,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "a[1] = 100\n",
    "a[4] = [5,6,7,8]\n",
    "a"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 14,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "[1, 0, -1, -2, [5, 6, 7, 8]]"
      ]
     },
     "execution_count": 14,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# Да, работает и со срезами! Только нужно следить за размерами списков в левой и правой части\n",
    "a[1:4]=[0,-1,-2]\n",
    "a"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "**Микро-задача**.   \n",
    "Дан список. Не используя оператор цикла, заменить его элементы с нечетными индексами символом '*'."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 18,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11]\n",
      "[0, '*', 2, '*', 4, '*', 6, '*', 8, '*', 10, '*']\n"
     ]
    }
   ],
   "source": [
    "a = [0,1,2,3,4,5,6,7,8,9,10,11]\n",
    "# заменить элементы с нечетными индексами символом '*'\n",
    "print(a)\n",
    "# решение:\n",
    "a[1::2] = ['*']*(len(a)//2)\n",
    "print(a)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Создание списка"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "**1. Вручную**"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 19,
   "metadata": {},
   "outputs": [],
   "source": [
    "a = [10, 20, 30, 40, 50]"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "**2. Cложение списков, умножение списка на число.**\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 20,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[1, 2, 3, -1, -2, -3]\n",
      "[1, 2, 3, 1, 2, 3, 1, 2, 3, 1, 2, 3, 1, 2, 3]\n"
     ]
    }
   ],
   "source": [
    "a = [1,2,3]\n",
    "b = [-1, -2, -3]\n",
    "print(a+b)\n",
    "print(a*5)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "**3. Последовательное добавление элементов**"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 21,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[10, 20, 30, 40, 50]\n"
     ]
    }
   ],
   "source": [
    "a = []\n",
    "for i in range(1,6):\n",
    "    a.append(i*10)\n",
    "print(a)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "**Array 1.** Дано целое число $n$ (> 0). Сформировать и вывести целочисленный массив размера $n$, содержащий $n$ первых положительных нечетных чисел: 1, 3, 5, … .\n",
    "\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 22,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[1, 3, 5, 7, 9, 11, 13, 15, 17, 19, 21, 23, 25, 27, 29]\n"
     ]
    }
   ],
   "source": [
    "# Array1\n",
    "n = 15\n",
    "a = []\n",
    "for i in range(n):\n",
    "    a.append(2*i+1)        \n",
    "print(a)    "
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "**Array4.** Дано целое число $n$ (> 1), а также первый член $a$ и знаменатель $d$ геометрической прогрессии. Сформировать и вывести массив размера $n$, содержащий $n$ первых членов данной прогрессии: \n",
    "$$\n",
    "a,    a\\cdot d,    a\\cdot d^2,    a \\cdot d^3,    … .\n",
    "$$\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 23,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024, 2048, 4096, 8192, 16384]\n"
     ]
    }
   ],
   "source": [
    "# Array4\n",
    "n = 15\n",
    "a = 1\n",
    "d = 2\n",
    "b = []\n",
    "for i in range(n):\n",
    "    b.append(a*d**i)    \n",
    "print(b)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "**3. Генерация списков (List Comprehensions)**"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 24,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[1, 3, 5, 7, 9, 11, 13, 15, 17, 19, 21, 23, 25, 27, 29]\n",
      "[1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024, 2048, 4096, 8192, 16384]\n"
     ]
    }
   ],
   "source": [
    "# На примере решения задач Array1 и  Array4\n",
    "n = 15\n",
    "a = [2*i+1  for i in range(n)]\n",
    "print(a)\n",
    "\n",
    "a = 1\n",
    "d = 2\n",
    "b = [a*d**i for i in range(n)]\n",
    "print(b)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "**Генераторы с условием**\n",
    "\n",
    "Создать список квадратов четных чисел от 1 до 20, не делящихся на три"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 25,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[4, 16, 64, 100, 196, 256, 400]\n"
     ]
    }
   ],
   "source": [
    "# В генератор списка можно добавлять условие:\n",
    "a = [i**2 for i in range(1,21) if i%2==0 and i%3!=0]\n",
    "print(a)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "**Генератор списка списков**\n",
    "\n",
    "Создать следующий список:  \n",
    "```python\n",
    "[[1, 2, 3, 4, 5],\n",
    " [10, 20, 30, 40, 50],\n",
    " [100, 200, 300, 400, 500]]\n",
    "```"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 26,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[[1, 2, 3, 4, 5], [10, 20, 30, 40, 50], [100, 200, 300, 400, 500]]\n"
     ]
    }
   ],
   "source": [
    "# Заготовка для решения\n",
    "\n",
    "a = [[i*10**j for i in range(1, 6)] for j in range(3)]\n",
    "print(a)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "**Генератор с вложенными циклами**\n",
    "\n",
    "Создать следующий список:  \n",
    "```python\n",
    "[1, 2, 3, 4, 5, 11, 12, 13, 14, 15, 21, 22, 23, 24, 25]\n",
    "```"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 27,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[1, 2, 3, 4, 5, 11, 12, 13, 14, 15, 21, 22, 23, 24, 25]\n"
     ]
    }
   ],
   "source": [
    "# Заготовка для решения\n",
    "\n",
    "a = [10*j + i for j in range (3) for i in range(1, 6)]\n",
    "print(a)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "**Отличие списка от генератора:**"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 28,
   "metadata": {},
   "outputs": [],
   "source": [
    "a = [i**2 for i in range(10)]\n",
    "g = (i**2 for i in range(10))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 30,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[0, 1, 4, 9, 16, 25, 36, 49, 64, 81]\n"
     ]
    }
   ],
   "source": [
    "print(a)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 31,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "<generator object <genexpr> at 0x000001FC62FFF850> <class 'generator'>\n"
     ]
    }
   ],
   "source": [
    "print(g, type(g))\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 42,
   "metadata": {},
   "outputs": [
    {
     "ename": "StopIteration",
     "evalue": "",
     "output_type": "error",
     "traceback": [
      "\u001b[1;31m---------------------------------------------------------------------------\u001b[0m",
      "\u001b[1;31mStopIteration\u001b[0m                             Traceback (most recent call last)",
      "Cell \u001b[1;32mIn[42], line 1\u001b[0m\n\u001b[1;32m----> 1\u001b[0m \u001b[43mg\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[38;5;21;43m__next__\u001b[39;49m\u001b[43m(\u001b[49m\u001b[43m)\u001b[49m\n",
      "\u001b[1;31mStopIteration\u001b[0m: "
     ]
    }
   ],
   "source": [
    "g.__next__()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 43,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "['__abs__',\n",
       " '__add__',\n",
       " '__and__',\n",
       " '__bool__',\n",
       " '__ceil__',\n",
       " '__class__',\n",
       " '__delattr__',\n",
       " '__dir__',\n",
       " '__divmod__',\n",
       " '__doc__',\n",
       " '__eq__',\n",
       " '__float__',\n",
       " '__floor__',\n",
       " '__floordiv__',\n",
       " '__format__',\n",
       " '__ge__',\n",
       " '__getattribute__',\n",
       " '__getnewargs__',\n",
       " '__getstate__',\n",
       " '__gt__',\n",
       " '__hash__',\n",
       " '__index__',\n",
       " '__init__',\n",
       " '__init_subclass__',\n",
       " '__int__',\n",
       " '__invert__',\n",
       " '__le__',\n",
       " '__lshift__',\n",
       " '__lt__',\n",
       " '__mod__',\n",
       " '__mul__',\n",
       " '__ne__',\n",
       " '__neg__',\n",
       " '__new__',\n",
       " '__or__',\n",
       " '__pos__',\n",
       " '__pow__',\n",
       " '__radd__',\n",
       " '__rand__',\n",
       " '__rdivmod__',\n",
       " '__reduce__',\n",
       " '__reduce_ex__',\n",
       " '__repr__',\n",
       " '__rfloordiv__',\n",
       " '__rlshift__',\n",
       " '__rmod__',\n",
       " '__rmul__',\n",
       " '__ror__',\n",
       " '__round__',\n",
       " '__rpow__',\n",
       " '__rrshift__',\n",
       " '__rshift__',\n",
       " '__rsub__',\n",
       " '__rtruediv__',\n",
       " '__rxor__',\n",
       " '__setattr__',\n",
       " '__sizeof__',\n",
       " '__str__',\n",
       " '__sub__',\n",
       " '__subclasshook__',\n",
       " '__truediv__',\n",
       " '__trunc__',\n",
       " '__xor__',\n",
       " 'as_integer_ratio',\n",
       " 'bit_count',\n",
       " 'bit_length',\n",
       " 'conjugate',\n",
       " 'denominator',\n",
       " 'from_bytes',\n",
       " 'imag',\n",
       " 'is_integer',\n",
       " 'numerator',\n",
       " 'real',\n",
       " 'to_bytes']"
      ]
     },
     "execution_count": 43,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "dir(10)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "**5. Cоздание списка из строки**"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 44,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "['Шла', 'Саша', 'по', 'шоссе', 'и', 'сосала', 'сушку']\n"
     ]
    }
   ],
   "source": [
    "s = 'Шла Саша по шоссе и сосала сушку'\n",
    "a = s.split()\n",
    "print(a)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 45,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "['Шла', 'Саша', 'по', 'шоссе', 'и', 'сосала', 'сушку']\n"
     ]
    }
   ],
   "source": [
    "s = 'Шла     Саша  по   шоссе   и сосала  сушку   '\n",
    "a = s.split()\n",
    "print(a)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 46,
   "metadata": {
    "scrolled": true
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "['195', '208', '253', '2']\n"
     ]
    }
   ],
   "source": [
    "ip_address = '195.208.253.2'\n",
    "blocks = ip_address.split('.')\n",
    "print(blocks)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 47,
   "metadata": {
    "scrolled": true
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "['Шла', '', '', '', '', 'Саша', '', 'по', '', '', 'шоссе', '', '', 'и', 'сосала', '', 'сушку', '', '', '']\n"
     ]
    }
   ],
   "source": [
    "print(s.split(' '))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "**Так нельзя:**"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 48,
   "metadata": {},
   "outputs": [
    {
     "ename": "ValueError",
     "evalue": "empty separator",
     "output_type": "error",
     "traceback": [
      "\u001b[1;31m---------------------------------------------------------------------------\u001b[0m",
      "\u001b[1;31mValueError\u001b[0m                                Traceback (most recent call last)",
      "Cell \u001b[1;32mIn[48], line 2\u001b[0m\n\u001b[0;32m      1\u001b[0m s \u001b[38;5;241m=\u001b[39m \u001b[38;5;124m'\u001b[39m\u001b[38;5;124mhello\u001b[39m\u001b[38;5;124m'\u001b[39m\n\u001b[1;32m----> 2\u001b[0m \u001b[43ms\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43msplit\u001b[49m\u001b[43m(\u001b[49m\u001b[38;5;124;43m'\u001b[39;49m\u001b[38;5;124;43m'\u001b[39;49m\u001b[43m)\u001b[49m\n",
      "\u001b[1;31mValueError\u001b[0m: empty separator"
     ]
    }
   ],
   "source": [
    "s = 'hello'\n",
    "s.split('')"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "**Если очень нужно, то вот так:**"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 49,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "['h', 'e', 'l', 'l', 'o']"
      ]
     },
     "execution_count": 49,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "s = 'hello'\n",
    "list(s)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Ну и заодно - про метод `join`. Он в некотором смысле обратный к `split` &ndash; позволяет объединить список строк в одну строку используя \"строку-заполнитель\""
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 50,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "195*208*253*2\n",
      "Шла Саша по шоссе и сосала сушку\n"
     ]
    }
   ],
   "source": [
    "print('*'.join(blocks))\n",
    "print(' '.join(a))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 51,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Шла     Саша  по   шоссе   и сосала  сушку   \n",
      "Шла Саша по шоссе и сосала сушку\n"
     ]
    }
   ],
   "source": [
    "# Еще один вариант удаления \"лишних\" пробелов из строки\n",
    "s = 'Шла     Саша  по   шоссе   и сосала  сушку   '\n",
    "print(s)\n",
    "print(' '.join(s.split()))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "<font color=\"#0000FF\">\n",
    "\n",
    "\n",
    "### Копирование списка"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 52,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[10, 20, [30, 40]]\n"
     ]
    }
   ],
   "source": [
    "a = [10, 20, [30, 40]]\n",
    "\n",
    "# Вариант 1. \n",
    "b = a\n",
    "print(b)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 53,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "b = [100, 20, [30, 40]]\n",
      "a = [100, 20, [30, 40]]\n"
     ]
    }
   ],
   "source": [
    "# Тестирование результата копирования\n",
    "b[0] = 100\n",
    "print(f'b = {b}\\na = {a}')"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "<font color=\"#0000FF\">\n",
    "\n",
    "Почему так получилось? Потому что `b` и `a` это две переменные, которые указывают на одно и то же место в памяти, содержимое которого **можно менять**."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 54,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[10, 20, [30, 40]]\n"
     ]
    }
   ],
   "source": [
    "a = [10, 20, [30, 40]]\n",
    "\n",
    "# Вариант 2\n",
    "b = a.copy()\n",
    "print(b)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 55,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "b = [100, 20, [30, 40]]\n",
      "a = [10, 20, [30, 40]]\n"
     ]
    }
   ],
   "source": [
    "# Тестирование результата копирования\n",
    "b[0] = 100\n",
    "print(f'b = {b}\\na = {a}')"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "<font color=\"#0000FF\">\n",
    "    \n",
    "Вроде бы все хорошо. Но на самом деле при таком копировании операция `=` применяется ко всем элементам списков по очереди. Если этот элемент списка `a` неизменяемый, например, `int` или `str`, то в списке `b` возникнет новый объект, а вот если этот элемент сам представляет собой список, то в массив `b` попадет ссылка на элемент из списка `a`."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# Усложненная проверка\n",
    "b[2][0] = 100\n",
    "print(f'b = {b}\\na = {a}')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "print(id(a), id(b))\n",
    "print(id(a[2]), id(b[2]))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "<font color=\"#0000FF\">\n",
    "\n",
    "Варианты 3 и 4 ниже тоже часто используются для копирования. Их результат полностью аналогичен варианту 2"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "a = [10, 20, [30, 40]]\n",
    "\n",
    "# Вариант 3\n",
    "b = list(a)\n",
    "print(b)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# Тестирование результата копирования\n",
    "b[0] = 100\n",
    "print(f'b = {b}\\na = {a}')\n",
    "# Усложненная проверка\n",
    "b[2][0] = 100\n",
    "print(f'b = {b}\\na = {a}')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "a = [10, 20, [30, 40]]\n",
    "\n",
    "# Вариант 4\n",
    "b = a[:]\n",
    "print(b)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# Тестирование результата копирования\n",
    "b[0] = 100\n",
    "print(f'b = {b}\\na = {a}')\n",
    "# Усложненная проверка\n",
    "b[2][0] = 100\n",
    "print(f'b = {b}\\na = {a}')"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "<font color=\"#0000FF\">\n",
    "\n",
    "\n",
    "Способы копирования 2-4 называются *поверхностным копированием*. Альтернатива &ndash; глубокое копирование.  \n",
    "Нужно подключить библиотеку `copy`."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "import copy\n",
    "a = [10, 20, [30, 40]]\n",
    "\n",
    "# Вариант 5\n",
    "b = copy.deepcopy(a)\n",
    "print(b)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# Тестирование результата копирования\n",
    "b[0] = 100\n",
    "print(f'b = {b}\\na = {a}')\n",
    "# Усложненная проверка\n",
    "b[2][0] = 100\n",
    "print(f'b = {b}\\na = {a}')"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "<font color=\"#0000FF\">\n",
    "\n",
    "**Важно:** при \"умножении\" списка на число происходит поверхностное копирование!"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "a = [1,2,[0,1]]\n",
    "b = a*2\n",
    "print(id(b[2]), id(b[5]))\n",
    "print(b)\n",
    "b[2][1] = 5\n",
    "print(b)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Краткий справочник по методам списков"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "| Операция, функция или метод| Назначение  |\n",
    "|:---|:---|\n",
    "|`a.append(x)`|Добавление элемент `x` в конец списка `a`|\n",
    "|`a.extend(L)`|Добавление списка (точнее, итерируемой последовательности) `L` в конец списка `a`|\n",
    "|`a.insert(i, x)`|Вставка на `i`-е место в список `a` элемента `x`; список \"раздвигается\" |\n",
    "|`a.remove(x)`|Удаление первого элемента в списке `a`, имеющего значение `x`. Если такого элемента не существует, возникает ошибка `ValueError`|\n",
    "|`a.pop(i)`|Удаление элемента с индексом `i` или последнего элемента, если индекс не указан. Значением функции является значение этого элемента|\n",
    "|`a.index(x, start , end)`|Определение индекса первого (с начала списка или от позиции `start`) элемента со значением `x`. По умолчанию ищется элемент от начала и до конца списка|\n",
    "|`a.count(x)`|Вычисление количества элементов списка `a`, имеющих значение `x`|\n",
    "|`a.sort()`| Упорядочивание списка *на месте* (подробности будут обсуждены позже)|\n",
    "|`sorted(a)`| Создание упорядоченного списка|\n",
    "|`a.reverse()`|Разворачивание списка *на месте*|\n",
    "|`reversed(a)`|Создание развернутого списка |\n",
    "|`a.copy()`|Создание поверхностной копии списка|\n",
    "|`a.clear()`|Очистка содержимого списка|\n",
    "\n",
    "**Важно**: методы `sort` и `reverse` не возвращают значения, а изменяют существующий список!"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Задачи на перебор элементов списка"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "**Array7.** Дан массив размера $n$. Вывести его элементы в обратном порядке."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 56,
   "metadata": {
    "scrolled": true
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "7 6 5 4 3 2 1 \n",
      "7 6 5 4 3 2 1 \n",
      "[7, 6, 5, 4, 3, 2, 1]\n",
      "[7, 6, 5, 4, 3, 2, 1]\n"
     ]
    }
   ],
   "source": [
    "a = [1,2,3,4,5,6,7]\n",
    "# Важно: нас не просят изменить список!\n",
    "\n",
    "n = len(a)\n",
    "\n",
    "# Вариант 1 (разбираемся с индексами) \n",
    "for i in range(n):\n",
    "    print(a[n-1-i], end = ' ') # исправить\n",
    "print()    \n",
    "\n",
    "# Вариант 2 (поручаем работу range)\n",
    "for i in range(n-1,-1, -1): # исправить\n",
    "    print(a[i], end = ' ')\n",
    "print()    \n",
    "\n",
    "# Вариант 3 (используем срез)\n",
    "print(a[::-1])   # исправить\n",
    "\n",
    "# Вариант 4 (используем обращение списка)\n",
    "print(list(reversed(a)))\n",
    "\n",
    "# Варианты 3 и 4 условно неэффективны по памяти. \n",
    "# Проверить эффективность по скорости трудно,\n",
    "#  так как самая медленная операция - вывод на экран"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 59,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "<list_reverseiterator at 0x1fc62b6bb20>"
      ]
     },
     "execution_count": 59,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "reversed(a)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "**Array10.** Дан целочисленный массив размера $n$. Вывести вначале все содержащиеся в данном массиве четные числа в порядке возрастания их индексов, а затем — все нечетные числа в порядке убывания их индексов. "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "2 4 6 8 9 7 5 3 1 "
     ]
    }
   ],
   "source": [
    "a = [1,2,3,4,5,6,7,8,9]\n",
    "n = len(a)\n",
    "\n",
    "# Вариант 1 - два цикла for\n",
    "for i in range(n):\n",
    "    if a[i]%2==0:\n",
    "        print(a[i], end = ' ')\n",
    "for i in range(n-1,-1,-1):\n",
    "    if a[i]%2!=0:\n",
    "        print(a[i], end = ' ')\n",
    "        \n",
    "\n",
    "# Вариант 2 - создадим список, \n",
    "#             удовлетворяющий условию,\n",
    "#             за один проход"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Перед тем, как написать второй вариант, поговорим о методах объекта `list`"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[2, 4, 6, 8, 9, 7, 5, 3, 1]\n"
     ]
    }
   ],
   "source": [
    "# Array 10\n",
    "a = [1,2,3,4,5,6,7,8,9]\n",
    "# Вариант 2 - создадим список, \n",
    "#             удовлетворяющий условию,\n",
    "#             за один проход\n",
    "#             Точнее - пару списков \n",
    "b = []\n",
    "c = []\n",
    "for i in range(n):\n",
    "    if a[i]%2 == 0:\n",
    "        b.append(a[i])\n",
    "    else:\n",
    "        c.insert(0, a[i])\n",
    "print(b+c)        \n",
    "        "
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "**Array11.** Дан массив $a$ размера $n$ и целое число $k$ ($1 \\leq k \\leq n$). Вывести элементы массива с порядковыми номерами, кратными $k$: \n",
    "$$ a_k, \\  a_{2k}, \\ a_{3k}, \\ \\ldots$$ \n",
    "Условный оператор не использовать. "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {},
   "outputs": [],
   "source": [
    "# для этой задачи и для дальнейшего нам пригодится\n",
    "import random"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "a = [8, 85, 52, 72, 15, 34, 25, 79, 4, 63, 69]\n",
      "85 72 34 79 63 "
     ]
    }
   ],
   "source": [
    "# Дано\n",
    "n = 11\n",
    "a = [random.randint(1,100) for i in range(n)]\n",
    "print(f'a = {a}')\n",
    "\n",
    "# решение\n",
    "k = 2\n",
    "for i in range(k,n,k):\n",
    "    print(a[i-1], end=' ')"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "**Array19.** Дан целочисленный массив $a$ размера 10. Вывести порядковый номер последнего из тех его элементов $a_k$, которые удовлетворяют двойному неравенству $a_1 < a_k < a_{10}$. Если таких элементов нет, то вывести 0. "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "a = [-47, -3, 38, 22, -5, 37, 1, -17, -33, 29]\n",
      "9\n"
     ]
    }
   ],
   "source": [
    "# Дано\n",
    "n = 10\n",
    "a = [random.randint(-50,50) for i in range(n)]\n",
    "print(f'a = {a}')\n",
    "\n",
    "# Решение\n",
    "nomer = -1\n",
    "for i in range(n-2,0,-1):\n",
    "    if a[0]<a[i]<a[9]:\n",
    "        nomer = i\n",
    "        break\n",
    "print(nomer+1)  "
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "**Array20.** Дан массив размера $n$ и целые числа $k$ и $m$ ($1 \\leq k \\leq m \\leq n$). Найти сумму элементов массива с номерами от $k$ до $m$ включительно. "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 13,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "a = [-6, 8, -3, 4, 7, -5, 5, 1, -1, -7]\n",
      "16\n"
     ]
    }
   ],
   "source": [
    "# Дано\n",
    "n = 10\n",
    "a = [random.randint(-10,10) for i in range(n)]\n",
    "print(f'a = {a}')\n",
    "# Решение\n",
    "k = 2 \n",
    "m = 5\n",
    "print(sum(a[k-1:m]))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "**String41.** Дана строка, состоящая из русских слов, разделенных пробелами (одним или несколькими). Найти количество слов в строке."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 14,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "7\n"
     ]
    }
   ],
   "source": [
    "s = 'Шла     Саша  по   шоссе   и сосала  сушку'\n",
    "\n",
    "print(len(s.split())) "
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "**String44.** Дана строка, состоящая из русских слов, набранных заглавными буквами и разделенных пробелами (одним или несколькими). Найти количество слов, которые содержат ровно три буквы «А»."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 15,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "ТАМАРА ПЛЫЛА НА КАТАМАРАНЕ И УВИДЕЛА МАКАРА НА КАРАКАТИЦЕ\n"
     ]
    }
   ],
   "source": [
    "s = 'ТАМАРА ПЛЫЛА НА КАТАМАРАНЕ \\\n",
    "И УВИДЕЛА МАКАРА НА КАРАКАТИЦЕ'\n",
    "print(s)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 16,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "3\n"
     ]
    }
   ],
   "source": [
    "# задачу можно решить в одну строчку!\n",
    "# исправить\n",
    "print(len([w for w in s.split() if w.count('А')==3]))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "**String50.** Дана строка, состоящая из русских слов, разделенных пробелами (одним или несколькими). Вывести строку, содержащую эти же слова, разделенные одним пробелом и расположенные в обратном порядке."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 17,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "вчера мышку поймал кот\n"
     ]
    }
   ],
   "source": [
    "s = 'кот   поймал    мышку   вчера'\n",
    "\n",
    "# при желании можно записать решение в одну строку\n",
    "# исправить\n",
    "print(' '.join(reversed(s.split())))\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "**Array63.** Даны два массива `a` и `b` размера 5, элементы которых упорядочены по возрастанию. Объединить эти массивы так, чтобы результирующий массив `c` (размера 10) остался упорядоченным по возрастанию."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 18,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "a = [7, 24, 33, 46, 50]\n",
      "b = [-36, -27, 20, 29, 48]\n"
     ]
    }
   ],
   "source": [
    "n = 5\n",
    "a = [random.randint(-50,50) for i in range(n)]\n",
    "a.sort()\n",
    "b = [random.randint(-50,50) for i in range(n)]\n",
    "b.sort()\n",
    "print(f'a = {a}\\nb = {b}')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 19,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[-36, -27, 7, 20, 24, 29, 33, 46, 48, 50]\n"
     ]
    }
   ],
   "source": [
    "# коротко, но (при больших n) неэффективно\n",
    "c = a+b\n",
    "c.sort()\n",
    "print(c)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 20,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[-36, -27, 7, 20, 24, 29, 33, 46, 48, 50]\n"
     ]
    }
   ],
   "source": [
    "# эффективный (при больших n) вариант\n",
    "i, j = 0,0\n",
    "c = []\n",
    "while i<n and j<n:\n",
    "    if a[i]<b[j]:\n",
    "        c.append(a[i])\n",
    "        i += 1\n",
    "    else:\n",
    "        c.append(b[j])\n",
    "        j += 1\n",
    "c += a[i:] + b[j:]   # один из этих двух срезов пуст!     \n",
    "print(c)\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "**Array92.** Дан целочисленный массив размера `n`. Удалить из массива все нечетные числа и вывести размер полученного массива и его содержимое. Нужно реализовать **три** варианта решения."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 28,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[-32, -6, 49, -28, -41, 49, -6, 43, -24, 26, -48, -31, 29, -24, 16]\n"
     ]
    }
   ],
   "source": [
    "n = 15\n",
    "a = [random.randint(-50,50) for i in range(n)]\n",
    "print(a)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 22,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "8, [46, -8, -12, 34, 42, -12, -18, -4]\n"
     ]
    }
   ],
   "source": [
    "# Вариант 1 - перебираем (и если надо удаляем)\n",
    "# элементы от начала до конца.\n",
    "# Подумайте, почему не годится цикл \"for\"?\n",
    "i = 0\n",
    "while i<len(a):\n",
    "    if a[i]%2 != 0:\n",
    "        a.remove(a[i])\n",
    "    else:\n",
    "        i += 1\n",
    "print(f'{len(a)}, {a}')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 27,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "-19\n",
      "-23\n",
      "-49\n",
      "11\n",
      "35\n",
      "10, [4, 40, -2, 16, 16, 50, 12, -42, 18, -38]\n"
     ]
    }
   ],
   "source": [
    "# Вариант 2 - перебираем элементы от конца к началу\n",
    "n = len(a)\n",
    "for i in range(n-1, -1, -1):\n",
    "    if a[i]%2 != 0:\n",
    "        print(a.pop(i))\n",
    "print(f'{len(a)}, {a}')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 29,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "9, [-32, -6, -28, -6, -24, 26, -48, -24, 16]\n"
     ]
    }
   ],
   "source": [
    "# Вариант 3 - создаем новый список\n",
    "a = [x for x in a if x%2 ==0]\n",
    "print(f'{len(a)}, {a}')"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Анонимные функции"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Начнем с решения пары задач сортировки"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "**Задача 1.** Дан список вещественных чисел.\n",
    "1. Нужно упорядочить список по возрастанию\n",
    "2. Нужно упорядочить список по возрастанию модулей его элементов"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 30,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[-4.13, -4.38, -5.34, 6.09, 7.05, 1.74, 6.76, 4.37, 8.55, -5.44, -3.17, 1.78, -7.4, 0.52, 1.42]\n"
     ]
    }
   ],
   "source": [
    "# создание заданного списка (\"Дан список...\")\n",
    "import random\n",
    "n = 15\n",
    "a = [(random.random()-0.5)*20 for i in range(n)]\n",
    "for i in range(n):\n",
    "    a[i] = round(a[i], 2)\n",
    "print(a)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 31,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[-7.4, -5.44, -5.34, -4.38, -4.13, -3.17, 0.52, 1.42, 1.74, 1.78, 4.37, 6.09, 6.76, 7.05, 8.55]\n",
      "[0.52, 1.42, 1.74, 1.78, -3.17, -4.13, 4.37, -4.38, -5.34, -5.44, 6.09, 6.76, 7.05, -7.4, 8.55]\n"
     ]
    }
   ],
   "source": [
    "# 1\n",
    "print(sorted(a))\n",
    "\n",
    "#2\n",
    "print(sorted(a, key=abs))\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "**Задача 2.** Дан список слов. \n",
    "1. Нужно упорядочить список слов по алфавиту.\n",
    "2. Упорядочить по алфавиту, но начиная с конца (\"словарь рифм\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 33,
   "metadata": {},
   "outputs": [],
   "source": [
    "words = ['палка', 'светло', 'дорога', 'галка', \n",
    "         'смелый', 'речка', 'барабан', 'клон', \n",
    "         'таракан', 'чубук', 'свечка', 'тон', \n",
    "         'коридор', 'овечка', 'балка', \n",
    "         'кегельбан', 'белый', 'умелый', 'сеньор',\n",
    "         'утекло', 'пирога', 'ноутбук', 'стекло',\n",
    "         'печка', 'стон', 'стакан', 'скот', \n",
    "         'поклон', 'помидор', 'спелый', \n",
    "         'каблук', 'кот']"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 34,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "['балка', 'барабан', 'белый', 'галка', 'дорога', 'каблук', 'кегельбан', 'клон', 'коридор', 'кот', 'ноутбук', 'овечка', 'палка', 'печка', 'пирога', 'поклон', 'помидор', 'речка', 'светло', 'свечка', 'сеньор', 'скот', 'смелый', 'спелый', 'стакан', 'стекло', 'стон', 'таракан', 'тон', 'умелый', 'утекло', 'чубук']\n"
     ]
    }
   ],
   "source": [
    "# 1\n",
    "print (sorted(words))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 35,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "['пирога', 'дорога', 'балка', 'галка', 'палка', 'овечка', 'свечка', 'печка', 'речка', 'белый', 'смелый', 'умелый', 'спелый', 'ноутбук', 'чубук', 'каблук', 'барабан', 'кегельбан', 'таракан', 'стакан', 'клон', 'поклон', 'тон', 'стон', 'стекло', 'утекло', 'светло', 'помидор', 'коридор', 'сеньор', 'кот', 'скот']\n"
     ]
    }
   ],
   "source": [
    "# 2\n",
    "def inverse(s):\n",
    "    return s[::-1]\n",
    "\n",
    "print (sorted(words, key=inverse))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "А стоило ли для решения такой простой задачи заводить ***отдельную функцию***, которая возможно в программе больше нигде не пригодится? \n",
    "\n",
    "Альтернатива &ndash; анонимные функции."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 36,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "['пирога', 'дорога', 'балка', 'галка', 'палка', 'овечка', 'свечка', 'печка', 'речка', 'белый', 'смелый', 'умелый', 'спелый', 'ноутбук', 'чубук', 'каблук', 'барабан', 'кегельбан', 'таракан', 'стакан', 'клон', 'поклон', 'тон', 'стон', 'стекло', 'утекло', 'светло', 'помидор', 'коридор', 'сеньор', 'кот', 'скот']\n"
     ]
    }
   ],
   "source": [
    "# с использованием lambda\n",
    "words.sort(key = lambda s: s[::-1])\n",
    "print(words)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "**Лямбда-выражения** — это особый синтаксис в Python, необходимый для создания анонимных функций, или лямбда-функций.\n",
    "\n",
    "Лямбда-выражения в Python позволяют функции быть созданной и переданной (зачастую другой функции) в одной строчке кода. Такие функции могут иметь только один оператор и автоматически возвращают его результат.  \n",
    "\n",
    "Лямбда-функция используется только в одном месте программы и выполняет одну единственную задачу."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "**Еще один пример на сортировку**  \n",
    "Дан список группы - список строк вида `'Имя Фамилия'`.\n",
    "Требуется упорядочить список по фамилиям."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 38,
   "metadata": {},
   "outputs": [],
   "source": [
    "group = ['Кирилл Харитонов', \n",
    "         'Егор Семеренко', \n",
    "         'Артём Сторчевой', \n",
    "         'Валентин Новиков', \n",
    "         'Рудем Трафимов', \n",
    "         'Дмитрий Терских', \n",
    "         'Кирилл Васильев', \n",
    "         'Юлия Менделева', \n",
    "         'Николай Мисюра', \n",
    "         'Дмитрий Логинов', \n",
    "         'Юлия Зерцикель', \n",
    "         'Антон Дворцов', \n",
    "         'Рахматжан Худайбергенов', \n",
    "         'Елена Данелян']"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 40,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "['Кирилл Васильев',\n",
       " 'Елена Данелян',\n",
       " 'Антон Дворцов',\n",
       " 'Юлия Зерцикель',\n",
       " 'Дмитрий Логинов',\n",
       " 'Юлия Менделева',\n",
       " 'Николай Мисюра',\n",
       " 'Валентин Новиков',\n",
       " 'Егор Семеренко',\n",
       " 'Артём Сторчевой',\n",
       " 'Дмитрий Терских',\n",
       " 'Рудем Трафимов',\n",
       " 'Кирилл Харитонов',\n",
       " 'Рахматжан Худайбергенов']"
      ]
     },
     "execution_count": 40,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "  \n",
    "group.sort(key = lambda s : s.split()[1] )\n",
    "group"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "**Важно не злоупотреблять!**\n",
    "\n",
    "Рекомендуется к прочтению:\\\n",
    "[Хватит использовать lambda выражения в Python](https://python-scripts.com/no-lambda)\n",
    "\n",
    "<img src=\"no-lambda.jpg\" align=left width=400 />"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "---"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Очень часто лямбда-функции используются в комбинации с функциями `filter`, `map`, `reduce`."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Функция `map` \n",
    "\n",
    "Эта функция имеет два аргумента. Первый аргумент &ndash; функция. Второй аргумент &ndash; некоторая последовательность (точнее, итерируемый объект, например, список, кортеж или объект типа `range`) или несколько таких последовательностей. Функция `map` применяет первый аргумент (функцию) к каждому элементу последовательности и возвращает итератор с результатами. \n",
    "\n",
    "**Важно:** результатом применения функции `map` является не список или кортеж, а объект типа `map`. Для получения списка требуется конвертация."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Примеры использования"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "**Пример 1**.  Составить список кубов натуральных чисел от 1 до 10"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 41,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[1, 8, 27, 64, 125, 216, 343, 512, 729, 1000]\n"
     ]
    }
   ],
   "source": [
    "# Решение: \n",
    "print(list(map(lambda x:x**3, range(1,11))))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "**Пример 2.** Дан списк слов. Нужно создать список этих же слов, набранных заглавными буквами. "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 42,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "['ONE', 'TWO', 'THREE', 'DOG', 'CAT']\n"
     ]
    }
   ],
   "source": [
    "words = ['one', 'two', 'three', 'dog', 'cat']\n",
    "# Решение:\n",
    "print(list(map(str.upper, words)))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "**Пример 3.** Найти сумму цифр натурального числа. Без использования циклов. В одну строчку."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 43,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "15\n"
     ]
    }
   ],
   "source": [
    "n = 12345\n",
    "# Решение:\n",
    "print(sum(map(int, list(str(n)))))\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Предыдущие задачи можно было решать и с помощью генераторов списков (list comprehensions)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 44,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "['ONE', 'TWO', 'THREE', 'DOG', 'CAT']\n"
     ]
    }
   ],
   "source": [
    "words_upper = [w.upper() for w in words]\n",
    "print(words_upper)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "**Пример 4**. Реализовать условие задачи: \\\n",
    "\"Дан список целых чисел. Пользователь вводит числа в одной строке через пробел\""
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 45,
   "metadata": {},
   "outputs": [
    {
     "name": "stdin",
     "output_type": "stream",
     "text": [
      "введите список:  5 6 7 -1 2 34 567\n"
     ]
    }
   ],
   "source": [
    "a = list(map(int, input(\"введите список: \").split()))\n",
    "# возможное решение через генераторы написать самостоятельно"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 46,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "[5, 6, 7, -1, 2, 34, 567]"
      ]
     },
     "execution_count": 46,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "a"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# а вот тут map выглядит удобнее\n",
    "v, t = map(float, input(\"введите v и t: \").split())"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Функция `filter` \n",
    "\n",
    "Эта функция имеет такие же аргументы, как и `map`. Она применяет первый аргумент (функцию) ко всем элементам второго аргумента (последовательности) и возвращает итератор с теми объектами, для которых функция вернула `True`. \n",
    "\n",
    "**Важно:** результатом применения функции `filter` является не список или кортеж, а объект типа `filter`. Для получения списка и т.п. требуется конвертация."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "**Примеры использования**"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 47,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[12, 6, 12, 78, 6]\n",
      "[1, 3, 45, 33, 7]\n"
     ]
    }
   ],
   "source": [
    "# Дан список чисел\n",
    "numbers = [12, 1, 3, 6, 12, 45, 33, 78, 6, 7]\n",
    "\n",
    "# Нужно оставить (отфильтровать) только четные \n",
    "evens = list(filter(lambda x : x%2==0, numbers))\n",
    "print(evens)\n",
    "# Нужно оставить (отфильтровать) только нечетные \n",
    "odds = list(filter(lambda x : x%2!=0, numbers))\n",
    "print(odds)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 48,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "3\n"
     ]
    }
   ],
   "source": [
    "# Сколько слов в строке \n",
    "# содержат ровно три буквы «А» ?\n",
    "\n",
    "s = 'ТАМАРА ПЛЫЛА НА КАТАМАРАНЕ \\\n",
    "И УВИДЕЛА МАКАРА НА КАРАКАТИЦЕ'\n",
    "\n",
    "print(len(list(filter(lambda s: s.count('А')==3, s.split()))))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Функция `filter` в чем-то аналогична генератору списков с условием. \n",
    "\n",
    "Важное отличие `map` и `filter`: экономия памяти при возможном ухудшении быстродействия (последнее не проверено)."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Задачи с сайта pythontutor"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "**«Уникальные элементы».**  Дан список. Выведите те его элементы, которые встречаются в списке только один раз. Элементы нужно выводить в том порядке, в котором они встречаются в списке."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 51,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[6, 2, 4, 0, 8, 3, 8, 9, 6, 0, 10, 4, 0, 0, 0]\n"
     ]
    }
   ],
   "source": [
    "import random\n",
    "# дан список\n",
    "n = 15\n",
    "a = [random.randint(0,10) for i in range(n)]\n",
    "print(a)\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 52,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[2, 3, 9, 10]\n",
      "[2, 3, 9, 10]\n"
     ]
    }
   ],
   "source": [
    "# варианты решения\n",
    "b = list(filter(lambda x: a.count(x)==1, a))\n",
    "print(b)\n",
    "\n",
    "c = [x for x in a if a.count(x)==1]\n",
    "print(c)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "**Важно:** Существует более эффективное решение с помощью объекта `словарь` (`dictionary`). Обсудим позже"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "<font color=\"#0000FF\">\n",
    "\n",
    "\n",
    "**«Кегельбан»**.  $n$ кеглей выставили в один ряд, занумеровав их слева направо числами от 1 до $n$. Затем по этому ряду бросили $k$ шаров, при этом $i$-й шар сбил все кегли с номерами от $l_i$ до $r_i$ включительно. Определите, какие кегли остались стоять на месте.\n",
    "\n",
    "Программа получает на вход количество кеглей $n$ и количество бросков $k$. \n",
    "Далее идет $k$ пар чисел $l_i$, $r_i$, при этом $1 \\leq l_i \\leq r_i \\leq n.$  \n",
    "\n",
    "Программа должна вывести последовательность из $n$ символов, где $j$-й символ есть `'I'`, если $j$-я кегля осталась стоять, или `'.'`, если $j$-я кегля была сбита. \n",
    "\n",
    "|Тест 1|Входные данные|Результат работы|Тест 2|Входные данные|Результат работы|\n",
    "|:--:|:--:|:--:|:--:|:--:|:--:|\n",
    "| |`5 2` |        |  |`10 3`  |            |\n",
    "| |`1 2` |`..I.I` |  |`3 5`   |`II....III.`| \n",
    "| |`4 4` |        |  |`4 6`   |            |\n",
    "| |      |        |  |`10 10` |            |\n",
    "\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# решение задачи\n",
    "n, k = map(int, input('n, k:').split())\n",
    "a = ['I']*n\n",
    "for i in range(k):\n",
    "    left, right = map(int, input('l, r:').split())\n",
    "    a[left-1:right] = ['.']*(right-left+1)\n",
    "print(''.join(a))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Кортежи"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Основное отличие от списка: кортеж - это неизменяемый объект"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 53,
   "metadata": {},
   "outputs": [],
   "source": [
    "a = [1,2,3]\n",
    "t = (1,2,3)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 54,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "2"
      ]
     },
     "execution_count": 54,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "a[1]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 55,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "2"
      ]
     },
     "execution_count": 55,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "t[1]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 56,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "tuple"
      ]
     },
     "execution_count": 56,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "type(t)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 57,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "(1, 2, 3, 1, 2, 3)"
      ]
     },
     "execution_count": 57,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "t + t"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 58,
   "metadata": {},
   "outputs": [
    {
     "ename": "TypeError",
     "evalue": "'tuple' object does not support item assignment",
     "output_type": "error",
     "traceback": [
      "\u001b[31m---------------------------------------------------------------------------\u001b[39m",
      "\u001b[31mTypeError\u001b[39m                                 Traceback (most recent call last)",
      "\u001b[36mCell\u001b[39m\u001b[36m \u001b[39m\u001b[32mIn[58]\u001b[39m\u001b[32m, line 1\u001b[39m\n\u001b[32m----> \u001b[39m\u001b[32m1\u001b[39m \u001b[43mt\u001b[49m\u001b[43m[\u001b[49m\u001b[32;43m1\u001b[39;49m\u001b[43m]\u001b[49m = \u001b[32m2\u001b[39m\n",
      "\u001b[31mTypeError\u001b[39m: 'tuple' object does not support item assignment"
     ]
    }
   ],
   "source": [
    "t[1] = 2"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 59,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[] <class 'list'>\n"
     ]
    }
   ],
   "source": [
    "# пустой список\n",
    "a = []\n",
    "print(a, type(a))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 60,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "() <class 'tuple'>\n"
     ]
    }
   ],
   "source": [
    "# пустой кортеж (в отличие от списка у такого кортежа смыла не очень много)\n",
    "b = ()\n",
    "print(b, type(b))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 61,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "5 <class 'int'>\n"
     ]
    }
   ],
   "source": [
    "# кортеж из одного элемента? нет!\n",
    "x = (5)\n",
    "print(x, type(x))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 62,
   "metadata": {},
   "outputs": [],
   "source": [
    "# если нужно, то вот так:\n",
    "x = (5,)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 63,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "tuple"
      ]
     },
     "execution_count": 63,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "type(x)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 64,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "1"
      ]
     },
     "execution_count": 64,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "len(x)"
   ]
  },
  {
   "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.14.0"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 4
}
