{ "cells": [ { "cell_type": "markdown", "metadata": { "id": "iWFWs9SjJR1o" }, "source": [ "### Комбинаторика в Питоне" ] }, { "cell_type": "code", "execution_count": 10, "metadata": { "colab": { "base_uri": "https://localhost:8080/" }, "id": "Nh4EhvMbJUIa", "outputId": "871cbe2f-db64-4ed6-a5bf-7678acdbdafa" }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "None [2 1 3 4 5]\n" ] } ], "source": [ "import numpy as np\n", "# создадим массив и передадим его в функцию np.random.shuffle()\n", "arr = np.array([1, 2, 3, 4, 5])\n", "\n", "# сама функция выдала None, исходный массив при этом изменился\n", "print(np.random.shuffle(arr), arr)" ] }, { "cell_type": "code", "execution_count": 11, "metadata": { "colab": { "base_uri": "https://localhost:8080/" }, "id": "Xrf3CqP2Fg1O", "outputId": "fe95126f-2591-496d-a00a-eea6f92b99d0" }, "outputs": [ { "data": { "text/plain": [ "(array([2, 4, 5, 1, 3]), array([1, 2, 3, 4, 5]))" ] }, "execution_count": 11, "metadata": {}, "output_type": "execute_result" } ], "source": [ "# еще раз создадим массив\n", "arr = np.array([1, 2, 3, 4, 5])\n", "\n", "# передав его в np.random.permutation(),\n", "# мы получим перемешанную копию и исходный массив без изменений\n", "np.random.permutation(arr), arr" ] }, { "cell_type": "markdown", "metadata": { "id": "CRc0_oP1eO3y" }, "source": [ "#### Модуль itertools" ] }, { "cell_type": "markdown", "metadata": { "id": "Ib9u0kxzA785" }, "source": [ "##### Перестановки" ] }, { "cell_type": "markdown", "metadata": { "id": "WdlV4ZrwdliN" }, "source": [ "###### Перестановки без замены" ] }, { "cell_type": "markdown", "metadata": { "id": "fOdk6SujdoLH" }, "source": [ "1. Перестановки без повторений" ] }, { "cell_type": "code", "execution_count": 12, "metadata": { "colab": { "base_uri": "https://localhost:8080/" }, "id": "xdlxohSLeRUW", "outputId": "9e9bfd0e-9a7a-4a41-a1e5-cb17668c5408" }, "outputs": [ { "data": { "text/plain": [ "6" ] }, "execution_count": 12, "metadata": {}, "output_type": "execute_result" } ], "source": [ "# импортируем модуль math\n", "import math\n", "\n", "# передадим функции factorial() число 3\n", "math.factorial(3)" ] }, { "cell_type": "code", "execution_count": 13, "metadata": { "colab": { "base_uri": "https://localhost:8080/" }, "id": "S5ceeFMfeNwT", "outputId": "679f6eb5-2ef6-4f6a-e748-ea187470de80" }, "outputs": [ { "data": { "text/plain": [ "[('A', 'B', 'C'),\n", " ('A', 'C', 'B'),\n", " ('B', 'A', 'C'),\n", " ('B', 'C', 'A'),\n", " ('C', 'A', 'B'),\n", " ('C', 'B', 'A')]" ] }, "execution_count": 13, "metadata": {}, "output_type": "execute_result" } ], "source": [ "# импортируем модуль itertools\n", "import itertools\n", "\n", "# создадим строку из букв A, B, C\n", "x = 'ABC'\n", "# помимо строки можно использовать и список\n", "# x = ['A', 'B', 'C']\n", "\n", "# и передадим ее в функцию permutations()\n", "# так как функция возвращает объект itertools.permutations,\n", "# для вывода результата используем функцию list()\n", "list(itertools.permutations(x))" ] }, { "cell_type": "code", "execution_count": 14, "metadata": { "colab": { "base_uri": "https://localhost:8080/" }, "id": "DufioTwtfH5v", "outputId": "93bfc07b-856b-4aa4-8d7f-0b82b20e58c4" }, "outputs": [ { "data": { "text/plain": [ "6" ] }, "execution_count": 14, "metadata": {}, "output_type": "execute_result" } ], "source": [ "# чтобы узнать количество перестановок, можно использовать функцию len()\n", "len(list(itertools.permutations(x)))" ] }, { "cell_type": "code", "execution_count": 15, "metadata": { "colab": { "base_uri": "https://localhost:8080/" }, "id": "B-J32YZ4fQCL", "outputId": "183f8a99-6ab5-4578-c584-ff5fa45332a7" }, "outputs": [ { "data": { "text/plain": [ "[('A', 'B', 'C'),\n", " ('A', 'B', 'D'),\n", " ('A', 'B', 'E'),\n", " ('A', 'B', 'F'),\n", " ('A', 'C', 'B')]" ] }, "execution_count": 15, "metadata": {}, "output_type": "execute_result" } ], "source": [ "# теперь элементов исходного множества шесть\n", "x = 'ABCDEF'\n", "\n", "# чтобы узнать, сколькими способами их можно разместить на трех местах,\n", "# передадим параметр r = 3 и выведем первые пять элементов\n", "list(itertools.permutations(x, r = 3))[:5]" ] }, { "cell_type": "code", "execution_count": 16, "metadata": { "colab": { "base_uri": "https://localhost:8080/" }, "id": "NAkXrmpKfzUC", "outputId": "c33775a0-0c6b-4cae-e7cb-1961fe254a5a" }, "outputs": [ { "data": { "text/plain": [ "120" ] }, "execution_count": 16, "metadata": {}, "output_type": "execute_result" } ], "source": [ "# посмотрим на общее количество таких перестановок\n", "len(list(itertools.permutations(x, r = 3)))" ] }, { "cell_type": "markdown", "metadata": { "id": "PqRx8pF0dtKm" }, "source": [ "2. Перестановки с повторениями" ] }, { "cell_type": "code", "execution_count": 17, "metadata": { "id": "3qQ5QpTFpIJc" }, "outputs": [], "source": [ "# импортируем необходимые библиотеки\n", "import itertools\n", "import numpy as np\n", "import math\n", "\n", "# объявим функцию permutations_w_repetition(), которая будет принимать два параметра\n", "# x - строка, список или массив Numpy\n", "# r - количество мест в перестановке, по умолчанию равно количеству элементов в x\n", "def permutations_w_repetition(x, r = len(x)):\n", "\n", " # если передается строка,\n", " if isinstance(x, str):\n", " # превращаем ее в список\n", " x = list(x)\n", "\n", " # в числителе рассчитаем количество перестановок без повторений\n", " numerator = len(list(itertools.permutations(x, r = r)))\n", "\n", " # для того чтобы рассчитать знаменатель найдем,\n", " # сколько раз повторяется каждый из элементов\n", " _, counts = np.unique(x, return_counts = True)\n", "\n", " # объявим переменную для знаменателя\n", " denominator = 1\n", "\n", " # и в цикле будем помещать туда произведение факториалов\n", " # повторяющихся элементов\n", " for c in counts:\n", "\n", " # для этого проверим повторяется ли элемент\n", " if c > 1:\n", "\n", " # и если да, умножим знаменатель на факториал повторяющегося элемента\n", " denominator *= math.factorial(c)\n", "\n", " # разделим числитель на знаменатель\n", " # деление дает тип float, поэтому используем функцию int(),\n", " # чтобы результат был целым числом\n", " return int(numerator/denominator)" ] }, { "cell_type": "code", "execution_count": 18, "metadata": { "colab": { "base_uri": "https://localhost:8080/" }, "id": "Fq0vyfdg--5m", "outputId": "478c5a0b-0768-473c-ff1f-fd48231e0bda" }, "outputs": [ { "data": { "text/plain": [ "120" ] }, "execution_count": 18, "metadata": {}, "output_type": "execute_result" } ], "source": [ "# создадим строку со словом \"молоко\"\n", "x = 'МОЛОКО'\n", "\n", "# вызовем функцию\n", "permutations_w_repetition(x)" ] }, { "cell_type": "markdown", "metadata": { "id": "GoAiKH8-pIo3" }, "source": [ "###### Перестановки с заменой" ] }, { "cell_type": "code", "execution_count": 19, "metadata": { "colab": { "base_uri": "https://localhost:8080/" }, "id": "-uevbl8WdvsA", "outputId": "b320a8a8-bfed-43b0-b8bf-8f041c6d256f" }, "outputs": [ { "data": { "text/plain": [ "[('Ваниль', 'Ваниль'),\n", " ('Ваниль', 'Клубника'),\n", " ('Клубника', 'Ваниль'),\n", " ('Клубника', 'Клубника')]" ] }, "execution_count": 19, "metadata": {}, "output_type": "execute_result" } ], "source": [ "# посмотрим, сколькими способами можно выбрать два сорта мороженого\n", "list(itertools.product(['Ваниль', 'Клубника'], repeat = 2))" ] }, { "cell_type": "code", "execution_count": 20, "metadata": { "colab": { "base_uri": "https://localhost:8080/" }, "id": "9uxp4aeItTED", "outputId": "29ce5a18-39fd-4bf3-b3d5-0eb977763122" }, "outputs": [ { "data": { "text/plain": [ "[('A', 'A'),\n", " ('A', 'B'),\n", " ('A', 'C'),\n", " ('A', 'D'),\n", " ('B', 'A'),\n", " ('B', 'B'),\n", " ('B', 'C'),\n", " ('B', 'D'),\n", " ('C', 'A'),\n", " ('C', 'B'),\n", " ('C', 'C'),\n", " ('C', 'D'),\n", " ('D', 'A'),\n", " ('D', 'B'),\n", " ('D', 'C'),\n", " ('D', 'D')]" ] }, "execution_count": 20, "metadata": {}, "output_type": "execute_result" } ], "source": [ "# посмотрим на способы переставить с заменой два элемента из четырех\n", "list(itertools.product('ABCD', repeat = 2))" ] }, { "cell_type": "code", "execution_count": 21, "metadata": { "colab": { "base_uri": "https://localhost:8080/" }, "id": "LLlYVJ6Cgwc9", "outputId": "fe8ce0c1-d717-49c2-bd59-6c8ae45335fc" }, "outputs": [ { "data": { "text/plain": [ "16" ] }, "execution_count": 21, "metadata": {}, "output_type": "execute_result" } ], "source": [ "# убедимся, что таких способов 16\n", "len(list(itertools.product('ABCD', repeat = 2)))" ] }, { "cell_type": "markdown", "metadata": { "id": "9TKsA791BEES" }, "source": [ "##### Сочетания" ] }, { "cell_type": "code", "execution_count": 22, "metadata": { "colab": { "base_uri": "https://localhost:8080/" }, "id": "tIbK4PNsyVwB", "outputId": "09dbb8bf-a98c-4101-d465-2b6a19e88015" }, "outputs": [ { "data": { "text/plain": [ "[('A', 'B'),\n", " ('A', 'C'),\n", " ('A', 'D'),\n", " ('A', 'E'),\n", " ('B', 'A'),\n", " ('B', 'C'),\n", " ('B', 'D'),\n", " ('B', 'E'),\n", " ('C', 'A'),\n", " ('C', 'B'),\n", " ('C', 'D'),\n", " ('C', 'E'),\n", " ('D', 'A'),\n", " ('D', 'B'),\n", " ('D', 'C'),\n", " ('D', 'E'),\n", " ('E', 'A'),\n", " ('E', 'B'),\n", " ('E', 'C'),\n", " ('E', 'D')]" ] }, "execution_count": 22, "metadata": {}, "output_type": "execute_result" } ], "source": [ "# возьмем пять элементов\n", "x = 'ABCDE'\n", "\n", "# и найдем способ переставить два элемента из этих пяти\n", "list(itertools.permutations(x, r = 2))" ] }, { "cell_type": "code", "execution_count": 23, "metadata": { "colab": { "base_uri": "https://localhost:8080/" }, "id": "9NJLHZVP9xve", "outputId": "1ec51fcc-93ee-4cc9-b130-47935e0a1d01" }, "outputs": [ { "data": { "text/plain": [ "10" ] }, "execution_count": 23, "metadata": {}, "output_type": "execute_result" } ], "source": [ "# уменьшим на количество перестановок каждого типа r!\n", "int(len(list(itertools.permutations(x, r = 2)))/math.factorial(2))" ] }, { "cell_type": "code", "execution_count": 24, "metadata": { "colab": { "base_uri": "https://localhost:8080/" }, "id": "imUV1aSA_JI4", "outputId": "44cc4c14-993e-492a-8a17-839cc41d0f0f" }, "outputs": [ { "data": { "text/plain": [ "[('A', 'B'),\n", " ('A', 'C'),\n", " ('A', 'D'),\n", " ('A', 'E'),\n", " ('B', 'C'),\n", " ('B', 'D'),\n", " ('B', 'E'),\n", " ('C', 'D'),\n", " ('C', 'E'),\n", " ('D', 'E')]" ] }, "execution_count": 24, "metadata": {}, "output_type": "execute_result" } ], "source": [ "# то же самое можно рассчитать с помощью функции combinations()\n", "list(itertools.combinations(x, 2))" ] }, { "cell_type": "code", "execution_count": 25, "metadata": { "colab": { "base_uri": "https://localhost:8080/" }, "id": "GNuEIKwl_Px1", "outputId": "23f3ec43-59a5-4914-f2ad-aae6291ac8ad" }, "outputs": [ { "data": { "text/plain": [ "10" ] }, "execution_count": 25, "metadata": {}, "output_type": "execute_result" } ], "source": [ "# посмотрим на количество сочетаний\n", "len(list(itertools.combinations(x, 2)))" ] }, { "cell_type": "markdown", "metadata": { "id": "CPpGYzYJMuiv" }, "source": [ "Сочетания с заменой" ] }, { "cell_type": "code", "execution_count": 26, "metadata": { "colab": { "base_uri": "https://localhost:8080/" }, "id": "75SIWA4TMgj1", "outputId": "f622aa9c-c089-4352-c2b1-f5f423947286" }, "outputs": [ { "data": { "text/plain": [ "[('A', 'A'), ('A', 'B'), ('B', 'B')]" ] }, "execution_count": 26, "metadata": {}, "output_type": "execute_result" } ], "source": [ "# сколькими способами с заменой можно выбрать два элемента из двух\n", "list(itertools.combinations_with_replacement('AB', 2))" ] }, { "cell_type": "code", "execution_count": 27, "metadata": { "colab": { "base_uri": "https://localhost:8080/" }, "id": "DgCya-oDUIyd", "outputId": "f78b7f06-b597-4006-d9cc-fa49fe45f809" }, "outputs": [ { "data": { "text/plain": [ "[('A', 'B')]" ] }, "execution_count": 27, "metadata": {}, "output_type": "execute_result" } ], "source": [ "# очевидно, что без замены есть только один такой способ\n", "list(itertools.combinations('AB', 2))" ] }, { "cell_type": "markdown", "metadata": { "id": "9xgg_wXLbjuu" }, "source": [ "Биномиальные коэффициенты" ] }, { "cell_type": "code", "execution_count": 28, "metadata": { "colab": { "base_uri": "https://localhost:8080/" }, "id": "6dDgzQTlB7ZF", "outputId": "768cf35c-a548-450e-935c-dc84a6533d70" }, "outputs": [ { "data": { "text/plain": [ "[('H', 'H', 'H'),\n", " ('H', 'H', 'T'),\n", " ('H', 'T', 'H'),\n", " ('H', 'T', 'T'),\n", " ('T', 'H', 'H'),\n", " ('T', 'H', 'T'),\n", " ('T', 'T', 'H'),\n", " ('T', 'T', 'T')]" ] }, "execution_count": 28, "metadata": {}, "output_type": "execute_result" } ], "source": [ "# дерево вероятностей можно построить с помощью декартовой степени\n", "list(itertools.product('HT', repeat = 3))" ] }, { "cell_type": "code", "execution_count": 29, "metadata": { "colab": { "base_uri": "https://localhost:8080/" }, "id": "NFqzBH7lblyY", "outputId": "e2d1b80c-a022-4878-8a5a-111019cdd561" }, "outputs": [ { "data": { "text/plain": [ "3" ] }, "execution_count": 29, "metadata": {}, "output_type": "execute_result" } ], "source": [ "# посмотрим, в скольких комбинациях выпадет два орла при трех бросках\n", "comb = len(list(itertools.combinations('ABC', 2)))\n", "comb" ] }, { "cell_type": "markdown", "metadata": { "id": "q5YrLz3_sffO" }, "source": [ "### Упражнения" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "**Задание 1**. Реализовать комбинаторные конструкции без использования библиотеки intertools. Проведите сравнительный анализ на быстродействие и объем используемой памяти. Сделайте выводы." ] }, { "cell_type": "code", "execution_count": 30, "metadata": {}, "outputs": [], "source": [ "def permutations(items: list[int]):\n", " if len(items) == 0:\n", " yield []\n", " else:\n", " for i in range(len(items)):\n", " for perm in permutations(items[:i] + items[i+1:]):\n", " yield [items[i]] + perm\n", "\n", "def combinations(items: list[int], k: int):\n", " if k == 0:\n", " yield []\n", " elif len(items) == k:\n", " yield items\n", " else:\n", " for comb in combinations(items[1:], k-1):\n", " yield [items[0]] + comb\n", " for comb in combinations(items[1:], k):\n", " yield comb\n", "\n", "def arrangements(items: list[int], k: int):\n", " if k == 0:\n", " yield []\n", " else:\n", " for i in range(len(items)):\n", " for arr in arrangements(items[:i] + items[i+1:], k-1):\n", " yield [items[i]] + arr" ] }, { "cell_type": "code", "execution_count": 31, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "my func\n", "\n", "===Permutations===\n", "Output: [[1, 2, 3, 4], [1, 2, 4, 3], [1, 3, 2, 4], [1, 3, 4, 2], [1, 4, 2, 3], [1, 4, 3, 2], [2, 1, 3, 4], [2, 1, 4, 3], [2, 3, 1, 4], [2, 3, 4, 1], [2, 4, 1, 3], [2, 4, 3, 1], [3, 1, 2, 4], [3, 1, 4, 2], [3, 2, 1, 4], [3, 2, 4, 1], [3, 4, 1, 2], [3, 4, 2, 1], [4, 1, 2, 3], [4, 1, 3, 2], [4, 2, 1, 3], [4, 2, 3, 1], [4, 3, 1, 2], [4, 3, 2, 1]]\n", "Time: 4.315376281738281e-05\n", "===Combinations===\n", "Output: [[1, 2], [1, 3], [1, 4], [2, 3], [2, 4], [3, 4]]\n", "Time: 1.0013580322265625e-05\n", "===Arrangements===\n", "Output: [[1, 2], [1, 3], [1, 4], [2, 1], [2, 3], [2, 4], [3, 1], [3, 2], [3, 4], [4, 1], [4, 2], [4, 3]]\n", "Time: 1.4066696166992188e-05\n", "\n", "itertools\n", "\n", "===Permutations===\n", "Output: [(1, 2, 3, 4), (1, 2, 4, 3), (1, 3, 2, 4), (1, 3, 4, 2), (1, 4, 2, 3), (1, 4, 3, 2), (2, 1, 3, 4), (2, 1, 4, 3), (2, 3, 1, 4), (2, 3, 4, 1), (2, 4, 1, 3), (2, 4, 3, 1), (3, 1, 2, 4), (3, 1, 4, 2), (3, 2, 1, 4), (3, 2, 4, 1), (3, 4, 1, 2), (3, 4, 2, 1), (4, 1, 2, 3), (4, 1, 3, 2), (4, 2, 1, 3), (4, 2, 3, 1), (4, 3, 1, 2), (4, 3, 2, 1)]\n", "Time: 2.1219253540039062e-05\n", "===Combinations===\n", "Output: [(1, 2), (1, 3), (1, 4), (2, 3), (2, 4), (3, 4)]\n", "Time: 5.0067901611328125e-06\n", "===Arrangements===\n", "Output: [(1, 2), (1, 3), (1, 4), (2, 1), (2, 3), (2, 4), (3, 1), (3, 2), (3, 4), (4, 1), (4, 2), (4, 3)]\n", "Time: 5.0067901611328125e-06\n" ] } ], "source": [ "import time\n", "\n", "\n", "def measure(func, *args):\n", " start_time = time.time()\n", " print(\"Output:\", list(func(*args)))\n", " end_time = time.time()\n", " print(\"Time:\", end_time - start_time)\n", "\n", "\n", "items = [1, 2, 3, 4]\n", "k = 2\n", "\n", "print(\"my func\\n\")\n", "\n", "print(\"===Permutations===\")\n", "measure(permutations, items)\n", "print(\"===Combinations===\")\n", "measure(combinations, items, k)\n", "print(\"===Arrangements===\")\n", "measure(arrangements, items, k)\n", "\n", "print(\"\\nitertools\\n\")\n", "print(\"===Permutations===\")\n", "measure(itertools.permutations, items)\n", "print(\"===Combinations===\")\n", "measure(itertools.combinations, items, k)\n", "print(\"===Arrangements===\")\n", "measure(itertools.permutations, items, k)\n" ] }, { "cell_type": "markdown", "metadata": { "id": "awwMLMoylUED" }, "source": [ "**Задание 2**. В новую школу не успели завезти парты в один из классов. Поэтому в этот класс принесли круглые столы из столовой. Столы в столовой разных размеров — на 4, 7 и 13 человек, всего их хватало на 59 человек. Когда часть столов отнесли в класс, в столовой осталось 33 места. Какие столы могли быть отнесены в класс?" ] }, { "cell_type": "code", "execution_count": 37, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Столы по 4 места: 0 | Столы по 7 мест: 0 | Столы по 13 мест: 2\n", "Столы по 4 места: 3 | Столы по 7 мест: 2 | Столы по 13 мест: 0\n" ] } ], "source": [ "def find_possible_tables():\n", " total_seats = 59\n", " remaining_seats = 33\n", " table_sizes = [4, 7, 13]\n", "\n", " for counts in itertools.product(range(total_seats // 4 + 1),\n", " range(total_seats // 7 + 1),\n", " range(total_seats // 13 + 1)):\n", " if sum(count * size for count, size in zip(counts, table_sizes)) == total_seats-remaining_seats:\n", " yield counts\n", "\n", "\n", "for tables in find_possible_tables():\n", " print(\"Столы по 4 места:\", tables[0], end=\" | \")\n", " print(\"Столы по 7 мест:\", tables[1], end=\" | \")\n", " print(\"Столы по 13 мест:\", tables[2])\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "**Задание 3**. Продавец имеет достаточное количество гирь для взвешивания следующих номиналов: 5гр, 10гр, 20гр, 50гр. каждый день к нему в магазин заходит житель соседнего дома и покупает ровно 500гр докторской колбасы. Продавец решил в течение месяца использовать различные наборы гирек для взвешивания. Сможет ли он выполнить задуманное?" ] }, { "cell_type": "code", "execution_count": 51, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Да\n" ] } ], "source": [ "def find_possible_weights():\n", " total = 500\n", " weights = [5, 10, 20, 50]\n", " \n", " for counts in itertools.product(range(total // 5 + 1),\n", " range(total // 10 + 1),\n", " range(total // 20 + 1),\n", " range(total // 50 + 1)):\n", " if sum(count * weight for count, weight in zip(counts, weights)) == total:\n", " yield counts\n", "\n", "print(\"Да\" if len(list(find_possible_weights())) >= 31 else \"Нет\")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "**Задание 4**. Сколько можно найти различных семизначных чисел, сумма цифр которых равна ровно 50?" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "26418\n" ] } ], "source": [ "def find_numbers() -> list[int]:\n", " possible_combinations = itertools.product(range(10), repeat=7)\n", " valid_numbers = []\n", "\n", " for combination in possible_combinations:\n", " if combination[0] != 0:\n", " if sum(combination) == 50:\n", " number = int(\"\".join(map(str, combination)))\n", " valid_numbers.append(number)\n", "\n", " return valid_numbers\n", "\n", "\n", "print(len(find_numbers()))\n" ] } ], "metadata": { "colab": { "provenance": [], "toc_visible": true }, "kernelspec": { "display_name": "Python 3 (ipykernel)", "language": "python", "name": "python3" }, "language_info": { "codemirror_mode": { "name": "ipython", "version": 3 }, "file_extension": ".py", "mimetype": "text/x-python", "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", "version": "3.11.0" } }, "nbformat": 4, "nbformat_minor": 1 }