{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Nieuporządkowane typy danych i funkcje"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Nieuporządkowane typy danych (zbiory i słowniki)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "#### Funkcje zip i enumerate"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[(1, 5), (2, 6), (3, 7), (4, 8)]\n"
     ]
    }
   ],
   "source": [
    "lista1 = [1, 2, 3, 4]\n",
    "lista2 = [5, 6, 7, 8]\n",
    "\n",
    "print(list(zip(lista1,lista2)))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[(1, 5), (2, 6), (3, 7)]\n"
     ]
    }
   ],
   "source": [
    "lista1 = [1, 2, 3]\n",
    "lista2 = [5, 6, 7, 8]\n",
    "\n",
    "print(list(zip(lista1,lista2)))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[(1, 2, 3, 4), (5, 6, 7, 8)]\n"
     ]
    }
   ],
   "source": [
    "lista1 = [1, 2, 3, 4]\n",
    "lista2 = [5, 6, 7, 8]\n",
    "\n",
    "print(list(zip(*zip(lista1, lista2))))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 14,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "['H', 'e', 'l', 'l', 'o', ' ', 'W', 'o', 'r', 'l', 'd']\n",
      "[(0, 'H'), (1, 'e'), (2, 'l'), (3, 'l'), (4, 'o'), (5, ' '), (6, 'W'), (7, 'o'), (8, 'r'), (9, 'l'), (10, 'd')]\n",
      "[(5, 'H'), (6, 'e'), (7, 'l'), (8, 'l'), (9, 'o'), (10, ' '), (11, 'W'), (12, 'o'), (13, 'r'), (14, 'l'), (15, 'd')]\n"
     ]
    }
   ],
   "source": [
    "znaki = list(\"Hello World\")\n",
    "\n",
    "print(znaki)\n",
    "print(list(enumerate(znaki)))\n",
    "print(list(enumerate(znaki,5)))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 15,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "True\n"
     ]
    }
   ],
   "source": [
    "print(list(enumerate(znaki)) == list(zip(range(len(znaki)),znaki)))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "#### Słowniki   \n",
    "Zbiór par klucz-wartość"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 17,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "['studen1', 'student2', 'student3']\n",
      "[('studen1', 5), ('student2', 3), ('student3', 2)]\n",
      "['studen1', 'student2', 'student3']\n",
      "[5, 3, 2]\n"
     ]
    }
   ],
   "source": [
    "oceny = {'studen1': 5, 'student2': 3, 'student3': 2}\n",
    "\n",
    "print(list(oceny))\n",
    "print(list(oceny.items()))\n",
    "print(list(oceny.keys()))\n",
    "print(list(oceny.values()))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 19,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[('studen1', 5), ('student2', 4.5), ('student3', 2)]\n",
      "True\n"
     ]
    }
   ],
   "source": [
    "oceny['student2'] = 4.5\n",
    "\n",
    "print(list(oceny.items()))\n",
    "print(\"student3\" in oceny)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 22,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[(0, True), (1, False), (2, True), (3, False), (4, True), (5, False), (6, True), (7, False), (8, True), (9, False), (10, True), (11, False), (12, True), (13, False), (14, True), (15, False), (16, True), (17, False), (18, True), (19, False)]\n"
     ]
    }
   ],
   "source": [
    "parzyste = {n: n%2 == 0 for n in range(20)}\n",
    "\n",
    "print(list(parzyste.items()))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 25,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "dict_items([('student1', 2), ('student2', 3.5), ('student3', 5)])\n",
      "3.5\n"
     ]
    }
   ],
   "source": [
    "studenci = [\"student1\", \"student2\", \"student3\"]\n",
    "oceny = [2, 3.5, 5]\n",
    "\n",
    "słownik_ocen = dict(zip(studenci, oceny))\n",
    "\n",
    "print(słownik_ocen.items())\n",
    "print(słownik_ocen['student2'])"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "{'a': 97, 'b': 98, 'c': 99, 'd': 100, 'e': 101, 'f': 102, 'g': 103, 'h': 104, 'i': 105, 'j': 106, 'k': 107, 'l': 108, 'm': 109, 'n': 110, 'o': 111, 'p': 112, 'q': 113, 'r': 114, 's': 115, 't': 116, 'u': 117, 'v': 118, 'w': 119, 'x': 120, 'y': 121, 'z': 122}\n",
      "False\n"
     ]
    }
   ],
   "source": [
    "# usuwanie elementu\n",
    "repr_liczbowa = list(range(97,123))\n",
    "alfabet = [chr(v) for v in repr_liczbowa]\n",
    "słownik = dict(zip(alfabet, repr_liczbowa))\n",
    "\n",
    "print(słownik)\n",
    "\n",
    "del słownik['b']\n",
    "print('b' in słownik.keys())"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "#### Zbiory"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "{1, 2, 4, 11, 51, 19}\n",
      "{2}\n",
      "{1, 2, 4, 5, 71, 11, 12, 51, 19, 21}\n",
      "{1, 4, 5, 71, 11, 12, 19, 21, 51}\n",
      "{1, 4, 11, 19, 51}\n"
     ]
    }
   ],
   "source": [
    "zbior_liczb1 = {1, 2, 4, 11, 51, 19, 2}\n",
    "zbior_liczb2 = {2, 5, 12, 71, 21}\n",
    "\n",
    "print(zbior_liczb1) \n",
    "\n",
    "# opearcje na zbiorach\n",
    "print(zbior_liczb1 & zbior_liczb2)\n",
    "print(zbior_liczb1 | zbior_liczb2)\n",
    "print(zbior_liczb1 ^ zbior_liczb2)\n",
    "print(zbior_liczb1 - zbior_liczb2)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 33,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "{'e', 'l', 'h', 'o'} {'d', 'o', 'l', 'w', 'r'}\n",
      "{'l', 'o'}\n"
     ]
    }
   ],
   "source": [
    "litery1 = set(\"Hello\".lower())\n",
    "litery2 = set(\"World\".lower())\n",
    "\n",
    "print(litery1,litery2)\n",
    "print(litery1 & litery2)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "{0, 1, 2, 3, 4, 5, 6, 7, 8, 9}\n",
      "{0, 1, 2, 3, 4, 5, 6, 7, 8}\n",
      "{0, 1, 2, 3, 4, 5, 6, 7}\n",
      "0\n",
      "{1, 2, 3, 4, 5, 6, 7}\n"
     ]
    }
   ],
   "source": [
    "# usuwanie ze zbioru\n",
    "\n",
    "zbior = set(range(10))\n",
    "print(zbior)\n",
    "\n",
    "zbior.remove(9)\n",
    "print(zbior)\n",
    "\n",
    "zbior.discard(8)\n",
    "print(zbior)\n",
    "\n",
    "print(zbior.pop())\n",
    "print(zbior)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Funkcje"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "**Docstringi** są bardzo ważne podczas pisania własnych funkcji! Dokładne informację jak pisać napisy dokumentujące działanie naszej funkcji można znaleźć w [PEP 257](https://www.python.org/dev/peps/pep-0257/) oraz w [artykule](https://www.datacamp.com/community/tutorials/docstrings-python) na DataCamp."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 25,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Witaj!\n"
     ]
    }
   ],
   "source": [
    "def powitanie():\n",
    "    \"\"\"Funkcja zwraca napis 'Witaj!' \n",
    "    \"\"\"\n",
    "    return \"Witaj!\"\n",
    "\n",
    "print(powitanie())"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Help on function powitanie in module __main__:\n",
      "\n",
      "powitanie()\n",
      "    Funkcja wyświetla napis 'Witaj!'\n",
      "\n"
     ]
    }
   ],
   "source": [
    "help(powitanie)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 34,
   "metadata": {},
   "outputs": [],
   "source": [
    "def suma_dwoch_liczb(x, y):\n",
    "    \"\"\"Funkcja oblicza sumę liczb x i y.\n",
    "    \"\"\"\n",
    "    return x + y"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 29,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "3\n"
     ]
    }
   ],
   "source": [
    "print(suma_dwoch_liczb(1, 2))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 30,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Help on function suma_dwoch_liczb in module __main__:\n",
      "\n",
      "suma_dwoch_liczb(x, y)\n",
      "    Funkcja oblicza sumę liczb x i y.\n",
      "\n"
     ]
    }
   ],
   "source": [
    "help(suma_dwoch_liczb)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 36,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Funkcja oblicza sumę liczb x i y.\n",
      "    \n"
     ]
    }
   ],
   "source": [
    "print(suma_dwoch_liczb.__doc__)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 37,
   "metadata": {},
   "outputs": [],
   "source": [
    "def czy_podzielna(x, y=2): # y ma wartość domyślną\n",
    "    \"\"\"Funkcja sprawdza czy liczba  dzieli liczbę x\n",
    "       bez reszty.\n",
    "           \n",
    "       Parametry:\n",
    "       x -- liczba, której podzielność badamy\n",
    "       y -- liczba, która może być dzielnikiem \n",
    "       liczby x\n",
    "    \"\"\"\n",
    "    return x % y == 0"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 20,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Help on function czy_podzielna in module __main__:\n",
      "\n",
      "czy_podzielna(x, y=2)\n",
      "    Funkcja sprawdza czy liczba  dzieli liczbę x\n",
      "    bez reszty.\n",
      "        \n",
      "    Parametry:\n",
      "    x -- liczba, której podzielność badamy\n",
      "    y -- liczba, która może być dzielnikiem \n",
      "    liczby x\n",
      "\n"
     ]
    }
   ],
   "source": [
    "help(czy_podzielna)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 22,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "True"
      ]
     },
     "execution_count": 22,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "czy_podzielna(21, 7)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 24,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "False"
      ]
     },
     "execution_count": 24,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "czy_podzielna(21) # 'False' ponieważ 21 nie jest podzielna przez 2"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 45,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "True\n"
     ]
    }
   ],
   "source": [
    "funkcja = czy_podzielna\n",
    "\n",
    "print(funkcja(4,2))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 47,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "3\n",
      "5\n"
     ]
    }
   ],
   "source": [
    "def zwieksz_liczbe(x):\n",
    "    \"\"\"Funkcja zwiększa liczbę x o jeden jeżeli x jest parzysta\"\"\"\n",
    "    def dodaj_jeden(x):\n",
    "        return x + 1\n",
    "    return dodaj_jeden(x) if x%2 == 0 else x\n",
    "\n",
    "print(zwieksz_liczbe(3))\n",
    "print(zwieksz_liczbe(4))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 48,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Help on function zwieksz_liczbe in module __main__:\n",
      "\n",
      "zwieksz_liczbe(x)\n",
      "    Funkcja zwiększa liczbę x o jeden jeżeli x jest parzysta\n",
      "\n"
     ]
    }
   ],
   "source": [
    "help(zwieksz_liczbe)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 67,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Średnia liczb wyliczona ręcznie: 2.8785714285714286\n",
      "Średnia liczb wyliczona za pomocą funkcji 'oblicz_srednia': 2.88\n"
     ]
    }
   ],
   "source": [
    "def dekorator_liczb(funkcja):\n",
    "    def opakowanie(arg1):\n",
    "        srednia = funkcja(arg1)\n",
    "        zaokraglenie = round(srednia, 2)\n",
    "        return zaokraglenie\n",
    "\n",
    "    return opakowanie\n",
    "\n",
    "\n",
    "\n",
    "@dekorator_liczb\n",
    "def oblicz_srednia(lista_liczb):\n",
    "    return sum(lista_liczb)/len(lista_liczb)\n",
    "\n",
    "lista1 = [1, 2, 4, 3, 7, 1, 2.15]\n",
    "srednia = sum(lista1)/len(lista1)\n",
    "\n",
    "print(\"Średnia liczb wyliczona ręcznie: {0}\".format(srednia))\n",
    "print(\"Średnia liczb wyliczona za pomocą funkcji 'oblicz_srednia': {0}\".format(oblicz_srednia(lista1)))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Nasz dekorator opakowuje funkcję *oblicz_srednia* tak żeby podczas wykonywania funkcji *oblicz_srednia* wartość zwrotna była w pewien sposób udekorowana (w tym przypadku zaokrąglamy do dwóch miejsc po przecinku). Niestety podczas opakowania funkcja *oblicz_srednia* przejmuje nawet nazwę od funkcji *opakowanie* co może być kłopotliwe w przypadku próby wykrycia błędu w kodzie.  Dlatego zaleca się używania funkcji *wraps* z pakietu functools aby pozbyć się tej 'niedogodności'."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 69,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "opakowanie\n"
     ]
    }
   ],
   "source": [
    "def dekorator_liczb(funkcja):\n",
    "    def opakowanie(arg1):\n",
    "        srednia = funkcja(arg1)\n",
    "        zaokraglenie = round(srednia, 2)\n",
    "        return zaokraglenie\n",
    "\n",
    "    return opakowanie\n",
    "\n",
    "\n",
    "\n",
    "@dekorator_liczb\n",
    "def oblicz_srednia(lista_liczb):\n",
    "    return sum(lista_liczb)/len(lista_liczb)\n",
    "\n",
    "print(oblicz_srednia.__name__)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 70,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "oblicz_srednia\n"
     ]
    }
   ],
   "source": [
    "import functools\n",
    "\n",
    "def dekorator_liczb(funkcja):\n",
    "    @functools.wraps(funkcja)\n",
    "    def opakowanie(arg1):\n",
    "        srednia = funkcja(arg1)\n",
    "        zaokraglenie = round(srednia, 2)\n",
    "        return zaokraglenie\n",
    "\n",
    "    return opakowanie\n",
    "\n",
    "\n",
    "\n",
    "@dekorator_liczb\n",
    "def oblicz_srednia(lista_liczb):\n",
    "    return sum(lista_liczb)/len(lista_liczb)\n",
    "\n",
    "print(oblicz_srednia.__name__)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "#### Funkcje anonimowe (lambda function)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 44,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "False\n"
     ]
    }
   ],
   "source": [
    "parzysta = lambda x: czy_podzielna(x, y=2)\n",
    "\n",
    "print(parzysta(5))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 31,
   "metadata": {},
   "outputs": [],
   "source": [
    "funkcja = lambda x,y: x**y + y**x "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 32,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "17"
      ]
     },
     "execution_count": 32,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "funkcja(2, 3)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "\\begin{equation}\n",
    "szereg\\_geometryczny = \\sum\\limits_{i=0}^{n}x^n,\\quad |x|<1.\n",
    "\\end{equation}"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 34,
   "metadata": {},
   "outputs": [],
   "source": [
    "szereg_geometryczny = lambda x, n: sum(x**i for i in range(n+1))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 35,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "2.0"
      ]
     },
     "execution_count": 35,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "szereg_geometryczny(1/2, 10**5)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Importowanie oraz "
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Importowanie pakietów \n",
    "W Pythonie mamy dostęp do dużej ilości funkcji wbudowanych. Podczas pracy nad większymi programami będzie potrzeba importowania funkcji ze standardowych bibliotek (które są instalowane razam z Pythonem) oraz bibliotek zewnętrznych stworzonych przez innych programistów. "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "0.0 1.0\n"
     ]
    }
   ],
   "source": [
    "from math import sin, cos # importujemy tylko funkcje sin i cos z pakietu math\n",
    "\n",
    "print(sin(0),cos(0))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "0.0 1.0\n"
     ]
    }
   ],
   "source": [
    "import math\n",
    "\n",
    "print(math.sin(0), math.cos(0))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 52,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[1.  1.1 1.2 1.3 1.4 1.5 1.6 1.7 1.8 1.9 2.  2.1 2.2 2.3 2.4 2.5 2.6 2.7\n",
      " 2.8 2.9 3.  3.1 3.2 3.3 3.4 3.5 3.6 3.7 3.8 3.9 4.  4.1 4.2 4.3 4.4 4.5\n",
      " 4.6 4.7 4.8 4.9 5.  5.1 5.2 5.3 5.4 5.5 5.6 5.7 5.8 5.9 6.  6.1 6.2 6.3\n",
      " 6.4 6.5 6.6 6.7 6.8 6.9 7.  7.1 7.2 7.3 7.4 7.5 7.6 7.7 7.8 7.9 8.  8.1\n",
      " 8.2 8.3 8.4 8.5 8.6 8.7 8.8 8.9 9.  9.1 9.2 9.3 9.4 9.5 9.6 9.7 9.8 9.9]\n"
     ]
    }
   ],
   "source": [
    "import numpy as np\n",
    "\n",
    "print(np.arange(1,10,0.1))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "**Nie zaleca** się używania poniższej składni do importowania przestrzeni nazw z danego pakietu.  \n",
    "\n",
    "\n",
    "from math import *  "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  }
 ],
 "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.7.3"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
