{
 "cells": [
  {
   "cell_type": "markdown",
   "id": "3c0c7af7",
   "metadata": {},
   "source": [
    "# Списки. Пример программы #"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "7cd71aeb",
   "metadata": {},
   "source": [
    "Итак, мы с вами разобрали, как работают списки. Давайте попробуем решить задачу на их применение.\n",
    "\n",
    "В качестве примера попробуем найти медиану случайного списка."
   ]
  },
  {
   "cell_type": "markdown",
   "id": "1384a6a8",
   "metadata": {},
   "source": [
    "Медиана - это значение в отсортированном списке, которое лежит ровно посередине, таким образом, половина значений - слева от него, и половина значений - справа."
   ]
  },
  {
   "cell_type": "markdown",
   "id": "50a2cb56",
   "metadata": {},
   "source": [
    "Чтобы получить медиану случайного списка, нам нужно случайный список создать."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "id": "8139fe20",
   "metadata": {},
   "outputs": [],
   "source": [
    "import random"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "84628ca0",
   "metadata": {},
   "source": [
    "Давайте воспользуемся для этого модулем `random` в стандартной библиотеке.\n",
    "\n",
    "Заведём наш список `numbers`. Давайте, у нас будет какое-то случайное количество элементов в этом списке, чтобы было интереснее.\n",
    "\n",
    "У нас будет `number_size`, который мы получим с помощью функции `randint`. Функция `randint` возвращает какое-то случайное значение в интервале, ей переданном.\n",
    "\n",
    "Таким образом, у нас `number_size` будет равняться от 10 до 15, какому-то числу."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "id": "29199966",
   "metadata": {},
   "outputs": [],
   "source": [
    "numbers = []\n",
    "numbers_size = random.randint(10, 15)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "c0c7e008",
   "metadata": {},
   "source": [
    "Теперь нам нужно создать наш случайный список. Давайте воспользуемся циклом `for` и встроенной функцией `range`. Будем интерироваться ровно `number_size` раз. \n",
    "\n",
    "Обратите внимание, я использую переменную нижнее подчёркивание, которая говорит о том, что нам не интересно, в принципе, что в неё записывается. Мы не будем её использовать. Нам важно, чтобы итерация происходила ровно `number_size` раз.\n",
    "\n",
    "И будем добавлять в наши `numbers` с помощью знакомого вам метода `append` какое-то новое число. А случайное число мы будем получать с помощью той же самой функции `randint`, и пусть это число будет от 10 до 20."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "id": "95d1de3b",
   "metadata": {},
   "outputs": [],
   "source": [
    "for _ in range(numbers_size):\n",
    "    numbers.append(random.randint(10, 20))"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "1cd2eb85",
   "metadata": {},
   "source": [
    "Давайте выведем наш список. Отлично."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "id": "26e888a2",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[15, 15, 16, 17, 10, 18, 13, 20, 20, 17]\n"
     ]
    }
   ],
   "source": [
    "print(numbers)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "328d7ffd",
   "metadata": {},
   "source": [
    "У нас получился список со случайными значениями, они не отсортированы, и, как видно, от 11 до 20, насколько я вижу.\n",
    "\n"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "701ba286",
   "metadata": {},
   "source": [
    "Теперь, чтобы найти медиану, нам нужно список отсортировать. Давайте используем для этого встроенный в список метод `sort` и отсортируем его."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "id": "c96230f4",
   "metadata": {},
   "outputs": [],
   "source": [
    "numbers.sort()"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "b7e71ccc",
   "metadata": {},
   "source": [
    "`sort` сортирует `in place`, поэтому наш список уже должен быть отсортирован, давайте выведем его."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "id": "5dc5b158",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[10, 13, 15, 15, 16, 17, 17, 18, 20, 20]\n"
     ]
    }
   ],
   "source": [
    "print(numbers)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "f3a7b55e",
   "metadata": {},
   "source": [
    "Отлично, 10 в начале, 20 в конце, значит, список отсортирован.\n",
    "\n",
    "Теперь нам нужно взять какое-то среднее значение. Как вы могли догадаться, случая может быть два. Если у нас количество элементов в списке нечётное, то всё просто. Мы просто берём средний элемент. Если количество элементов чётное, то по определению медианы нам нужно взять среднее арифметическое от двух средних элементов.\n",
    "\n",
    "Давайте заведем переменную `half_size`, в которую положим значение, равное половине длины списка. Для этого используем встроенную функцию `len` и поделим нашу длину пополам. И заведём переменную медиана, которая будет для начала равняться `None`."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "id": "49d11c5e",
   "metadata": {},
   "outputs": [],
   "source": [
    "half_size = len(numbers) // 2\n",
    "median = None"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "2b920f46",
   "metadata": {},
   "source": [
    "Итак, в простейшем случае у нас нечётное количество элементов. Если у нас наш `number_size` нечётный, то есть при делении на два даёт остаток один, то мы просто берём в качестве медианы `numbers[half_size]`.\n",
    " \n",
    "Однако интересное происходит, когда у нас чётное количество элементов в нашем списке. В таком случае нам нужно взять среднее из двух чисел, которые лежат посередине. Воспользуемся знакомой вам функцией `sum` встроенной и срезом. Нам нужен срез от `half_size -1` до `half_size +1`.\n",
    "\n",
    "Обратите внимание, элементы нумеруются с нуля, поэтому именно так нам нужно поступать. И мы берём среднее арифметическое, поэтому делим на два."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "id": "460fd334",
   "metadata": {},
   "outputs": [],
   "source": [
    "if numbers_size % 2 == 1:\n",
    "    median = numbers[half_size]\n",
    "else:\n",
    "    median = sum(\n",
    "        numbers[half_size - 1:half_size + 1]\n",
    "    ) / 2"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "18bd5ff2",
   "metadata": {},
   "source": [
    "Давайте попробуем вывести нашу медиану."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 12,
   "id": "8fd0d3ae",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "16.5\n"
     ]
    }
   ],
   "source": [
    "print(median)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "33912a15",
   "metadata": {},
   "source": [
    "У нас получилось значение, и, на самом деле, это действительно медиана нашего списка.\n",
    "\n",
    "Чтобы это проверить, можно воспользоваться встроенным модулем `statistics`, который позволяет нам сделать то, что мы делали только что какое-то заметное количество времени, намного быстрее.\n",
    "\n",
    "Давайте импортируем модуль `statistics`, и у `statistics` есть метод `median`, который позволит нам найти медиану очень легко. Отлично."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 14,
   "id": "71dd213f",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "16.5"
      ]
     },
     "execution_count": 14,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "import statistics\n",
    "\n",
    "statistics.median(numbers)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "13664bbb",
   "metadata": {},
   "source": [
    "Медиана действительно равна 16.5. Мы с вами не только разобрали списки, но и посмотрели задачу на их применение."
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "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.8.8"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}
