From 18b7e17eb0f390b8fe123362e14ee8f256f121a8 Mon Sep 17 00:00:00 2001
From: Romain Vuillemot <romain.vuillemot@gmail.com>
Date: Tue, 10 Oct 2023 17:31:22 +0200
Subject: [PATCH] new version of class material

---
 01-data-structures-complexity.ipynb           | 2203 +++++++++++++++++
 03-lists-search-sort.ipynb                    |   58 +-
 04-05-06-programming-strategies.ipynb         |   44 +-
 07-stacks-queues.ipynb                        |   25 +-
 ...data-structures-complexity-exercises.ipynb |    6 +-
 exercises/02-recursion-exercises.ipynb        |    6 +-
 .../03-lists-search-sort-exercises.ipynb      |    6 +-
 ...-06-programming-strategies-exercises.ipynb |   74 +-
 exercises/07-stacks-queues-exercises.ipynb    |  444 ++++
 ...-06-programming-strategies-exercises.ipynb | 1106 +++++++++
 10 files changed, 3904 insertions(+), 68 deletions(-)
 create mode 100644 01-data-structures-complexity.ipynb
 create mode 100644 exercises/07-stacks-queues-exercises.ipynb
 create mode 100644 solutions/04-05-06-programming-strategies-exercises.ipynb

diff --git a/01-data-structures-complexity.ipynb b/01-data-structures-complexity.ipynb
new file mode 100644
index 0000000..e1b8d69
--- /dev/null
+++ b/01-data-structures-complexity.ipynb
@@ -0,0 +1,2203 @@
+{
+ "cells": [
+  {
+   "cell_type": "markdown",
+   "id": "b50844ff",
+   "metadata": {
+    "slideshow": {
+     "slide_type": "slide"
+    },
+    "tags": [
+     "definition"
+    ]
+   },
+   "source": [
+    "# UE5 Fundamentals of Algorithms\n",
+    "## Lecture 1: Introduction\n",
+    "### Ecole Centrale de Lyon, Bachelor of Science in Data Science for Responsible Business\n",
+    "#### Romain Vuillemot\n",
+    "<center><img  src=\"figures/Logo_ECL.png\" style=\"width:300px\"></center>"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "id": "2ada5ceb",
+   "metadata": {
+    "slideshow": {
+     "slide_type": "subslide"
+    }
+   },
+   "source": [
+    "## Outline\n",
+    "- Definition and examples of algorithms\n",
+    "- Algorithms properties\n",
+    "- Complexity analysis\n",
+    "- Data structures\n",
+    "- Empirical complexity analysis"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "id": "2f278159",
+   "metadata": {
+    "slideshow": {
+     "slide_type": "skip"
+    }
+   },
+   "source": [
+    "---"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "id": "f828e797",
+   "metadata": {
+    "slideshow": {
+     "slide_type": "subslide"
+    }
+   },
+   "source": [
+    "## What is an algorithm?\n",
+    "\n",
+    "### Definition\n",
+    "\n",
+    "> An algorithm is a **set of unambiguous instructions** designed to solve a problem.\n",
+    "\n",
+    "\n",
+    "### History\n",
+    "\n",
+    "The earliest algorithms, originating from the name **Mūsā al-Khwārizmī**, a Persian mathematician from the 9th century. For more information, visit https://mathematical-tours.github.io/algorithms/.\n",
+    "\n",
+    "Back to ancient civilizations, such as the Egyptians and Babylonians, developed algorithms for **basic arithmetic operations**, like addition and multiplication. Euclid's algorithm, developed around 300 BCE, is **one of the earliest known algorithms** and is used to find the greatest common divisor (GCD) of two numbers.\n"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "id": "a3b03927",
+   "metadata": {
+    "slideshow": {
+     "slide_type": "subslide"
+    }
+   },
+   "source": [
+    "### Question\n",
+    "\n",
+    "- Are you aware of any algorithm?"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "id": "0e1b605e",
+   "metadata": {
+    "slideshow": {
+     "slide_type": "fragment"
+    }
+   },
+   "source": [
+    "- Do you know how they work?\n",
+    "- Do you think they work perfectly? \n",
+    "- Can they be biased or make non-optimal decisions?"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "id": "598f0585",
+   "metadata": {
+    "slideshow": {
+     "slide_type": "subslide"
+    }
+   },
+   "source": [
+    "### Notes\n",
+    "\n",
+    "- The representation (or sometimes translation) into a programming language is not reciprocal: **not every program is an algorithm.**\n",
+    "\n",
+    "- For example, reactive programs (handling input/output) or those containing animations do not terminate because they are always waiting for input. They do not constitute algorithms in the strict sense.\n",
+    "\n",
+    "- Algorithms are language-agnostic; they describe the logic and steps needed to solve a problem, but not the specific coding details."
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "id": "13950423",
+   "metadata": {
+    "slideshow": {
+     "slide_type": "subslide"
+    }
+   },
+   "source": [
+    "### Example: Euclid's algorithm\n",
+    "\n",
+    "One of the earliest algorithm: Euclid's algorithm to compute the greatest common divisor of two integers a and b: "
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 19,
+   "id": "1ab6e76d",
+   "metadata": {
+    "slideshow": {
+     "slide_type": "fragment"
+    }
+   },
+   "outputs": [],
+   "source": [
+    "def gcd(a, b):\n",
+    "    while b != 0:\n",
+    "        t = b\n",
+    "        b = a % b\n",
+    "        a = t\n",
+    "    return a\n",
+    "\n",
+    "gcd(10, 20) # 10"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 44,
+   "id": "e594e658",
+   "metadata": {
+    "slideshow": {
+     "slide_type": "fragment"
+    }
+   },
+   "outputs": [],
+   "source": [
+    "assert gcd(12, 18) == 6  # GCD of 12 and 18 is 6\n",
+    "assert gcd(1071, 462) == 21  # GCD of 1071 and 462 is 21\n",
+    "assert gcd(0, 8) == 8  # GCD of 0 and 8 is 8\n",
+    "assert gcd(25, 0) == 25  # GCD of 25 and 0 is 25\n",
+    "assert gcd(-12, 18) == 6  # GCD of -12 and 18 is 6"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "id": "d06be14a",
+   "metadata": {
+    "slideshow": {
+     "slide_type": "subslide"
+    }
+   },
+   "source": [
+    "### How do you check an algorithm is correct?\n",
+    "\n",
+    "- **Mathematical Proof:** a formal and rigorous method of demonstrating that an algorithm is correct.\n",
+    "- **Code Review:** a collaborative process where one or more peers review the code implementation of an algorithm.\n",
+    "- **Test Cases:** sets of inputs and expected outputs used to validate that an algorithm produces correct results.\n",
+    "\n",
+    "For **test cases:**, the ```assert``` statement is used to check whether a given condition evaluates to ```True```, then the program continues to execute normally. If the condition is ```False```, an ```AssertionError``` exception is raised, and the program stops executing.\n"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "id": "b4756712",
+   "metadata": {
+    "slideshow": {
+     "slide_type": "subslide"
+    }
+   },
+   "source": [
+    "### How do you check an algorithm is correct? (cont.)\n"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 82,
+   "id": "c978e5c9",
+   "metadata": {},
+   "outputs": [
+    {
+     "name": "stdout",
+     "output_type": "stream",
+     "text": [
+      "All test cases passed!\n"
+     ]
+    }
+   ],
+   "source": [
+    "def add(a, b): # function to test\n",
+    "    return a + b\n",
+    "\n",
+    "assert add(2, 3) == 5, \"Test Case 1 Failed\" \n",
+    "assert add(-1, 1) == 0, \"Test Case 2 Failed\" \n",
+    "assert add(0, 0) == 0, \"Test Case 3 Failed\"  \n",
+    "assert add(10, -5) == 5, \"Test Case 4 Failed\"\n",
+    "\n",
+    "print(\"All test cases passed!\")"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "id": "b3440a3c",
+   "metadata": {
+    "slideshow": {
+     "slide_type": "subslide"
+    }
+   },
+   "source": [
+    "### Exercice: x power n\n",
+    "\n",
+    "An algorithm (and tests) that calculates $x^n$:"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 84,
+   "id": "0eec5ad4",
+   "metadata": {
+    "slideshow": {
+     "slide_type": "fragment"
+    }
+   },
+   "outputs": [],
+   "source": [
+    "def puissance(x, n):\n",
+    "    if n == 0:\n",
+    "        return 1\n",
+    "    elif n % 2 == 0:\n",
+    "        temp = puissance(x, n // 2)\n",
+    "        return temp * temp\n",
+    "    elif n < 0:\n",
+    "        temp = puissance(x, -(n + 1) // 2)\n",
+    "        return 1 / (temp * temp * x)\n",
+    "    else:\n",
+    "        temp = puissance(x, (n - 1) // 2)\n",
+    "        return temp * temp * x"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 85,
+   "id": "265c8dbf",
+   "metadata": {
+    "slideshow": {
+     "slide_type": "fragment"
+    }
+   },
+   "outputs": [],
+   "source": [
+    "assert puissance(2, 3) == 8\n",
+    "assert puissance(5, 0) == 1\n",
+    "assert puissance(3, -2) == 1/9\n",
+    "assert puissance(2, 10) == 1024\n",
+    "assert puissance(2, -3) == 1/8\n",
+    "assert puissance(2, 1) == 2"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "id": "42bd90e0",
+   "metadata": {
+    "slideshow": {
+     "slide_type": "subslide"
+    }
+   },
+   "source": [
+    "### Exercice: The sum of the first n integers\n",
+    "\n",
+    "An algorithm (and tests) that calculates $\\sum_{i=1}^{n} x_i$:"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 86,
+   "id": "c97cd26b",
+   "metadata": {
+    "slideshow": {
+     "slide_type": "fragment"
+    }
+   },
+   "outputs": [],
+   "source": [
+    "def sum_n(n):\n",
+    "    return n*(n+1)/2\n",
+    "\n",
+    "assert sum_n(1) == 1  # 1\n",
+    "assert sum_n(2) == 3  # 1 + 2\n",
+    "assert sum_n(3) == 6  # 1 + 2 + 3\n",
+    "assert sum_n(4) == 10 # 1 + 2 + 3 + 4\n",
+    "assert sum_n(5) == 15 # 1 + 2 + 3 + 4 + 5\n",
+    "assert sum_n(1000) == 500500 # .."
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "id": "f4b2a737",
+   "metadata": {
+    "slideshow": {
+     "slide_type": "subslide"
+    }
+   },
+   "source": [
+    "### Exercice: Leap year\n",
+    "\n",
+    "Write a function `is_leap_year` that takes a year as input and returns `True` if it's a leap year and `False`\n",
+    " otherwise. The function follows the rules for leap year determination:\n",
+    "\n",
+    "- A year that is divisible by 4 is a leap year.\n",
+    "- However, a year that is divisible by 100 is not a leap year, unless...\n",
+    "- The year is also divisible by 400, in which case it is a leap year.\n",
+    "\n",
+    "E.g 2000 is a leap year, 2020 is a leap year."
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "id": "6086ec57",
+   "metadata": {
+    "slideshow": {
+     "slide_type": "subslide"
+    }
+   },
+   "source": [
+    "### Exercice: Leap year (cont.)"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 26,
+   "id": "8630973c",
+   "metadata": {
+    "slideshow": {
+     "slide_type": "fragment"
+    }
+   },
+   "outputs": [
+    {
+     "name": "stdout",
+     "output_type": "stream",
+     "text": [
+      "2000 is a leap year.\n",
+      "2020 is a leap year.\n",
+      "2100 is not a leap year.\n",
+      "2400 is a leap year.\n"
+     ]
+    }
+   ],
+   "source": [
+    "def is_leap_year(year):\n",
+    "    if (year % 4 == 0 and year % 100 != 0) or (year % 400 == 0):\n",
+    "        return True\n",
+    "    else:\n",
+    "        return False\n",
+    "\n",
+    "test_years = [2020, 2100, 2400]\n",
+    "\n",
+    "for year in test_years:\n",
+    "    if is_leap_year(year):\n",
+    "        print(f\"{year} is a leap year.\")\n",
+    "    else:\n",
+    "        print(f\"{year} is not a leap year.\")"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "id": "eb56b548",
+   "metadata": {
+    "slideshow": {
+     "slide_type": "fragment"
+    }
+   },
+   "source": [
+    "Another possible test: compare to the Python [isLeap](https://github.com/python/cpython/blob/607f18c89456cdc9064e27f86a7505e011209757/Lib/calendar.py#L141) from the `calendar` module."
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 87,
+   "id": "c3a28d0e",
+   "metadata": {
+    "slideshow": {
+     "slide_type": "fragment"
+    }
+   },
+   "outputs": [],
+   "source": [
+    "import calendar\n",
+    "\n",
+    "def is_leap_year(year):\n",
+    "    return calendar.isleap(year)"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "id": "68fa27fe",
+   "metadata": {
+    "slideshow": {
+     "slide_type": "subslide"
+    }
+   },
+   "source": [
+    "### Exercice: Find a number in a list\n",
+    "\n",
+    "Given a list of integer, return a specific number provided as parameter"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 90,
+   "id": "8b2ba103",
+   "metadata": {
+    "slideshow": {
+     "slide_type": "fragment"
+    }
+   },
+   "outputs": [],
+   "source": [
+    "def search_element_in_list(element, list):\n",
+    "\n",
+    "    for i in list:\n",
+    "        if i == element:\n",
+    "            return True\n",
+    "    return False\n",
+    "\n",
+    "element_list = [1, 2, 3, 4, 5]\n",
+    "element_to_find = 3\n",
+    "result = search_element_in_list(element_to_find, element_list)\n",
+    "assert result == True, f\"Expected True, but got {result}\""
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "id": "6dbe39e2",
+   "metadata": {
+    "slideshow": {
+     "slide_type": "fragment"
+    }
+   },
+   "source": [
+    "Another type of test is to compare with a built-in Python function:"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 89,
+   "id": "40147ce1",
+   "metadata": {
+    "slideshow": {
+     "slide_type": "-"
+    }
+   },
+   "outputs": [],
+   "source": [
+    "def search_element_in_list_python(element, lst):\n",
+    "    return element in lst\n",
+    "\n",
+    "assert search_element_in_list(element_to_find, element_list) == search_element_in_list(element_to_find, element_list)"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "id": "15b9f515",
+   "metadata": {
+    "slideshow": {
+     "slide_type": "slide"
+    }
+   },
+   "source": [
+    "# Algorithms properties"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "id": "b78724b1",
+   "metadata": {
+    "slideshow": {
+     "slide_type": "subslide"
+    }
+   },
+   "source": [
+    "## Properties\n",
+    "\n",
+    "An algorithm possesses the following properties (among others):\n",
+    "\n",
+    "- Communicable\n",
+    "- Efficient\n",
+    "- Complete, terminates, and correct\n",
+    "- Deterministic"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "id": "8bccda63",
+   "metadata": {
+    "slideshow": {
+     "slide_type": "subslide"
+    }
+   },
+   "source": [
+    "## Communicate algorithms\n",
+    "\n",
+    "There are different ways to write algorithms. There is no optimal one, it depends on the context. Examples of contexts are:\n",
+    "\n",
+    "- Plain language (pseudo-code)\n",
+    "- Formalization such as an equation\n",
+    "- A software specification\n",
+    "- Implementation in a programming language"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "id": "60a6156f",
+   "metadata": {
+    "slideshow": {
+     "slide_type": "subslide"
+    }
+   },
+   "source": [
+    "### Plain language (pseudo-code)\n",
+    "\n",
+    "The pseudocode is a way to write algorithms in a human-readable way. It is not a programming language, but it is close to it. It is a way to communicate algorithms. E.g. for Euclid's algorithm:\n",
+    "\n",
+    "- Divide a by b, and you get the remainder r.\n",
+    "- Replace a with b.\n",
+    "- Replace b with r.\n",
+    "- Continue as long as it's possible; otherwise, you get the GCD (Greatest Common Divisor).\n",
+    "\n",
+    "or\n",
+    "  \n",
+    "```\n",
+    "function gcd(a, b)\n",
+    "    while b ≠ 0\n",
+    "       t := b; \n",
+    "       b := a mod b; \n",
+    "       a := t; \n",
+    "    return a;\n",
+    "  ````"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "id": "9d16ff11",
+   "metadata": {
+    "slideshow": {
+     "slide_type": "subslide"
+    }
+   },
+   "source": [
+    "### Equation\n",
+    "\n",
+    "You can use mathematical equations and notations to describe certain aspects of the algorithm's behavior or to express mathematical relationships within the algorithm. \n",
+    "\n",
+    "- $\\sum_{i=1}^{n} x_i$\n",
+    "\n",
+    "- $Fn = Fn-1 + Fn-2$\n",
+    "\n",
+    "- μ = (Σx) / N\n",
+    "\n",
+    "- $PR_{t+1}(P_i) =  \\sum_{P_j} \\frac{PR_t(P_j)}{C(P_j)}$"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "id": "b2f99051",
+   "metadata": {
+    "slideshow": {
+     "slide_type": "subslide"
+    }
+   },
+   "source": [
+    "### Graphics\n",
+    "\n",
+    "Graphical representations of algorithms are visual ways to illustrate the flow, logic, and structure of an algorithm. They are often used to aid in understanding, designing, and communicating algorithms, especially in algorithm design and computer science education. There are various types of graphical representations, and the choice depends on the complexity and purpose of the algorithm. \n",
+    "\n",
+    "<img src=\"figures/flowchart.png\" width=150></img>\n",
+    "\n",
+    "source: https://commons.wikimedia.org/wiki/File:Euclid_flowchart.svg\n"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "id": "861e2f0b",
+   "metadata": {
+    "slideshow": {
+     "slide_type": "subslide"
+    }
+   },
+   "source": [
+    "### Code (Python)\n",
+    "\n",
+    "Code (Python, Java, ..); example in Python:\n",
+    "\n",
+    "```python\n",
+    "def gcd(a, b):\n",
+    "    while b != 0:\n",
+    "        t = b\n",
+    "        b = a % b\n",
+    "        a = t\n",
+    "    return a\n",
+    "```\n",
+    "\n",
+    "In Java:\n",
+    "\n",
+    "```java\n",
+    "public class GCD {\n",
+    "    public static int gcd(int a, int b) {\n",
+    "        while (b != 0) {\n",
+    "            int t = b;\n",
+    "            b = a % b;\n",
+    "            a = t;\n",
+    "        }\n",
+    "        return a;\n",
+    "    }\n",
+    "}\n",
+    "```"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "id": "55662526",
+   "metadata": {
+    "slideshow": {
+     "slide_type": "subslide"
+    }
+   },
+   "source": [
+    "### Discussion on the type of representation\n",
+    "\n",
+    "There are different ways to express an algorithm, depending on the context and the level of formalization required.\n",
+    "\n",
+    "- **Graphical representation** is more accessible and provides an overview, allowing for the detection of errors, patterns, etc. Humans have better perception abilities in the visual space than in text.\n",
+    "\n",
+    "- **Pseudo-language** has the characteristic of being flexible, close to both human and computer languages, and independent of a programming language. However, it is often defined ambiguously and requires additional effort for implementation.\n",
+    "\n",
+    "- Finally, **implementation (e.g., Python)** has the advantage of being immediately testable. However, it can be very strict (must be correct) and sometimes challenging to read if one is not familiar with the language. This also depends on the programmer."
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "id": "39e29af0",
+   "metadata": {
+    "slideshow": {
+     "slide_type": "subslide"
+    }
+   },
+   "source": [
+    "## Efficiency\n",
+    "\n",
+    "> An algorithm is considered **efficient** if it minimizes the consumption of resources required to perform it.\n",
+    "\n",
+    "\n",
+    "Efficiency is relative to various criteria (values we want to measure) that need to be calculated (theoretically) or measured (empirically) in order to understand what is happening. Note that it is necessary to use large values of $n$ to obtain a representative behavior. Among these criteria:\n",
+    "\n",
+    "- Execution time\n",
+    "\n",
+    "- Required memory space\n",
+    "\n",
+    "- Disk storage space\n",
+    "\n",
+    "- Etc.\n",
+    "\n",
+    "We will see later that the concept of **Complexity** is based on one of these criteria and allows independence from the technology used (language, computer, compiler, etc.).\n"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "id": "a9849a9c",
+   "metadata": {
+    "slideshow": {
+     "slide_type": "subslide"
+    }
+   },
+   "source": [
+    "### Example:\n",
+    "\n",
+    "In genomics, it is common to compare two sequences (of genes) of lengths $N$ and $M$ (e.g., $\\texttt{TAG CAC}$ and $\\texttt{TGC TTG}$).\n",
+    "\n",
+    "- The number of comparisons is $N \\times M$.\n",
+    "\n",
+    "- If the size of the sequences doubles, then the number of comparisons... quadruples!\n",
+    "\n",
+    "- $(2 \\times N) \\times (2 \\times M) = 4 \\times (N \\times M)$.\n",
+    "\n",
+    "- Now, if we want to align 3 sequences, it becomes $N^{3}$.\n",
+    "\n",
+    "In practice, it becomes challenging to find a solution quickly (especially when comparing more than 2 sequences).\n",
+    "\n",
+    "\n",
+    "$\\rightarrow$ The same applies to long sequences.\n",
+    "\n",
+    "$\\rightarrow$ Therefore, it is necessary to have an efficient algorithm (in the case of sequence comparison, consider the [BLAST algorithm](https://en.wikipedia.org/wiki/BLAST) (Basic Local Alignment Search Tool)).\n"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "id": "b48e5cc5",
+   "metadata": {
+    "slideshow": {
+     "slide_type": "subslide"
+    }
+   },
+   "source": [
+    "## Other properties\n",
+    "\n",
+    "Other qualities of an algorithm (beyond being simple and understandable):\n",
+    "\n",
+    "---\n",
+    "\n",
+    "> **Completeness**: An algorithm must be complete, meaning that for a given problem, it provides a solution for each of the inputs.\n",
+    "\n",
+    "---\n",
+    "\n",
+    "> **Termination**: An algorithm must terminate within a finite time.\n",
+    "\n",
+    "---\n",
+    "\n",
+    "> **Correctness**: An algorithm must be correct and terminate by providing a result that is the solution to the problem it is supposed to solve.\n",
+    "\n",
+    "---\n",
+    "\n",
+    "$\\rightarrow$ All of this is very difficult to prove (formal proof, etc.)!\n"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "id": "0af6998c",
+   "metadata": {
+    "slideshow": {
+     "slide_type": "subslide"
+    }
+   },
+   "source": [
+    "### Algorithms patterns\n",
+    "\n",
+    "An algorithm has a **pattern**, which is a way to classify algorithms based on their properties.\n",
+    "\n",
+    "- There are several ways to design algorithms, either based on performance constraints or based on the structural style.\n",
+    "\n",
+    "- There is not a single unique algorithm for a given problem.\n",
+    "\n",
+    "Examples of patterns (main ones):\n",
+    "\n",
+    "- By purpose\n",
+    "- By implementation (e.g., **recursion**, functional, etc.)\n",
+    "- By **design paradigm** (Divide and Conquer, etc.)\n",
+    "- By **complexity**\n"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "id": "3d5ba2a2",
+   "metadata": {
+    "slideshow": {
+     "slide_type": "slide"
+    }
+   },
+   "source": [
+    "# Complexity"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "id": "e260b392",
+   "metadata": {
+    "slideshow": {
+     "slide_type": "subslide"
+    }
+   },
+   "source": [
+    "### What is complexity?\n",
+    "\n",
+    "> The **complexity of an algorithm** is the formal estimation of the amount of resources required to execute an algorithm. These resources can include time, memory space, storage, etc. \n",
+    "\n",
+    "There are different types of complexity:\n",
+    "\n",
+    "- **Best Case:** The _smallest_ number of operations the algorithm will have to execute on a dataset of a fixed size.\n",
+    "\n",
+    "- **Worst Case:** This is the _largest_ number of operations the algorithm will have to execute on a dataset of a fixed size.\n",
+    "\n",
+    "- **Average Case:** This is the _average_ of the algorithm's complexities on datasets of a fixed size.\n",
+    "\n",
+    "\n",
+    "Note: It is often the worst-case analysis that is chosen (provides an upper performance limit). The complexity in terms of the number of operations is typically the most studied.\n"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "id": "41ff1b6e",
+   "metadata": {
+    "slideshow": {
+     "slide_type": "subslide"
+    }
+   },
+   "source": [
+    "<img src=\"figures/big-o-chart.png\" width=75%>"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "id": "37fee118",
+   "metadata": {
+    "slideshow": {
+     "slide_type": "subslide"
+    }
+   },
+   "source": [
+    "### Exercice: find the complexity\n",
+    "\n",
+    "```python\n",
+    "  def maximum(L):\n",
+    "    m=L[0]\n",
+    "    for i in range(1,len(L)):\n",
+    "      if L[i]>m:\n",
+    "        m=L[i]\n",
+    "  return m\n",
+    "````\n"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "id": "7420338d",
+   "metadata": {
+    "slideshow": {
+     "slide_type": "fragment"
+    }
+   },
+   "source": [
+    "  $\\mathcal{O}(n)$\n",
+    "  \n",
+    "  (goes through the whole list in the worst case scenario)"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "id": "1c68b012",
+   "metadata": {
+    "slideshow": {
+     "slide_type": "subslide"
+    }
+   },
+   "source": [
+    "### Intuition behind the complexity calculation\n",
+    "\n",
+    "| Notation             | Complexity       | Intuition                                        |\n",
+    "| -------------------- | ---------------- | ------------------------------------------------ |\n",
+    "| $\\mathcal{O} 1$     | Constant         | First or nth element of a list, ...             |\n",
+    "| $\\mathcal{O} log n$ | Logarithmic     | Divide in half and repeat, ...                  |\n",
+    "| $\\mathcal{O} n$     | Linear           | Traverse data, ...                              |\n",
+    "| $\\mathcal{O} nlog n$ | Quasi-Linear   | Divide in half and combine, ...                 |\n",
+    "| $\\mathcal{O}n^{2}$  | Quadratic       | Traverse data with 2 loops, ...                 |\n",
+    "| $\\mathcal{O}2^{n}$  | Exponential     | Test all combinations, ...                      |\n",
+    "| $\\mathcal{O}n^k$, k >2 | Polynomial | Traverse data with k loops, ...               |\n",
+    "| $\\mathcal{O}n!$     | Factorial        | Test all paths (graph), ...                     |"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "id": "354c08c0",
+   "metadata": {
+    "slideshow": {
+     "slide_type": "subslide"
+    }
+   },
+   "source": [
+    "### Exercice: find the complexity"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 104,
+   "id": "65be2326",
+   "metadata": {
+    "slideshow": {
+     "slide_type": "-"
+    }
+   },
+   "outputs": [],
+   "source": [
+    "def nocc(x,L):\n",
+    "    n=0\n",
+    "    for y in L:\n",
+    "        if x==y:\n",
+    "            n=n+1\n",
+    "    return n"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "id": "c2853423",
+   "metadata": {
+    "slideshow": {
+     "slide_type": "fragment"
+    }
+   },
+   "source": [
+    "$\\mathcal{O}(n)$\n",
+    "  \n",
+    "(goes through the whole list in the worst case scenario)"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "id": "a667f037",
+   "metadata": {
+    "slideshow": {
+     "slide_type": "subslide"
+    }
+   },
+   "source": [
+    "### Exercice: find the complexity"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 108,
+   "id": "41fee19f",
+   "metadata": {},
+   "outputs": [],
+   "source": [
+    "def maj(L):\n",
+    "  xmaj=L[0]\n",
+    "  nmaj=nocc(xmaj,L)\n",
+    "  for i in range(1,len(L)):\n",
+    "    if nocc(L[i],L)>nmaj:\n",
+    "      xmaj=L[i]\n",
+    "      nmaj=nocc(L[i],L)\n",
+    "  return xmaj"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "id": "ad350594",
+   "metadata": {
+    "slideshow": {
+     "slide_type": "fragment"
+    }
+   },
+   "source": [
+    "$\\mathcal{O}(n^{2})$"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "id": "20906f5f",
+   "metadata": {
+    "slideshow": {
+     "slide_type": "subslide"
+    }
+   },
+   "source": [
+    "### Exercice: find the complexity\n",
+    "\n",
+    "The complexity of an `is_even(n)`algorithm that takes an integer `n` as input and returns `True` if n is an even number and `False`` otherwise."
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 125,
+   "id": "f6306bf2",
+   "metadata": {
+    "slideshow": {
+     "slide_type": "fragment"
+    }
+   },
+   "outputs": [],
+   "source": [
+    "def is_even(n):\n",
+    "    return n % 2 == 0"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "id": "41b3bb3c",
+   "metadata": {
+    "slideshow": {
+     "slide_type": "fragment"
+    }
+   },
+   "source": [
+    "$\\mathcal{O}(1)$"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "id": "872695b1",
+   "metadata": {
+    "slideshow": {
+     "slide_type": "subslide"
+    }
+   },
+   "source": [
+    "### Exercice: find the complexity"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 126,
+   "id": "206fae84",
+   "metadata": {},
+   "outputs": [],
+   "source": [
+    "def somcubes(n):\n",
+    "    s = 0\n",
+    "    while n>0:\n",
+    "        s = s+(n%10)**3\n",
+    "        n = n//10\n",
+    "    return s\n",
+    "\n",
+    "\n",
+    "def eq_somcubes(N):\n",
+    "  L = []\n",
+    "  for n in range(0, N+1):\n",
+    "    if n==somcubes(n):\n",
+    "      L.append(n)\n",
+    "    return L"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "id": "83fa5d5d",
+   "metadata": {
+    "slideshow": {
+     "slide_type": "fragment"
+    }
+   },
+   "source": [
+    "$\\mathcal{O}(nlog(n))$ (we seek numbers that are equal to the sum of the cubes of their digits)."
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "id": "6a617a3b",
+   "metadata": {
+    "slideshow": {
+     "slide_type": "subslide"
+    }
+   },
+   "source": [
+    "### Exercice: find the complexity\n",
+    "\n",
+    "You have two sorted lists, `[1, 3, 8, 10]` and `[2, 3, 9]``, and you want to obtain a new merged list from these two lists (without using sorting functions like sort or sorted). What is the complexity?"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "id": "01f5db81",
+   "metadata": {
+    "slideshow": {
+     "slide_type": "fragment"
+    }
+   },
+   "source": [
+    "We iterate through all the data once: $O(n)$."
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 120,
+   "id": "ae749b90",
+   "metadata": {
+    "slideshow": {
+     "slide_type": "subslide"
+    }
+   },
+   "outputs": [
+    {
+     "name": "stdout",
+     "output_type": "stream",
+     "text": [
+      "[1, 2, 3, 3, 8, 9, 10]\n"
+     ]
+    }
+   ],
+   "source": [
+    "def merge_sorted_lists(list1, list2):\n",
+    "    merged_list = []\n",
+    "    i = j = 0\n",
+    "\n",
+    "    while i < len(list1) and j < len(list2):\n",
+    "        if list1[i] < list2[j]:\n",
+    "            merged_list.append(list1[i])\n",
+    "            i += 1\n",
+    "        else:\n",
+    "            merged_list.append(list2[j])\n",
+    "            j += 1\n",
+    "\n",
+    "    while i < len(list1):\n",
+    "        merged_list.append(list1[i])\n",
+    "        i += 1\n",
+    "\n",
+    "    while j < len(list2):\n",
+    "        merged_list.append(list2[j])\n",
+    "        j += 1\n",
+    "\n",
+    "    return merged_list\n",
+    "\n",
+    "# Example usage:\n",
+    "list1 = [1, 3, 8, 10]\n",
+    "list2 = [2, 3, 9]\n",
+    "result = merge_sorted_lists(list1, list2)\n",
+    "print(result)"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "id": "85357f95",
+   "metadata": {
+    "slideshow": {
+     "slide_type": "subslide"
+    }
+   },
+   "source": [
+    "### Example: Selection sort\n",
+    "\n",
+    "Implement the selection sort which is described as pseudo-code below:\n",
+    "    \n",
+    "- Start with an unsorted list of elements.\n",
+    "- Find the smallest element in the unsorted portion of the list.\n",
+    "- Swap this smallest element with the first element in the unsorted portion.\n",
+    "- Now, consider the remaining unsorted portion (excluding the element that was just swapped).\n",
+    "- Repeat steps 2 to 4 until the entire list is sorted.\n",
+    "- The result is a sorted list in ascending order.\n",
+    "- The key idea is to repeatedly select the smallest element from the unsorted part of the list and move it to the beginning of the sorted part of the list. This process continues until the entire list is sorted.\n",
+    "\n"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "id": "ef34203d",
+   "metadata": {
+    "slideshow": {
+     "slide_type": "subslide"
+    }
+   },
+   "source": [
+    "### Example: Selection sort (cont.)"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 116,
+   "id": "311b2a95",
+   "metadata": {
+    "slideshow": {
+     "slide_type": "fragment"
+    }
+   },
+   "outputs": [
+    {
+     "name": "stdout",
+     "output_type": "stream",
+     "text": [
+      "[17, 20, 26, 31, 44, 54, 55, 77, 93]\n"
+     ]
+    }
+   ],
+   "source": [
+    "def selectionSort(l):\n",
+    "    for i in range(0, len(l)):\n",
+    "      min = i\n",
+    "      for j in range(i+1, len(l)):\n",
+    "          if(l[j] < l[min]):\n",
+    "              min = j\n",
+    "      tmp = l[i]\n",
+    "      l[i] = l[min]\n",
+    "      l[min] = tmp\n",
+    "    return l  \n",
+    "\n",
+    "if __name__==\"__main__\": \n",
+    "    liste = [54,26,93,17,77,31,44,55,20]\n",
+    "    selectionSort(liste)\n",
+    "    print(liste) # [17, 20, 26, 31, 44, 54, 55, 77, 93]\n",
+    "\n"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "id": "75b4a494",
+   "metadata": {
+    "slideshow": {
+     "slide_type": "fragment"
+    }
+   },
+   "source": [
+    "Complexity is on the order of $\\mathcal{O}(n^{2})$."
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "id": "c1afcc1d",
+   "metadata": {
+    "slideshow": {
+     "slide_type": "subslide"
+    }
+   },
+   "source": [
+    "## Complexity Calculation\n",
+    "\n",
+    "There isn't just one but several methods to calculate the complexity of an algorithm, depending on its properties (and the desired precision of the complexity). Here are the main approaches:\n",
+    "\n",
+    "- **Reduction of the code to a known case** and combination of complexities. For example, two loops ($O(\\log N)$) result in an overall complexity of $O(n^{2} \\log(n))$.\n",
+    "\n",
+    "- **Reduction to a family of known functions** and calculation of the relative growth rate (limit).\n",
+    "\n",
+    "- **Empirical calculation by displaying execution times** as a function of the problem size. It's worth noting that this is independent of the power of the machine.\n"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "id": "204152e1",
+   "metadata": {
+    "slideshow": {
+     "slide_type": "slide"
+    }
+   },
+   "source": [
+    "# Data structures\n"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "id": "282ed691",
+   "metadata": {
+    "slideshow": {
+     "slide_type": "subslide"
+    }
+   },
+   "source": [
+    "### Standard data structures\n",
+    "\n",
+    "Included in Python ([documentation](https://docs.python.org/3/tutorial/datastructures.html))\n",
+    "\n",
+    "\n",
+    "- `int`: Integer, typically 4 bytes in size.\n",
+    "- `long`: Long integer, can be 4 or 8 bytes in size.\n",
+    "- `float`: Real number.\n",
+    "- `str`: String, a sequence of characters (with Unicode conversion).\n",
+    "- `bool`: Boolean, representing True or False.\n",
+    "- `tuple`: Tuple, an ordered collection of elements, e.g., `(1, 2, \"ECL\", 3.14)`.\n",
+    "- `list`: List, an ordered and mutable collection of elements.\n",
+    "- `set`: Set, an unordered collection of unique elements.\n",
+    "- `dict`: Dictionary, a collection of key-value pairs, e.g., `{'small': 1, 'large': 2}`.\n",
+    "\n",
+    "You can check the data type of a variable or object \n",
+    "\n",
+    "```python\n",
+    "print(int)\n",
+    "print(type(int))\n",
+    "assert isinstance(3, int)\n",
+    "```\n"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "id": "b0dfbe40",
+   "metadata": {
+    "slideshow": {
+     "slide_type": "subslide"
+    }
+   },
+   "source": [
+    "### Standard data structures (cont.)\n",
+    "\n",
+    "- `range`: A range, representing a sequence of values to generate (in Python 2, `xrange()`).\n",
+    "- `complex`: Complex number, e.g., `1j` is one of the square roots of -1.\n",
+    "- `file`: File, for handling file input/output.\n",
+    "- `None`: Represents the absence of a value (equivalent to `void` in some contexts).\n",
+    "- `exception`: Exception, for handling errors and exceptional conditions.\n",
+    "- `function`: Function, a reusable block of code.\n",
+    "- `module`: Module, a file containing Python code and definitions.\n",
+    "- `object`: Object, a generic data type representing any Python object.\n"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "id": "01b8a90c",
+   "metadata": {
+    "slideshow": {
+     "slide_type": "subslide"
+    }
+   },
+   "source": [
+    "### Advanced data structures\n",
+    "\n",
+    "Not included in Python, often achieved using standard structure and object-oriented programming:\n",
+    "\n",
+    "- **Linked Lists**: A data structure where elements are linked together with pointers, allowing for efficient insertions and deletions but not direct access to elements by index.\n",
+    "\n",
+    "- **Stacks**: A linear data structure that follows the Last-In-First-Out (LIFO) principle, commonly used for managing function calls, undo operations, and parsing expressions.\n",
+    "\n",
+    "- **Queues**: A linear data structure that follows the First-In-First-Out (FIFO) principle, used for tasks such as managing tasks in a print queue or breadth-first search in graphs.\n",
+    "\n",
+    "- **Priority Queue**: A data structure that stores elements with associated priorities and allows for efficient retrieval of the element with the highest (or lowest) priority."
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "id": "ce212ed1",
+   "metadata": {
+    "slideshow": {
+     "slide_type": "subslide"
+    }
+   },
+   "source": [
+    "### Advanced data structures (cont.)\n",
+    "- **Heaps**: A specialized tree-based data structure that is often used to implement priority queues. It ensures that the highest (or lowest) priority element can be efficiently accessed.\n",
+    "\n",
+    "- **Deques (Double-Ended Queues)**: A linear data structure that allows elements to be added or removed from both ends with constant-time complexity, useful for certain algorithms and data management.\n",
+    "\n",
+    "- **Trees**: A hierarchical data structure with a root node and child nodes, commonly used for various purposes such as binary search trees, AVL trees, and decision trees.\n",
+    "\n",
+    "- **Graphs**: A non-linear data structure consisting of nodes and edges, used for modeling relationships between objects or entities. Python provides libraries like NetworkX for graph manipulation.\n",
+    "\n",
+    "- **Hash Tables (Dictionaries)**: A data structure that allows efficient key-value mapping and retrieval. Python's built-in `dict` type is an example.\n"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "id": "8982a34a",
+   "metadata": {
+    "slideshow": {
+     "slide_type": "subslide"
+    }
+   },
+   "source": [
+    "### Data structures complexity\n",
+    "\n",
+    "\n",
+    "- **List:** Lists in Python offer dynamic resizing and allow for constant-time access to elements by index. However, they may have linear time complexity for operations like insertion or deletion in the middle of the list due to shifting elements.\n",
+    "\n",
+    "- **Dictionary:** Python dictionaries, implemented as hash tables, provide constant-time average-case complexity for key-based operations such as insertion, retrieval, and deletion. However, the worst-case scenario can lead to linear time complexity.\n",
+    "\n",
+    "- **Set:** Sets in Python have efficient average-case time complexity for set operations like union, intersection, and difference, which is often close to constant time. However, in rare cases, these operations may exhibit linear time complexity.\n",
+    "\n",
+    "Understanding the complexities of these built-in data structures is essential for selecting the right one for specific programming tasks and optimizing the performance of Python programs."
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "id": "87538ea2",
+   "metadata": {
+    "slideshow": {
+     "slide_type": "subslide"
+    }
+   },
+   "source": [
+    "## Dictionnaries\n",
+    "\n",
+    "\n",
+    "A **dictionary** in Python is an unordered collection of key-value pairs. It is a versatile data structure that allows you to store and retrieve values based on unique keys. Unlike lists or arrays, which use integer indices, dictionaries use keys to access their elements.\n",
+    "\n",
+    "- **Keys** in a dictionary must be unique and immutable, meaning you can use strings, numbers, or tuples as keys, but not lists or other dictionaries.\n",
+    "- **Values** can be of any data type, including strings, numbers, lists, other dictionaries, or even functions.\n",
+    "\n",
+    "Dictionaries are useful for a wide range of applications, such as:\n",
+    "\n",
+    "- Storing and retrieving configuration settings.\n",
+    "- Counting the frequency of elements in a dataset.\n",
+    "- Representing data in a structured way, such as JSON.\n",
+    "\n"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "id": "9036ba27",
+   "metadata": {
+    "slideshow": {
+     "slide_type": "subslide"
+    }
+   },
+   "source": [
+    "### Example: Creating a Dictionary in Python\n",
+    "\n",
+    "\n",
+    "```python\n",
+    ">>> phonebook = {'bob': 7387, 'alice': 3719, 'jack': 7052}\n",
+    ">>> phonebook['alice']\n",
+    "3719\n",
+    "```\n",
+    "\n",
+    "- Implemented as a Python dictionary.\n",
+    "- Raises a `KeyError: 'missing'` exception if accessing an undefined key.\n",
+    "- A good practice is to use `.get(\"attr\", \"\")` to return a default value if the key doesn't exist.\n",
+    "- We will see that they are widely used for memoization to avoid recomputing certain calculations (e.g., dynamic programming).\n"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "id": "192c9168",
+   "metadata": {
+    "slideshow": {
+     "slide_type": "subslide"
+    }
+   },
+   "source": [
+    "### Example: Creating a Dictionary in Python\n",
+    "\n",
+    "Here's an example of how to create a dictionary in Python:\n",
+    "\n",
+    "```python\n",
+    "# Create a dictionary to store information about a person\n",
+    "person = {\n",
+    "    \"name\": \"John Doe\",\n",
+    "    \"age\": 30,\n",
+    "    \"city\": \"New York\"\n",
+    "}\n",
+    "\n",
+    "# Access values using keys\n",
+    "print(\"Name:\", person[\"name\"])\n",
+    "print(\"Age:\", person[\"age\"])\n",
+    "print(\"City:\", person[\"city\"])\n",
+    "```\n",
+    "\n",
+    "In this example, we've created a dictionary named `person` that contains information about an individual. We access the values stored in the dictionary using their respective keys.\n",
+    "\n",
+    "Output:\n",
+    "```\n",
+    "Name: John Doe\n",
+    "Age: 30\n",
+    "City: New York\n",
+    "```\n",
+    "."
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "id": "3cc3715e",
+   "metadata": {
+    "slideshow": {
+     "slide_type": "subslide"
+    }
+   },
+   "source": [
+    "### Question: Count words in a list (using a dictionnary)\n",
+    "\n",
+    "Write an algorithm that takes two parameters:\n",
+    "- `stri`: A list of words.\n",
+    "- `n`: An integer.\n",
+    "\n",
+    "And returns how many words in the list appear exactly `n` times, and return that count.\n"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "id": "db5cc56c",
+   "metadata": {
+    "slideshow": {
+     "slide_type": "subslide"
+    }
+   },
+   "source": [
+    "### Question: Count words in a list (using a dictionnary)"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 121,
+   "id": "d5b559aa",
+   "metadata": {
+    "slideshow": {
+     "slide_type": "fragment"
+    }
+   },
+   "outputs": [
+    {
+     "name": "stdout",
+     "output_type": "stream",
+     "text": [
+      "2\n"
+     ]
+    }
+   ],
+   "source": [
+    "def countWords(stri, n): \n",
+    "    \n",
+    "    m = dict() \n",
+    "    for w in stri: # m {'hate': 2, 'love': 4, 'peace': 4}\n",
+    "        m[w] = m.get(w, 0) + 1\n",
+    "\n",
+    "    res = 0\n",
+    "    for i in m.values(): \n",
+    "        if i == n: \n",
+    "            res += 1\n",
+    "\n",
+    "    return res \n",
+    "\n",
+    "if __name__==\"__main__\": \n",
+    "    # Driver code \n",
+    "    s = [ \"hate\", \"love\", \"peace\", \"love\", \n",
+    "        \"peace\", \"hate\", \"love\", \"peace\", \"love\", \"peace\" ] \n",
+    "\n",
+    "    print(countWords(s, 4)) # 2"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "id": "35a76856",
+   "metadata": {
+    "slideshow": {
+     "slide_type": "subslide"
+    }
+   },
+   "source": [
+    "### Exercice: detect duplicates from a list (using dicts)\n",
+    "\n",
+    "Write an algorithm validates the following:\n",
+    "\n",
+    "```python\n",
+    "assert duplicatas([1,2]) == False\n",
+    "assert duplicatas([1,2,1]) == True\n",
+    "```"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 98,
+   "id": "67336f28",
+   "metadata": {
+    "slideshow": {
+     "slide_type": "fragment"
+    }
+   },
+   "outputs": [],
+   "source": [
+    "def duplicatas(L):\n",
+    "    d = {}\n",
+    "    for x in L:\n",
+    "        if x in d:\n",
+    "            return True\n",
+    "        d[x] = True\n",
+    "    return False\n",
+    "\n",
+    "assert duplicatas([1,2]) == False\n",
+    "assert duplicatas([1,2,1]) == True"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "id": "3fb60306",
+   "metadata": {
+    "slideshow": {
+     "slide_type": "subslide"
+    }
+   },
+   "source": [
+    "### Exercice: algorithm optimization (using dicts)\n",
+    "\n",
+    "Optimize this algorithm all integers such that $A^2 + B^2 = C^2 + D^2$ with A, B, C, D ranging from 1 to 1000.\n",
+    "\n",
+    "```python\n",
+    "n = 1000\n",
+    "for a in range(1, n+1):\n",
+    "    for b in range(1, n+1):\n",
+    "        for c in range(1, n+1):\n",
+    "            for d in range(1, n+1):\n",
+    "                if a**2 + b**2 == c**2 + d**2:\n",
+    "                    print(a, b, c, d)\n",
+    "\n",
+    "```"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "id": "247972d9",
+   "metadata": {
+    "slideshow": {
+     "slide_type": "subslide"
+    }
+   },
+   "source": [
+    "### Exercice: algorithm optimization (using dicts) (cont.)\n",
+    "\n",
+    "```python\n",
+    "n = 1000\n",
+    "result_map = {}\n",
+    "\n",
+    "for c in range(1, n+1):\n",
+    "    for d in range(1, n+1):\n",
+    "        result = c**2 + d**2\n",
+    "        if result in result_map:\n",
+    "            result_map[result].append((c, d))\n",
+    "        else:\n",
+    "            result_map[result] = [(c, d)]\n",
+    "\n",
+    "for a in range(1, n+1):\n",
+    "    for b in range(1, n+1):\n",
+    "        result = a**2 + b**2\n",
+    "        if result in result_map:\n",
+    "            matching_pairs = result_map[result]\n",
+    "            for pair in matching_pairs:\n",
+    "                print(a, b, pair)\n",
+    "\n",
+    "```\n",
+    "\n",
+    "- A first loop uses a dictionary `result_map` to store pairs $(c, d)$ that yield the same result $c^2 + d^2$.\n",
+    "- A second loop iterates through $a^2 + b^2$ values and checks if there are matching pairs in `result_map`.\n"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "id": "c82d4d90",
+   "metadata": {
+    "slideshow": {
+     "slide_type": "subslide"
+    }
+   },
+   "source": [
+    "## Sets\n",
+    "\n",
+    "A **set** in Python is an unordered collection of unique elements. It is similar to a mathematical set and has several important characteristics:\n",
+    "\n",
+    "1. **Uniqueness**: Sets do not allow duplicate elements. If you try to add a duplicate element to a set, it will be ignored.\n",
+    "\n",
+    "2. **Unordered**: Unlike lists or tuples, sets do not have a specific order. The elements are not stored in any particular sequence, and you cannot access them by index.\n",
+    "\n",
+    "3. **Mutable**: Sets are mutable, which means you can add or remove elements after creating a set.\n",
+    "\n",
+    "4. **No Indexing**: Since sets are unordered, you cannot access elements by their index. Instead, you typically perform operations on sets as a whole.\n",
+    "\n",
+    "5. **Common Set Operations**: Sets support various set operations such as union, intersection, difference, and more, making them useful for mathematical and data manipulation tasks.\n"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "id": "bca7c805",
+   "metadata": {
+    "slideshow": {
+     "slide_type": "subslide"
+    }
+   },
+   "source": [
+    "## Sets (cont.)\n",
+    "\n",
+    "```python\n",
+    "# Creating a set\n",
+    "my_set = {1, 2, 3, 4, 5}\n",
+    "\n",
+    "# Creating an empty set\n",
+    "empty_set = set()\n",
+    "```\n",
+    "\n",
+    "Common set operations include:\n",
+    "\n",
+    "- **Adding Elements**: You can add elements to a set using the `add()` method.\n",
+    "\n",
+    "- **Removing Elements**: Elements can be removed from a set using the `remove()` or `discard()` method.\n",
+    "\n",
+    "- **Set Operations**: You can perform operations like union (`|`), intersection (`&`), difference (`-`), and more between sets.\n",
+    "\n",
+    "- **Checking Membership**: You can check if an element is in a set using the `in` operator.\n",
+    "\n",
+    "- **Iterating**: You can iterate through the elements of a set using a `for` loop.\n",
+    "\n",
+    "Sets are commonly used for tasks where uniqueness and set operations are essential."
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "id": "cf4fcdf0",
+   "metadata": {
+    "slideshow": {
+     "slide_type": "subslide"
+    }
+   },
+   "source": [
+    "### Set Operations in Python\n",
+    "\n",
+    "| Method                | Description                    |\n",
+    "|-----------------------|--------------------------------|\n",
+    "| `add()`               | Adds an element to the set.    |\n",
+    "| `clear()`             | Removes all elements from the set. |\n",
+    "| `copy()`              | Returns a copy of the set.     |\n",
+    "| `difference()`        | Returns the difference of two sets. |\n",
+    "| `intersection()`      | Returns the intersection of two sets. |\n",
+    "| `pop()`               | Removes and returns a random element from the set. |\n",
+    "| `union()`             | Returns the union of two sets. |\n",
+    "| `isdisjoint()`        | Returns `True` if the sets have no elements in common. |\n",
+    "| `issubset()`          | Returns `True` if the set is a subset of another set. |\n",
+    "| `issuperset()`        | Returns `True` if the set contains another set. |\n",
+    "\n",
+    "There are many other set operations available in Python, and `frozenset` can be used to create an immutable set.\n",
+    "\n",
+    "For more details, refer to the [Python documentation](https://docs.python.org/3/library/stdtypes.html#set-types-set-frozenset).\n"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "id": "e3fce712",
+   "metadata": {
+    "slideshow": {
+     "slide_type": "subslide"
+    }
+   },
+   "source": [
+    "### Exercice: remove duplicatas from a list (using sets)\n",
+    "\n",
+    "Write an algorithm validates the following:\n",
+    "\n",
+    "```python\n",
+    "assert duplicatas_sets([1,2]) == False\n",
+    "assert duplicatas_sets([1,2,1]) == True\n",
+    "```"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 135,
+   "id": "19e2c4ab",
+   "metadata": {
+    "slideshow": {
+     "slide_type": "fragment"
+    }
+   },
+   "outputs": [],
+   "source": [
+    "def duplicatas_sets(L):\n",
+    "\ts = set()\n",
+    "\tfor x in L:\n",
+    "\t\tif x in s:\n",
+    "\t\t\treturn True\n",
+    "\t\ts.add(x)\n",
+    "\treturn False"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 141,
+   "id": "aec4421f",
+   "metadata": {
+    "slideshow": {
+     "slide_type": "fragment"
+    }
+   },
+   "outputs": [],
+   "source": [
+    "def duplicatas_sets2(nums):\n",
+    "    return True if len(set(nums)) < len(nums) else False\n",
+    "  \n",
+    "assert duplicatas_sets2([1,2]) == False\n",
+    "assert duplicatas_sets2([1,2,1]) == True"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "id": "61b23935",
+   "metadata": {
+    "slideshow": {
+     "slide_type": "subslide"
+    }
+   },
+   "source": [
+    "### Exercice: find pairs duplicates (using sets) \n",
+    "\n",
+    "In a list, return the values that occure exactly 2 times."
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 137,
+   "id": "632fd6b4",
+   "metadata": {
+    "slideshow": {
+     "slide_type": "fragment"
+    }
+   },
+   "outputs": [
+    {
+     "name": "stdout",
+     "output_type": "stream",
+     "text": [
+      "[(2, 2), (3, 3), (5, 5)]\n"
+     ]
+    }
+   ],
+   "source": [
+    "def find_duplicate_pairs_optimized(lst):\n",
+    "    seen = set()\n",
+    "    duplicate_pairs = []\n",
+    "\n",
+    "    for num in lst:\n",
+    "        if num in seen:\n",
+    "            duplicate_pairs.append((num, num))\n",
+    "        seen.add(num)\n",
+    "\n",
+    "    return duplicate_pairs\n",
+    "\n",
+    "# Example usage:\n",
+    "input_list = [2, 3, 5, 2, 7, 3, 8, 5]\n",
+    "result = find_duplicate_pairs_optimized(input_list)\n",
+    "print(result)"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "id": "7c958cd9",
+   "metadata": {
+    "slideshow": {
+     "slide_type": "subslide"
+    }
+   },
+   "source": [
+    "### Exercice: find words typed with a single row on a keyboard (using sets)\n",
+    "\n",
+    "You can determine words that can be typed with a single row of letters on a keyboard using sets in Python.\n",
+    "\n",
+    "```python\n",
+    "words = ['Velo', 'Ecole', 'Informatique', 'Etroit']\n",
+    "check_keyboard(words) == ['Etroit'] # for a French keyboard\n",
+    "```"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 151,
+   "id": "e3686496",
+   "metadata": {
+    "slideshow": {
+     "slide_type": "fragment"
+    }
+   },
+   "outputs": [
+    {
+     "name": "stdout",
+     "output_type": "stream",
+     "text": [
+      "['Etroit']\n"
+     ]
+    }
+   ],
+   "source": [
+    "def check_keyboard(words):\n",
+    "    result = []\n",
+    "    for w in words:\n",
+    "        ws = set([c.lower() for c in w])\n",
+    "        if not ws.difference(\"azertyuiop\") \\\n",
+    "            or not ws.difference(\"qsdfghjklm\") \\\n",
+    "            or not ws.difference(\"wxcvbn\"):\n",
+    "            result.append(w)\n",
+    "    return result\n",
+    "\n",
+    "typed_with_single_row = solution(words)\n",
+    "print(typed_with_single_row)"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "id": "8865e8a6",
+   "metadata": {
+    "slideshow": {
+     "slide_type": "subslide"
+    }
+   },
+   "source": [
+    "<img src=\"figures/complexite-arrays.png\" width=75%>"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "id": "995c354c",
+   "metadata": {
+    "slideshow": {
+     "slide_type": "subslide"
+    }
+   },
+   "source": [
+    "<img src=\"figures/complexite-data-structures.png\" width=75%>"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "id": "b6e68dc5",
+   "metadata": {
+    "slideshow": {
+     "slide_type": "slide"
+    }
+   },
+   "source": [
+    "# Empirical complexity analysis"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "id": "0a04e8e2",
+   "metadata": {
+    "slideshow": {
+     "slide_type": "subslide"
+    }
+   },
+   "source": [
+    "## Empirical complexity analysis\n",
+    "\n",
+    "A practical way to estimate complexity\n",
+    "\n",
+    "1. **Gather data** on the execution time of algorithms or operations for various input sizes. This data is typically collected through various random measurements.\n",
+    "\n",
+    "2. **Plot the time measures** for the various measurements, for each algorithm to assess performance scales.\n",
+    "\n",
+    "3. **Analyzing trends** to draw conclusions about the algorithm's time complexity by observing curves in the plotted data.\n",
+    "\n",
+    "Using the matplotlib library (to be imported as a module):"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 146,
+   "id": "273e0647",
+   "metadata": {},
+   "outputs": [],
+   "source": [
+    "import matplotlib.pyplot as plt"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "id": "80c00461",
+   "metadata": {
+    "slideshow": {
+     "slide_type": "subslide"
+    }
+   },
+   "source": [
+    "### Example: constant time"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 145,
+   "id": "76f6f476",
+   "metadata": {
+    "slideshow": {
+     "slide_type": "-"
+    }
+   },
+   "outputs": [
+    {
+     "data": {
+      "text/plain": [
+       "[<matplotlib.lines.Line2D at 0x11774cd30>]"
+      ]
+     },
+     "execution_count": 145,
+     "metadata": {},
+     "output_type": "execute_result"
+    },
+    {
+     "data": {
+      "image/png": "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rtnYRY8++qjGjRun2267TREREbrnnns0ffp0SVJYWJgkqampST179tQLL7yg1NRUTZ48WY888kjAy06fl5OTo9raWv+toqLiSh4KAADoAIIKlri4OIWFhTW7mlJdXd3sqstFUVFRysvL07lz53Tq1CmVl5erX79+io6OVlxcnCSpV69e+trXvuYPGOmz98VUVVXp/Pnzlzyv1+tVTExMwA0AAHROQQVL165dlZqaqoKCgoDxgoICpaenX/bYiIgI9enTR2FhYdqwYYPuuusudeny2a8fOXKkTp48qaamJv/8EydOqFevXuratWswSwQAAJ1Q0C8JZWdn68UXX1ReXp6OHTumefPmqby8XFlZWZI+e6lm6tSp/vknTpzQK6+8ovfee09FRUWaPHmyDh8+rKVLl/rnPPjgg/rwww81Z84cnThxQn/605+0dOlSzZw5MwQPEQAAdHRBfw/LpEmT9OGHH2rx4sWqrKzUoEGDlJ+fr759+0qSKisrVV5e7p/f2NioZ555RsePH1dERITGjBmjffv2qV+/fv45SUlJ2r59u+bNm6fBgwerd+/emjNnjubPn3/1jxAAAHR4QX8Pi1V8DwsAAB1Pm3wPCwAAQHsgWAAAgHkECwAAMI9gAQAA5hEsAADAPIIFAACYR7AAAADzCBYAAGAewQIAAMwjWAAAgHkECwAAMI9gAQAA5hEsAADAPIIFAACYR7AAAADzCBYAAGAewQIAAMwjWAAAgHkECwAAMI9gAQAA5hEsAADAPIIFAACYR7AAAADzCBYAAGAewQIAAMwjWAAAgHkECwAAMI9gAQAA5hEsAADAPIIFAACYR7AAAADzCBYAAGAewQIAAMwjWAAAgHkECwAAMI9gAQAA5hEsAADAPIIFAACYR7AAAADzCBYAAGAewQIAAMwjWAAAgHnh7b2AUHHOSZJ8Pl87rwQAALTWxefti8/jLek0wVJXVydJSkpKaueVAACAYNXV1Sk2NrbF+z3ui5Kmg2hqatIHH3yg6OhoeTyekJ3X5/MpKSlJFRUViomJCdl5cWns97XFfl9b7Pe1xX5fW1e638451dXVKTExUV26tPxOlU5zhaVLly7q06dPm50/JiaGv/DXEPt9bbHf1xb7fW2x39fWlez35a6sXMSbbgEAgHkECwAAMI9g+QJer1ePPfaYvF5vey/lfwL7fW2x39cW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",
+      "text/plain": [
+       "<Figure size 640x480 with 1 Axes>"
+      ]
+     },
+     "metadata": {},
+     "output_type": "display_data"
+    }
+   ],
+   "source": [
+    "steps = []\n",
+    "def constant(n):\n",
+    "    return 1\n",
+    "    \n",
+    "for i in range(1, 100):\n",
+    "    steps.append(constant(i))\n",
+    "plt.plot(steps)"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "id": "fe0a6c66",
+   "metadata": {
+    "slideshow": {
+     "slide_type": "subslide"
+    }
+   },
+   "source": [
+    "### Example: linear time"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 150,
+   "id": "6e6c4334",
+   "metadata": {},
+   "outputs": [
+    {
+     "data": {
+      "text/plain": [
+       "Text(0, 0.5, 'Steps')"
+      ]
+     },
+     "execution_count": 150,
+     "metadata": {},
+     "output_type": "execute_result"
+    },
+    {
+     "data": {
+      "image/png": "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",
+      "text/plain": [
+       "<Figure size 640x480 with 1 Axes>"
+      ]
+     },
+     "metadata": {},
+     "output_type": "display_data"
+    }
+   ],
+   "source": [
+    "steps = []\n",
+    "def linear(n):\n",
+    "    return n\n",
+    "    \n",
+    "for i in range(1, 100):\n",
+    "    steps.append(linear(i))\n",
+    "    \n",
+    "plt.plot(steps)\n",
+    "plt.xlabel('Inputs')\n",
+    "plt.ylabel('Steps')"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 77,
+   "id": "54dcf1fa",
+   "metadata": {
+    "slideshow": {
+     "slide_type": "subslide"
+    }
+   },
+   "outputs": [],
+   "source": [
+    "import time\n",
+    "import random\n",
+    "import numpy as np\n",
+    "#%matplotlib inline\n",
+    "\n",
+    "nvalues = [100, 500, 1000, 1500, 2000, 2500, 3000]\n",
+    "timesAlgo = []\n",
+    "\n",
+    "for i in nvalues:\n",
+    "\n",
+    "    random.seed()\n",
+    "    p = 12**2 # magnitude of values\n",
+    "    liste = []\n",
+    "    \n",
+    "    for x in range(i): liste.append(random.randint(0, p))\n",
+    "\n",
+    "    a=time.perf_counter()\n",
+    "    e1 = []\n",
+    "    for n in liste:\n",
+    "        e1.append(n)\n",
+    "    b = time.perf_counter()\n",
+    "    timesAlgo.append(b-a)"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 128,
+   "id": "340dc177",
+   "metadata": {
+    "slideshow": {
+     "slide_type": "subslide"
+    }
+   },
+   "outputs": [
+    {
+     "data": {
+      "image/png": "iVBORw0KGgoAAAANSUhEUgAAAkcAAAGxCAYAAABoYBJuAAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjYuMiwgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy8o6BhiAAAACXBIWXMAAA9hAAAPYQGoP6dpAABlz0lEQVR4nO3deVxU9f4/8BfLzCAoqJAgLohWEG4JpmIhpgm4tNwW1FtE3hatXFDLi0up3UparVsu3wxt/YUpUnktlVLJFMkFFcXMBVNLMkwHc2F9//74NAMjAzIIHAZez8djHpw58znn8z6HwfP2nM/iICICIiIiIgIAOGodABEREVFDwuSIiIiIqBwmR0RERETlMDkiIiIiKofJEREREVE5TI6IiIiIymFyRERERFQOkyMiIiKicpgcEREREZXD5IioluzduxdjxoyBv78/XFxc0Lx5cwQHB+PVV1/Fn3/+qXV4VRo4cCAGDhxYZ/s/duwYHBwc8MEHH5jXbd26FXPmzMG5c+euef///e9/4enpieLiYmzatAkODg7ml5OTE7y9vfHAAw/gwIED11zXlWbNmoWOHTvC2dkZLVu2rPX9Nwam38mmTZu0DoWoWpy1DoCoMViyZAmeeuopBAQE4Nlnn0VQUBCKioqwY8cOLF68GOnp6UhJSdE6TM20bdsW6enp6NKli3nd1q1bMXfuXDzyyCPXnFQkJyfj7rvvhrNz2T9pL7/8Mm6//XYUFhZix44deOGFF/Ddd98hKysL7dq1u6b6TL788ku89NJLmDlzJoYOHQqDwVAr+21sgoODkZ6ejqCgIK1DIaoWJkdE1yg9PR1PPvkkhgwZgi+++MLiAjlkyBBMnToVa9eu1TBC7RkMBvTr169O9v3777/jhx9+wLRp0yzW33DDDeY6BwwYgJYtW+LRRx/FBx98gJkzZ15TnRcvXoSrqyv27dsHAJg4cSLatGlzTftsjIqKiuDg4AB3d/c6+/0T1QU+ViO6Ri+//DIcHBzw3nvvWb1zoNfrcdddd5nfl5aW4tVXX0VgYCAMBgPatGmDhx9+GCdPnrTYbuDAgejWrRvS09PRv39/NGvWDJ06dcKyZcsAAGvWrEFwcDBcXV3RvXv3CgnYnDlz4ODggMzMTNx7771wd3eHh4cHHnroIfzxxx9XPa7CwkK8+OKL5jivu+46jBkzxmLbhIQEODo6YvXq1RbbPvLII3B1dUVWVhaAio/V5syZg2effRYA4O/vb34EtmnTJjz66KNo3bo1Ll68WCGmQYMGoWvXrhbrUlJS0Lx5c9xxxx1VHo/p4vzLL7+Y1y1fvhyhoaFwc3ND8+bNERkZiczMzArH0rx5c2RlZSEiIgItWrTA4MGD0alTJ8yaNQsA4O3tDQcHB8yZM6fKGDIyMnDnnXfC09MTLi4u6NKlC+Li4izK/PDDDxg8eDBatGgBV1dX9O/fH2vWrLEo88EHH8DBwQEbNmzA448/Dk9PT7i7u+Phhx/GhQsXkJubi+joaLRs2RJt27bFM888g6KiIvP2pt/Hq6++ipdeegkdO3aEi4sLevfuje+++86irsOHD2PMmDG44YYb4Orqinbt2uHOO+80/25NTI/OPv74Y0ydOhXt2rWDwWDA4cOHrT5WO3r0KEaNGgVfX18YDAZ4e3tj8ODB2L17t7mMrX8r27dvR1hYGFxdXdG5c2ckJCSgtLS0yt8JkVVCRDVWXFwsrq6u0rdv32pv88QTTwgAGT9+vKxdu1YWL14s1113nXTo0EH++OMPc7nw8HDx9PSUgIAASUxMlHXr1smIESMEgMydO1e6d+8un332mXz99dfSr18/MRgM8uuvv5q3nz17tgAQPz8/efbZZ2XdunXy5ptvipubm/Tq1UsKCwst6goPDze/LykpkaioKHFzc5O5c+dKamqqvP/++9KuXTsJCgqSixcviohIaWmpDBs2TFq1aiXHjh0TEZGlS5cKAHn//ffN+8vJyREAsmzZMhEROXHihEyYMEEAyKpVqyQ9PV3S09PFaDTKnj17BIAsWbLE4rzt379fAMiCBQss1t9xxx3yz3/+0/x+48aNAkBWrFhhUe7LL78UADJjxgwREXnppZfEwcFB/vWvf8n//vc/WbVqlYSGhoqbm5vs37/fvF1sbKzodDrp1KmTzJs3T7777jtZt26d7Nq1Sx599FEBIGvXrpX09HQ5ceJEpb/3tWvXik6nkx49esgHH3wgGzZskKVLl8qoUaPMZTZt2iQ6nU5CQkJk+fLl8sUXX0hERIQ4ODhIUlKSudyyZcsEgPj7+8vUqVNl/fr18sorr4iTk5OMHj1agoOD5cUXX5TU1FT597//LQDkjTfeqPD76NChg9x2222SnJwsK1askFtuuUV0Op1s3brVXDYtLU2mTp0qK1eulLS0NElJSZF77rlHmjVrJj/99FOF896uXTu5//775auvvpL//e9/cubMGfNnGzduNJcPCAiQ66+/Xj7++GNJS0uT5ORkmTp1qkUZW/9WbrjhBlm8eLGkpqbKU089JQDkww8/rPR3QlQZJkdE1yA3N1cAWFzgqnLgwAEBIE899ZTF+oyMDIsLt4j6Bx+A7Nixw7zuzJkz4uTkJM2aNbNIhHbv3i0A5L///a95nSk5mjx5skVdn376qQCQTz75xKKu8snRZ599JgAkOTnZYtvt27cLAFm4cKF5XV5enrRv31769Okju3btEldXV3nooYcstrsyORIRee211wSA5OTkVDhP4eHhcvPNN1use/LJJ8Xd3V3Onz9vUbezs7NFnKYL8fLly6WoqEguXrwo33//vVx//fXi5OQke/bskePHj4uzs7NMmDDBoo7z58+Lj4+PREdHm9fFxsYKAFm6dGmFOE3nuPyFujJdunSRLl26yKVLlyot069fP2nTpo3FMRYXF0u3bt2kffv2UlpaKiJlydGV8d9zzz0CQN58802L9TfffLMEBweb35t+H76+vhbx5OfnS+vWreWOO+6oNMbi4mIpLCyUG264weK7ZTrvAwYMqLDNlclRXl6eAJC33nqr0npq8reSkZFhUTYoKEgiIyMrrYOoMnysRlSPNm7cCEA9qimvT58+uOmmmyo80mjbti1CQkLM71u3bo02bdrg5ptvhq+vr3n9TTfdBMDykZHJgw8+aPE+Ojoazs7O5lis+d///oeWLVvizjvvRHFxsfl18803w8fHx+LxiKenJ5YvX45du3ahf//+6NixIxYvXlz1ibiKSZMmYffu3diyZQsAID8/Hx9//DFiY2PRvHlzc7kvv/wSer0eUVFRFfYxcuRI6HQ6uLq6YsCAASgpKcHKlSvRo0cPrFu3DsXFxXj44Yctjs/FxQXh4eFWe1Xdd999NT6en3/+GUeOHMGjjz4KFxcXq2UuXLiAjIwM3H///RbH6OTkhJiYGJw8eRIHDx602GbEiBEW703fg+HDh1dYb+27ce+991rE06JFC9x55534/vvvUVJSAgAoLi7Gyy+/jKCgIOj1ejg7O0Ov1+PQoUNWe/9V5zy1bt0aXbp0wWuvvYY333wTmZmZFR5/2fq34uPjgz59+lis69Gjh9XjJroaJkdE18DLywuurq7IycmpVvkzZ84AUEnPlXx9fc2fm7Ru3bpCOb1eX2G9Xq8HAFy+fLlCeR8fH4v3zs7O8PT0rFBXeb///jvOnTsHvV4PnU5n8crNzUVeXp5F+b59+6Jr1664fPkynnzySbi5uVW67+q4++670alTJyxYsACAamNz4cIFPP300xblVq5ciaFDh8LV1bXCPl555RVs374du3btwvHjx3H06FHcc8895uMDgFtuuaXC8S1fvrzC8bm6usLd3b3Gx2Nqp9W+fftKy5w9exYiUul3A8BVvx+m74G19dX5bpjWFRYW4q+//gIATJkyBc899xzuuecerF69GhkZGdi+fTt69uyJS5cuVdjeWvxXcnBwwHfffYfIyEi8+uqrCA4OxnXXXYeJEyfi/PnzFsda3b8VT0/PCuUMBoPVGImuhr3ViK6Bk5MTBg8ejG+++QYnT56s8uIHlP0DfurUqQplf/vtN3h5edV6jLm5uRZd14uLi3HmzBmrFxMTLy8veHp6VtrLrkWLFhbvZ8+ejaysLISEhOD555/HiBEj0Llz5xrH7OjoiKeffhozZszAG2+8gYULF2Lw4MEICAgwlzEajfjuu+8sxk4qr3Pnzujdu7fVz0zneeXKlfDz87tqPA4ODrYfRDnXXXcdAFRoSFxeq1at4OjoiFOnTlX47LfffgOAWv9+5ObmWl2n1+vNd68++eQTPPzww3j55ZctyuXl5VkdgqG658rPzw+JiYkA1J21zz//HHPmzEFhYSEWL16syd8KkQnvHBFdo+nTp0NE8Pjjj6OwsLDC50VFRebeXIMGDQKgLjjlbd++HQcOHMDgwYNrPb5PP/3U4v3nn3+O4uLiKgd9HDFiBM6cOYOSkhL07t27wqt8kpKamop58+Zh1qxZSE1NhYeHB0aOHGn1XJRn6tlX2f/sH3vsMej1ejz44IM4ePAgxo8fb/H56tWr4eDgUOHRUnVERkbC2dkZR44csXp8lSVVNXXjjTeiS5cuWLp0KQoKCqyWcXNzQ9++fbFq1SqLc1JaWopPPvkE7du3x4033lirca1atcrijtL58+exevVqhIWFwcnJCYBKdq7shblmzRr8+uuvtRbHjTfeiFmzZqF79+7YtWsXAG3+VohMeOeI6BqFhoZi0aJFeOqppxASEoInn3wSXbt2RVFRETIzM/Hee++hW7duuPPOOxEQEIAnnngC77zzDhwdHTF06FAcO3YMzz33HDp06IDJkyfXenyrVq2Cs7MzhgwZgv379+O5555Dz549ER0dXek2o0aNwqeffophw4Zh0qRJ6NOnD3Q6HU6ePImNGzfi7rvvxj/+8Q+cOnUKDz30EMLDwzF79mw4Ojpi+fLlGDBgAKZNm4a33nqr0jq6d+8OAHj77bcRGxsLnU6HgIAA812pli1b4uGHH8aiRYvg5+eHO++802L7lStXYsiQIRXuYlVHp06d8MILL2DmzJk4evQooqKi0KpVK/z+++/48ccf4ebmhrlz59q836osWLAAd955J/r164fJkyejY8eOOH78ONatW2dOYOfNm4chQ4bg9ttvxzPPPAO9Xo+FCxdi3759+Oyzz675DtaVnJycMGTIEEyZMgWlpaV45ZVXkJ+fb3HsI0aMwAcffIDAwED06NEDO3fuxGuvvXbVu6RV2bt3L8aPH48HHngAN9xwA/R6PTZs2IC9e/ciPj4eADT5WyEy07pFOFFjsXv3bomNjZWOHTuKXq83d5l//vnn5fTp0+ZyJSUl8sorr8iNN94oOp1OvLy85KGHHqrQDTw8PFy6du1aoR4/Pz8ZPnx4hfUA5Omnnza/N/Wk2rlzp9x5553SvHlzadGihYwePVp+//33CnWV760mIlJUVCSvv/669OzZU1xcXKR58+YSGBgoY8eOlUOHDklxcbGEh4eLt7e3nDp1ymJbU0+0lJQUEbHeW01EZPr06eLr6yuOjo4VunqLqK7tACQhIcFi/V9//SUuLi4V9idSeVd+a7744gu5/fbbxd3dXQwGg/j5+cn9998v3377rblMbGysuLm5Wd3elt5qIiLp6ekydOhQ8fDwEIPBIF26dKnQm3Dz5s0yaNAgcXNzk2bNmkm/fv1k9erVFmVMvdW2b99erXiuPAbT7+OVV16RuXPnSvv27UWv10uvXr1k3bp1FtuePXtWHn30UWnTpo24urrKbbfdJps3b67wnanqvF/ZW+3333+XRx55RAIDA8XNzU2aN28uPXr0kPnz50txcbF5u2v9W4mNjRU/P78K64muxkFERJOsjIjq1Jw5czB37lz88ccfdts+Y+rUqVi0aBFOnDhh0Ubq888/x4MPPojff//daqN1qtqxY8fg7++P1157Dc8884zW4RA1OGxzREQNzrZt2/DRRx9h4cKFeOKJJyo0Ho+OjkZRURETIyKqE2xzREQNTmhoKFxdXTFixAi8+OKLWodDRE0MH6sRERERlcPHakRERETlMDkiIiIiKofJEREREVE5bJBto9LSUvz2229o0aJFrQ/IRkRERHVDRHD+/Hn4+vrC0bHqe0NMjmz022+/oUOHDlqHQURERDVw4sSJq47wzuTIRqapCk6cOHFNs3QTERFR/cnPz0eHDh2qNeUQkyMbmR6lubu7MzkiIiKyM9VpEsMG2URERETlMDkiIiIiKofJEREREVE5TI6IiIiIymFyRERERFROjZKjhQsXwt/fHy4uLggJCcHmzZurLJ+WloaQkBC4uLigc+fOWLx4cYUyycnJCAoKgsFgQFBQEFJSUmyud9WqVYiMjISXlxccHBywe/fuCvvIzc1FTEwMfHx84ObmhuDgYKxcudK2E0BERESNls3J0fLlyxEXF4eZM2ciMzMTYWFhGDp0KI4fP261fE5ODoYNG4awsDBkZmZixowZmDhxIpKTk81l0tPTMXLkSMTExGDPnj2IiYlBdHQ0MjIybKr3woULuPXWW5GQkFBp/DExMTh48CC++uorZGVl4d5778XIkSORmZlp66kgIiKixkhs1KdPHxk3bpzFusDAQImPj7daftq0aRIYGGixbuzYsdKvXz/z++joaImKirIoExkZKaNGjapRvTk5OQJAMjMzK3zm5uYmH330kcW61q1by/vvv281/isZjUYBIEajsVrliYiISHu2XL9tunNUWFiInTt3IiIiwmJ9REQEtm7danWb9PT0CuUjIyOxY8cOFBUVVVnGtM+a1FuZ2267DcuXL8eff/6J0tJSJCUloaCgAAMHDrRavqCgAPn5+RYvIiIiarxsSo7y8vJQUlICb29vi/Xe3t7Izc21uk1ubq7V8sXFxcjLy6uyjGmfNam3MsuXL0dxcTE8PT1hMBgwduxYpKSkoEuXLlbLz5s3Dx4eHuYX51UjIiJq3GrUIPvKobdFpMrhuK2Vv3J9dfZpa73WzJo1C2fPnsW3336LHTt2YMqUKXjggQeQlZVltfz06dNhNBrNrxMnTthUHxEREdkXm+ZW8/LygpOTU4W7NadPn65wV8fEx8fHanlnZ2d4enpWWca0z5rUa82RI0fw7rvvYt++fejatSsAoGfPnti8eTMWLFhgtRedwWCAwWCodh1ERERk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",
+      "text/plain": [
+       "<Figure size 640x480 with 1 Axes>"
+      ]
+     },
+     "metadata": {},
+     "output_type": "display_data"
+    }
+   ],
+   "source": [
+    "plt.plot(nvalues, timesAlgo, \"r-\", label=\"Algo 1\")\n",
+    "plt.title(\"Complexity/Perf comparison\")\n",
+    "plt.show()"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": null,
+   "id": "8593238b",
+   "metadata": {
+    "slideshow": {
+     "slide_type": "subslide"
+    }
+   },
+   "outputs": [],
+   "source": [
+    "import time\n",
+    "import random\n",
+    "\n",
+    "def measure_sorting_time(sorting_function, lst):\n",
+    "    a = time.perf_counter()\n",
+    "    sorting_function(lst)\n",
+    "    b = time.perf_counter()\n",
+    "    return b - a\n",
+    "\n",
+    "nvalues = [100, 500, 1000, 1500, 2000, 2500, 3000]\n",
+    "timesAlgo = []\n",
+    "\n",
+    "for i in nvalues:\n",
+    "    random.seed()\n",
+    "    p = 12**2  # Magnitude of values\n",
+    "    lst = [random.randint(0, p) for x in range(i)]\n",
+    "\n",
+    "    time_python_sort = measure_sorting_time(sorted, lst.copy())\n",
+    "    time_selection_sort = measure_sorting_time(selectionSort, lst.copy())\n",
+    "    # add more sorting algorithms\n",
+    "    \n",
+    "    timesAlgo.append((time_python_sort, time_selection_sort))\n",
+    "\n",
+    "python_sort_times = [t[0] for t in timesAlgo]\n",
+    "selection_sort_times = [t[1] for t in timesAlgo]\n"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 148,
+   "id": "fb711c57",
+   "metadata": {
+    "slideshow": {
+     "slide_type": "subslide"
+    }
+   },
+   "outputs": [
+    {
+     "data": {
+      "image/png": "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",
+      "text/plain": [
+       "<Figure size 640x480 with 1 Axes>"
+      ]
+     },
+     "metadata": {},
+     "output_type": "display_data"
+    }
+   ],
+   "source": [
+    "# Plot the results\n",
+    "plt.plot(nvalues, python_sort_times, marker='o', linestyle='-', color='b', label='Python Built-in Sort')\n",
+    "plt.plot(nvalues, selection_sort_times, marker='o', linestyle='-', color='g', label='Selection Sort (Custom)')\n",
+    "plt.xlabel('Input Size (n)')\n",
+    "plt.ylabel('Time (seconds)')\n",
+    "plt.title('Comparison of Sorting Algorithms')\n",
+    "plt.legend()\n",
+    "plt.grid()\n",
+    "plt.show()"
+   ]
+  }
+ ],
+ "metadata": {
+  "celltoolbar": "Slideshow",
+  "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.10.9"
+  }
+ },
+ "nbformat": 4,
+ "nbformat_minor": 5
+}
diff --git a/03-lists-search-sort.ipynb b/03-lists-search-sort.ipynb
index b1084b9..cc8c8cd 100644
--- a/03-lists-search-sort.ipynb
+++ b/03-lists-search-sort.ipynb
@@ -597,25 +597,6 @@
     "order_by_alphabetical_order(\"cherry\", \"banana\")"
    ]
   },
-  {
-   "cell_type": "code",
-   "execution_count": 53,
-   "id": "a0c076fa",
-   "metadata": {},
-   "outputs": [
-    {
-     "data": {
-      "text/plain": [
-       "66"
-      ]
-     },
-     "execution_count": 53,
-     "metadata": {},
-     "output_type": "execute_result"
-    }
-   ],
-   "source": []
-  },
   {
    "cell_type": "markdown",
    "id": "ee60b8ff",
@@ -764,9 +745,17 @@
     "    print(item)"
    ]
   },
+  {
+   "cell_type": "markdown",
+   "id": "c5bf0281",
+   "metadata": {},
+   "source": [
+    "Fibonacci with generators"
+   ]
+  },
   {
    "cell_type": "code",
-   "execution_count": 11,
+   "execution_count": 15,
    "id": "ff445529",
    "metadata": {},
    "outputs": [],
@@ -832,7 +821,7 @@
   },
   {
    "cell_type": "code",
-   "execution_count": 18,
+   "execution_count": 16,
    "id": "53534019",
    "metadata": {
     "slideshow": {
@@ -849,10 +838,8 @@
     }
    ],
    "source": [
-    "# Initialize an empty linked list\n",
     "linked_list = None\n",
     "\n",
-    "# Function to append data to the linked list\n",
     "def append(data):\n",
     "    global linked_list\n",
     "    if linked_list is None:\n",
@@ -863,7 +850,6 @@
     "            current = current[\"next\"]\n",
     "        current[\"next\"] = {\"data\": data, \"next\": None}\n",
     "\n",
-    "# Function to traverse and print the linked list\n",
     "def traverse():\n",
     "    current = linked_list\n",
     "    while current:\n",
@@ -871,13 +857,11 @@
     "        current = current[\"next\"]\n",
     "    print(\"None\")\n",
     "\n",
-    "# Append some data to the linked list\n",
     "append(1)\n",
     "append(2)\n",
     "append(3)\n",
     "\n",
-    "# Print the linked list\n",
-    "traverse()\n"
+    "traverse()"
    ]
   },
   {
@@ -973,14 +957,6 @@
     "list(map(lambda x : x * x, x))"
    ]
   },
-  {
-   "cell_type": "code",
-   "execution_count": null,
-   "id": "fb30b1ce",
-   "metadata": {},
-   "outputs": [],
-   "source": []
-  },
   {
    "cell_type": "code",
    "execution_count": 15,
@@ -1075,19 +1051,19 @@
   },
   {
    "cell_type": "code",
-   "execution_count": 34,
+   "execution_count": 17,
    "id": "601e1691",
    "metadata": {},
    "outputs": [
     {
-     "ename": "ValueError",
-     "evalue": "10 is not in list",
+     "ename": "NameError",
+     "evalue": "name 'L' is not defined",
      "output_type": "error",
      "traceback": [
       "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m",
-      "\u001b[0;31mValueError\u001b[0m                                Traceback (most recent call last)",
-      "Cell \u001b[0;32mIn[34], line 1\u001b[0m\n\u001b[0;32m----> 1\u001b[0m \u001b[43mL\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mindex\u001b[49m\u001b[43m(\u001b[49m\u001b[38;5;241;43m10\u001b[39;49m\u001b[43m)\u001b[49m\n",
-      "\u001b[0;31mValueError\u001b[0m: 10 is not in list"
+      "\u001b[0;31mNameError\u001b[0m                                 Traceback (most recent call last)",
+      "Cell \u001b[0;32mIn[17], line 1\u001b[0m\n\u001b[0;32m----> 1\u001b[0m \u001b[43mL\u001b[49m\u001b[38;5;241m.\u001b[39mindex(\u001b[38;5;241m10\u001b[39m)\n",
+      "\u001b[0;31mNameError\u001b[0m: name 'L' is not defined"
      ]
     }
    ],
diff --git a/04-05-06-programming-strategies.ipynb b/04-05-06-programming-strategies.ipynb
index f1d734f..4c0ca22 100644
--- a/04-05-06-programming-strategies.ipynb
+++ b/04-05-06-programming-strategies.ipynb
@@ -665,7 +665,7 @@
     "- Fibonacci Sequence\n",
     "- Rod Cutting\n",
     "- Sequence Alignment, Longest Subsequence Finding\n",
-    "- Shortest Path Findin"
+    "- Shortest Path Finding"
    ]
   },
   {
@@ -810,7 +810,7 @@
    "source": [
     "## Rod cutting \n",
     "\n",
-    "_Given a list of cuts and prices, identify the optimal cuts. Given the example below, what is the best cutting strategy for a rod of size 2?_\n",
+    "_Given a list of cuts and prices, identify the optimal cuts. Given the example below, what is the best cutting strategy for a rod of size `4`?_\n",
     "\n",
     "<img src=\"figures/rod-cutting.png\" style=\"width:500px\">"
    ]
@@ -828,9 +828,13 @@
   {
    "cell_type": "markdown",
    "id": "47119bfb",
-   "metadata": {},
+   "metadata": {
+    "slideshow": {
+     "slide_type": "fragment"
+    }
+   },
    "source": [
-    "Solution: $2$ with $5 + 5 = 10$."
+    "Solution: For a rod of size `4` optimal solution is 2 cuts of size 2 so $5 + 5 = 10$."
    ]
   },
   {
@@ -1037,7 +1041,7 @@
     "\n",
     "Now, we can calculate `V_3` using the values of `V_2` and `V_1`:\n",
     "\n",
-    "$$V_3 = \\max(p_1 + V_2, p_2 + V_1, p_3 + V_0) = \\max(2 + 5, 5 + 2, 9 + 0) = \\max(7, 7, 9) = 9$$"
+    "$$V_3 = \\max(p_1 + V_2, p_2 + V_1, p_3 + V_0) = \\max(1 + 5, 5 + 2, 9 + 0) = \\max(6, 7, 8) = 8$$"
    ]
   },
   {
@@ -1093,6 +1097,36 @@
     "    print(\"Max size cut \" + str(cutRod(arr, size)), len(arr) ) "
    ]
   },
+  {
+   "cell_type": "markdown",
+   "id": "c42683cc",
+   "metadata": {
+    "slideshow": {
+     "slide_type": "subslide"
+    }
+   },
+   "source": [
+    "## Change-making problem (dynamic programming)\n",
+    "\n",
+    "\n",
+    "$Q_{opt}(S,M) = min \\ \\sum_{i=1}^n x_i$.\n",
+    " \n",
+    "$S$: all the available coins\n",
+    " \n",
+    "$M$: amount\n",
+    " \n",
+    "$\n",
+    " Q_{opt}(i,m) = min\n",
+    "\\begin{cases}\n",
+    "  1 + Q_{opt}(i, m - v_i) \\quad si \\ (m - v_i) \\geq 0  \\qquad \\text{we use a coin of type $i$ of value $v_i$}\\\\\n",
+    "Q_{opt}(i-1, m) \\qquad \\quad    si \\ i \\geq 1 \\qquad \\qquad \\quad \\text{we do not use coin of type $i$, \n",
+    "we use $i-1$}\n",
+    "\\end{cases}\n",
+    "$\n",
+    "\n",
+    "<img src=\"figures/coins-changing.png\" style=\"width:500px\">\n"
+   ]
+  },
   {
    "cell_type": "markdown",
    "id": "fd3e3af7",
diff --git a/07-stacks-queues.ipynb b/07-stacks-queues.ipynb
index e41de91..740b4b6 100644
--- a/07-stacks-queues.ipynb
+++ b/07-stacks-queues.ipynb
@@ -13,9 +13,18 @@
     "## Lecture 7: Stacks and queues\n",
     "### Ecole Centrale de Lyon, Bachelor of Science in Data Science for Responsible Business\n",
     "#### Romain Vuillemot\n",
-    "<center><img  src=\"figures/Logo_ECL.png\" style=\"width:300px\"></center>\n",
-    "\n",
-    "\n",
+    "<center><img  src=\"figures/Logo_ECL.png\" style=\"width:300px\"></center>"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "id": "4dfe56e7",
+   "metadata": {
+    "slideshow": {
+     "slide_type": "skip"
+    }
+   },
+   "source": [
     "---"
    ]
   },
@@ -192,14 +201,20 @@
     }
    },
    "source": [
-    "### Stacks (using OOP)"
+    "### Stacks (using OOP)\n",
+    "\n",
+    "_Internally, will be based on an `Array` structure._"
    ]
   },
   {
    "cell_type": "code",
    "execution_count": 17,
    "id": "8ae9a611",
-   "metadata": {},
+   "metadata": {
+    "slideshow": {
+     "slide_type": "fragment"
+    }
+   },
    "outputs": [],
    "source": [
     "class Stack():\n",
diff --git a/exercises/01-data-structures-complexity-exercises.ipynb b/exercises/01-data-structures-complexity-exercises.ipynb
index 0be737d..50f1d8f 100644
--- a/exercises/01-data-structures-complexity-exercises.ipynb
+++ b/exercises/01-data-structures-complexity-exercises.ipynb
@@ -2,7 +2,7 @@
  "cells": [
   {
    "cell_type": "markdown",
-   "id": "59aef681",
+   "id": "fa46e55d",
    "metadata": {},
    "source": [
     "# UE5 Fundamentals of Algorithms\n",
@@ -23,7 +23,7 @@
   {
    "cell_type": "code",
    "execution_count": null,
-   "id": "88952ac5",
+   "id": "4c1206d1",
    "metadata": {},
    "outputs": [],
    "source": [
@@ -33,7 +33,7 @@
   },
   {
    "cell_type": "markdown",
-   "id": "b779c274",
+   "id": "6157338f",
    "metadata": {},
    "source": [
     "---"
diff --git a/exercises/02-recursion-exercises.ipynb b/exercises/02-recursion-exercises.ipynb
index 5f854e3..5d727a2 100644
--- a/exercises/02-recursion-exercises.ipynb
+++ b/exercises/02-recursion-exercises.ipynb
@@ -2,7 +2,7 @@
  "cells": [
   {
    "cell_type": "markdown",
-   "id": "a14c054e",
+   "id": "01d26f8d",
    "metadata": {},
    "source": [
     "# UE5 Fundamentals of Algorithms\n",
@@ -23,7 +23,7 @@
   {
    "cell_type": "code",
    "execution_count": null,
-   "id": "b13780a7",
+   "id": "a6f5bcf0",
    "metadata": {},
    "outputs": [],
    "source": [
@@ -33,7 +33,7 @@
   },
   {
    "cell_type": "markdown",
-   "id": "67ead887",
+   "id": "51dc6634",
    "metadata": {},
    "source": [
     "---"
diff --git a/exercises/03-lists-search-sort-exercises.ipynb b/exercises/03-lists-search-sort-exercises.ipynb
index 2ff5741..d64010d 100644
--- a/exercises/03-lists-search-sort-exercises.ipynb
+++ b/exercises/03-lists-search-sort-exercises.ipynb
@@ -2,7 +2,7 @@
  "cells": [
   {
    "cell_type": "markdown",
-   "id": "f8151910",
+   "id": "7989517f",
    "metadata": {},
    "source": [
     "# UE5 Fundamentals of Algorithms\n",
@@ -23,7 +23,7 @@
   {
    "cell_type": "code",
    "execution_count": null,
-   "id": "94c8f6d3",
+   "id": "c659f857",
    "metadata": {},
    "outputs": [],
    "source": [
@@ -33,7 +33,7 @@
   },
   {
    "cell_type": "markdown",
-   "id": "9e5bf33f",
+   "id": "a58b61ff",
    "metadata": {},
    "source": [
     "---"
diff --git a/exercises/04-05-06-programming-strategies-exercises.ipynb b/exercises/04-05-06-programming-strategies-exercises.ipynb
index e79716b..1a37afe 100644
--- a/exercises/04-05-06-programming-strategies-exercises.ipynb
+++ b/exercises/04-05-06-programming-strategies-exercises.ipynb
@@ -2,7 +2,7 @@
  "cells": [
   {
    "cell_type": "markdown",
-   "id": "8fa9ea2e",
+   "id": "c271b1aa",
    "metadata": {},
    "source": [
     "# UE5 Fundamentals of Algorithms\n",
@@ -23,7 +23,7 @@
   {
    "cell_type": "code",
    "execution_count": null,
-   "id": "6017bb23",
+   "id": "757d4143",
    "metadata": {},
    "outputs": [],
    "source": [
@@ -33,7 +33,7 @@
   },
   {
    "cell_type": "markdown",
-   "id": "7dd0e72c",
+   "id": "451d6862",
    "metadata": {},
    "source": [
     "---"
@@ -599,7 +599,7 @@
    },
    "outputs": [],
    "source": [
-    "intervals = [(1, 3), (2, 4), (3, 5), (5, 7), (6, 8)]"
+    "interval_scheduling([(0, 2), (2, 4), (1, 3)])"
    ]
   },
   {
@@ -611,7 +611,7 @@
     "editable": false,
     "nbgrader": {
      "cell_type": "code",
-     "checksum": "a1c5ab0cb1fbb052b5567e17549a9723",
+     "checksum": "d8a22346b92125746d141cee329408f1",
      "grade": true,
      "grade_id": "correct_interval_scheduling",
      "locked": true,
@@ -624,7 +624,19 @@
    },
    "outputs": [],
    "source": [
-    "assert interval_scheduling(intervals) == [(1, 3), (3, 5), (5, 7)]"
+    "assert interval_scheduling([(0, 2), (2, 4), (1, 3)]) == [(0, 2), (2, 4)]"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": null,
+   "id": "de2c9857-9925-4477-96e4-341fa5bc4ec8",
+   "metadata": {
+    "tags": []
+   },
+   "outputs": [],
+   "source": [
+    "assert interval_scheduling([(0, 2), (2, 4), (1,3)]) == [(0, 2), (2, 4)]"
    ]
   },
   {
@@ -741,7 +753,7 @@
     "deletable": false,
     "nbgrader": {
      "cell_type": "code",
-     "checksum": "4d258685229c335d689928bcd6c973ec",
+     "checksum": "959fdc68a051b0090f4ead159f3356df",
      "grade": false,
      "grade_id": "cell-0bf75b2bfe8e2e4c",
      "locked": false,
@@ -753,7 +765,7 @@
    },
    "outputs": [],
    "source": [
-    "def greedy_knapsack(W, wt):\n",
+    "def greedy_knapsack(W, w):\n",
     "    # YOUR CODE HERE\n",
     "    raise NotImplementedError()"
    ]
@@ -849,6 +861,52 @@
    "source": [
     "assert dynamic_knapsack(max_weight, weights) == (5, [3, 2])"
    ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": null,
+   "id": "ef953a29-7632-4475-8230-54a8a110d19a",
+   "metadata": {},
+   "outputs": [],
+   "source": []
+  },
+  {
+   "cell_type": "code",
+   "execution_count": null,
+   "id": "e7dd8b57-0d0d-43d0-b228-b9c994043f81",
+   "metadata": {},
+   "outputs": [],
+   "source": []
+  },
+  {
+   "cell_type": "code",
+   "execution_count": null,
+   "id": "a066e026-8a09-46ca-a919-53bc90c8a308",
+   "metadata": {
+    "tags": []
+   },
+   "outputs": [],
+   "source": []
+  },
+  {
+   "cell_type": "code",
+   "execution_count": null,
+   "id": "80c70549-29c1-49ff-a7de-f47dbce004a9",
+   "metadata": {
+    "tags": []
+   },
+   "outputs": [],
+   "source": [
+    "greedy_intevals([(0, 2), (2, 4), (1,3)])"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": null,
+   "id": "41e37d95-4e71-42f0-81dd-fd6122fc9023",
+   "metadata": {},
+   "outputs": [],
+   "source": []
   }
  ],
  "metadata": {
diff --git a/exercises/07-stacks-queues-exercises.ipynb b/exercises/07-stacks-queues-exercises.ipynb
new file mode 100644
index 0000000..cfbe210
--- /dev/null
+++ b/exercises/07-stacks-queues-exercises.ipynb
@@ -0,0 +1,444 @@
+{
+ "cells": [
+  {
+   "cell_type": "markdown",
+   "id": "49d0b44c",
+   "metadata": {},
+   "source": [
+    "# UE5 Fundamentals of Algorithms\n",
+    "## Exercices\n",
+    "### Ecole Centrale de Lyon, Bachelor of Science in Data Science for Responsible Business\n",
+    "#### [Romain Vuillemot](https://romain.vuillemot.net/)\n",
+    "\n",
+    "Before you turn this problem in:\n",
+    "- make sure everything runs as expected. \n",
+    "    - first, **restart the kernel** (in the menubar, select Kernel$\\rightarrow$Restart) \n",
+    "    - then **run all cells** (in the menubar, select Cell$\\rightarrow$Run All).\n",
+    "- make sure you fill in any place that says `YOUR CODE HERE` or \"YOUR ANSWER HERE\"\n",
+    "- remove `raise NotImplementedError()` to get started with your answer\n",
+    "- bonus points (at the end of this notebook) are optionals\n",
+    "- write your name (and collaborators as a list if any) below:"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": null,
+   "id": "6a884873",
+   "metadata": {},
+   "outputs": [],
+   "source": [
+    "ID = \"\"\n",
+    "COLLABORATORS_ID = []"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "id": "c7232915",
+   "metadata": {},
+   "source": [
+    "---"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "id": "2f1f2dcd-96a9-45ef-90a6-4ad488635679",
+   "metadata": {},
+   "source": [
+    "# Stacks and queues"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "id": "b9bd540c-dd15-49ac-bfbd-f2e758688a85",
+   "metadata": {
+    "tags": []
+   },
+   "source": [
+    "---"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "id": "03a0653e-65c2-4e79-9e83-31765cf19098",
+   "metadata": {},
+   "source": [
+    "## Exercise 1: Reverse a string using a Stack\n",
+    "\n",
+    "_Use the `Stack` below to reverse a string given as input._"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": null,
+   "id": "4932473d-2734-4e81-b777-ca10decfd9e8",
+   "metadata": {
+    "tags": []
+   },
+   "outputs": [],
+   "source": [
+    "class Stack:\n",
+    "    def __init__(self):\n",
+    "        self.items = []\n",
+    "\n",
+    "    def push(self, item):\n",
+    "        self.items.append(item)\n",
+    "\n",
+    "    def pop(self):\n",
+    "        if not self.is_empty():\n",
+    "            return self.items.pop()\n",
+    "\n",
+    "    def peek(self):\n",
+    "        if not self.is_empty():\n",
+    "            return self.items[-1]\n",
+    "\n",
+    "    def is_empty(self):\n",
+    "        return len(self.items) == 0"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": null,
+   "id": "8b77ae34-ef7c-4664-94e0-8928156f2224",
+   "metadata": {
+    "deletable": false,
+    "nbgrader": {
+     "cell_type": "code",
+     "checksum": "128a37273e0e5da052abe4bf08bb1c27",
+     "grade": false,
+     "grade_id": "cell-5b0828e97507162e",
+     "locked": false,
+     "schema_version": 3,
+     "solution": true,
+     "task": false
+    },
+    "tags": []
+   },
+   "outputs": [],
+   "source": [
+    "def reverse_string(s):\n",
+    "    # YOUR CODE HERE\n",
+    "    raise NotImplementedError()"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": null,
+   "id": "63719c8e-f60c-4544-8e41-cb6380ae4bcf",
+   "metadata": {
+    "tags": []
+   },
+   "outputs": [],
+   "source": [
+    "reverse_string(\"Hello\")"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": null,
+   "id": "81e93620-0664-4a9d-ba5f-894937c9769e",
+   "metadata": {
+    "tags": []
+   },
+   "outputs": [],
+   "source": [
+    "assert reverse_string(\"Hello\") == \"olleH\" "
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "id": "81df9b1e-cfe5-4b69-96a5-c8065259cc7d",
+   "metadata": {},
+   "source": [
+    "## Exercise 2: Check if a word is a palindrom (using a Stack)\n",
+    "_A palindrome is a sequence of characters that reads the same forward and backward._"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": null,
+   "id": "cf6fbdd5-53c5-45c2-a0c5-a5ed845c4f81",
+   "metadata": {
+    "deletable": false,
+    "nbgrader": {
+     "cell_type": "code",
+     "checksum": "048d788477e620bf78240329c0dd8771",
+     "grade": false,
+     "grade_id": "is_palindrome",
+     "locked": false,
+     "schema_version": 3,
+     "solution": true,
+     "task": false
+    },
+    "tags": []
+   },
+   "outputs": [],
+   "source": [
+    "def is_palindrome(s):\n",
+    "    # YOUR CODE HERE\n",
+    "    raise NotImplementedError()"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": null,
+   "id": "586bafba-2fbb-4833-b2e3-609db9b28fbf",
+   "metadata": {
+    "tags": []
+   },
+   "outputs": [],
+   "source": [
+    "is_palindrome(\"ABA\")"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": null,
+   "id": "d0005a10-9152-4aa5-a94b-fcbff1bd2281",
+   "metadata": {
+    "deletable": false,
+    "editable": false,
+    "nbgrader": {
+     "cell_type": "code",
+     "checksum": "4165b33ba9b75546b0edd15216e61e4f",
+     "grade": true,
+     "grade_id": "correct_is_palindrome",
+     "locked": true,
+     "points": 0,
+     "schema_version": 3,
+     "solution": false,
+     "task": false
+    },
+    "tags": []
+   },
+   "outputs": [],
+   "source": [
+    "assert is_palindrome(\"ABA\")"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "id": "f767bf25-9f4f-4a0d-8cb9-b729bbec5c27",
+   "metadata": {},
+   "source": [
+    "## Exercise 3: Implement a min-heap\n",
+    "\n",
+    "Use a `PriorityQueue` to return the smallest element when using `pop` of a stack (or a queue). "
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": null,
+   "id": "ddcccaf6-d235-4327-826f-7a62a4c23f28",
+   "metadata": {
+    "tags": []
+   },
+   "outputs": [],
+   "source": [
+    "from queue import PriorityQueue"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": null,
+   "id": "2da2db1e-f55d-43b4-877f-96ef944818e8",
+   "metadata": {
+    "tags": []
+   },
+   "outputs": [],
+   "source": [
+    "# how to use the modue\n",
+    "priority_queue = PriorityQueue()\n",
+    "priority_queue.put((3, 'apple'))\n",
+    "priority_queue.put((1, 'banana'))\n",
+    "priority_queue.put((2, 'cherry'))\n",
+    "element = priority_queue.get()\n",
+    "print(element)"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": null,
+   "id": "804ea32d-5bf8-42b9-ae52-6318b26f4065",
+   "metadata": {
+    "deletable": false,
+    "nbgrader": {
+     "cell_type": "code",
+     "checksum": "7f6b90fc037aa2a24fa9ce3b4dfca6dd",
+     "grade": false,
+     "grade_id": "cell-4b9a5ecdee87514e",
+     "locked": false,
+     "schema_version": 3,
+     "solution": true,
+     "task": false
+    },
+    "tags": []
+   },
+   "outputs": [],
+   "source": [
+    "# YOUR CODE HERE\n",
+    "raise NotImplementedError()"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": null,
+   "id": "1b2d28c4-277b-44fa-b7e8-590aa00f8f70",
+   "metadata": {
+    "tags": []
+   },
+   "outputs": [],
+   "source": [
+    "min_heap = MinHeap()\n",
+    "min_heap.insert(5)\n",
+    "min_heap.insert(3)\n",
+    "min_heap.insert(8)"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": null,
+   "id": "ed61bced-f000-41c6-8ecd-d669b4edb700",
+   "metadata": {
+    "tags": []
+   },
+   "outputs": [],
+   "source": [
+    "assert min_heap.pop() == 3\n",
+    "assert min_heap.peek() == 5\n",
+    "assert min_heap.peek() == 5"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "id": "a445d290-b04f-49b5-a8e7-2c6e259daf58",
+   "metadata": {
+    "tags": []
+   },
+   "source": [
+    "## Exercise 4: Evaluate a postfix expression\n",
+    "\n",
+    "_Write a code that given the following expression, provides the following evaluation (using arthmetic operations over numerical values)._\n",
+    "\n",
+    "Expression: `\"3 4 +\"`\n",
+    "Evaluation: `3 + 4 = 7`\n",
+    "\n",
+    "First step: write a function `apply_operator` that applies an operation (ie + - * /) over two elements."
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": null,
+   "id": "4cc7f805-0887-4422-b6b7-3d591d0df1fb",
+   "metadata": {
+    "deletable": false,
+    "nbgrader": {
+     "cell_type": "code",
+     "checksum": "eb88296bc1de3c5dd7c68059e0a071e8",
+     "grade": false,
+     "grade_id": "cell-8c5106f02f243455",
+     "locked": false,
+     "schema_version": 3,
+     "solution": true,
+     "task": false
+    },
+    "tags": []
+   },
+   "outputs": [],
+   "source": [
+    "def apply_operator(op, b, a):\n",
+    "# YOUR CODE HERE\n",
+    "raise NotImplementedError()"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "id": "e68bdf7c-ca08-4553-9874-8bd9038fd4b5",
+   "metadata": {},
+   "source": [
+    "Solution in pseudo-code:\n",
+    "- Split the input expression in to a list of tokens\n",
+    "- If not an operator\n",
+    "    - Add the value to the stack\n",
+    "- If an operator \n",
+    "    - Make sure there is enough parameters `a` and `b`\n",
+    "    - Pop `a` and `b`\n",
+    "    - Apply `apply_operator` on `a` and `b`\n",
+    "    - Store the result in the stack"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": null,
+   "id": "e792c90d-1b38-47f5-9879-399debc934b9",
+   "metadata": {
+    "deletable": false,
+    "nbgrader": {
+     "cell_type": "code",
+     "checksum": "73960d3c6b85c2efc0ad8e298e2649b7",
+     "grade": false,
+     "grade_id": "cell-e9236618b265b34f",
+     "locked": false,
+     "schema_version": 3,
+     "solution": true,
+     "task": false
+    },
+    "tags": []
+   },
+   "outputs": [],
+   "source": [
+    "def evaluate_postfix(expression):\n",
+    "# YOUR CODE HERE\n",
+    "raise NotImplementedError()"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": null,
+   "id": "ea6e4840-1b7e-4265-b37d-e8c45ea6b3ed",
+   "metadata": {
+    "tags": []
+   },
+   "outputs": [],
+   "source": [
+    "postfix_expression = \"3 4 + 2 *\"\n",
+    "result = evaluate_postfix(postfix_expression)\n",
+    "print(\"Result:\", result)"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": null,
+   "id": "0dc4dff8-089b-46a6-a08d-f53ee2fe72c3",
+   "metadata": {
+    "tags": []
+   },
+   "outputs": [],
+   "source": [
+    "assert evaluate_postfix(\"3 4 + 2 *\") == 14\n",
+    "assert evaluate_postfix(\"4 2 3 5 * + *\") == 68 # (4 * (2 + (3 * 5))\n",
+    "assert evaluate_postfix(\"8 4 / 6 2 * +\") == 14 # ((8 / 4) + (6 * 2))"
+   ]
+  }
+ ],
+ "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.10.9"
+  }
+ },
+ "nbformat": 4,
+ "nbformat_minor": 5
+}
diff --git a/solutions/04-05-06-programming-strategies-exercises.ipynb b/solutions/04-05-06-programming-strategies-exercises.ipynb
new file mode 100644
index 0000000..5bee7fa
--- /dev/null
+++ b/solutions/04-05-06-programming-strategies-exercises.ipynb
@@ -0,0 +1,1106 @@
+{
+ "cells": [
+  {
+   "cell_type": "markdown",
+   "id": "e58599e3-9ab7-4d43-bb22-aeccade424ce",
+   "metadata": {},
+   "source": [
+    "# Programming strategies"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "id": "691b3c38-0e83-4bb2-ac90-ef76d2dd9a7a",
+   "metadata": {},
+   "source": [
+    "---"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "id": "9d813205-b709-42ab-b414-6f3fc947022a",
+   "metadata": {},
+   "source": [
+    "## Exercise 1: tribonacci\n",
+    "\n",
+    "Here is an implementation of the Tribonacci sequence (similar to the Fibonacci) defined as:\n",
+    "\n",
+    "$T(n) = T(n-1) + T(n-2) + T(n-3)$\n",
+    "\n",
+    "_Explain the role of the `tab` variable; write some tests._"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 60,
+   "id": "f3b233ec-7077-479d-9c04-f1a4c35f3111",
+   "metadata": {
+    "tags": []
+   },
+   "outputs": [],
+   "source": [
+    "def tribonacci(n: int) -> int:\n",
+    "        \n",
+    "        if(n==0):\n",
+    "            return 0\n",
+    "        if(n==1):\n",
+    "            return 1\n",
+    "        if(n==2):\n",
+    "            return 1\n",
+    "        \n",
+    "        tab=[0 for i in range(n+1)]\n",
+    "        tab[0]=0\n",
+    "        tab[1]=1\n",
+    "        tab[2]=1\n",
+    "        \n",
+    "        for i in range(3, n+1):\n",
+    "            tab[i]=tab[i-1]+tab[i-2]+tab[i-3]\n",
+    "        \n",
+    "        return tab[n]"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 47,
+   "id": "f280eeea-4812-4a30-80b5-3fe1cafa9283",
+   "metadata": {
+    "tags": []
+   },
+   "outputs": [
+    {
+     "data": {
+      "text/plain": [
+       "274"
+      ]
+     },
+     "execution_count": 47,
+     "metadata": {},
+     "output_type": "execute_result"
+    }
+   ],
+   "source": [
+    "tribonacci(11)"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 48,
+   "id": "423d2637-8bd6-4e8f-95ff-2765dae5bce7",
+   "metadata": {
+    "nbgrader": {
+     "grade": false,
+     "grade_id": "cell-9e7356aa23ccfb4c",
+     "locked": false,
+     "schema_version": 3,
+     "solution": true,
+     "task": false
+    },
+    "tags": []
+   },
+   "outputs": [],
+   "source": [
+    "### BEGIN SOLUTION\n",
+    "assert tribonacci(0) == 0\n",
+    "assert tribonacci(1) == 1\n",
+    "assert tribonacci(2) == 1\n",
+    "assert tribonacci(11) == 274\n",
+    "### END SOLUTION"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "id": "b2b31dca-a19a-46cf-b0de-4feec6afa083",
+   "metadata": {},
+   "source": [
+    "## Exercice 2: find two numbers with a given sum\n",
+    "\n",
+    "_Find two numbers in an array `nums` that add up to a specific target value `target`. Return a list of the values index. Tip: make sure you do not use twice the same array element._"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 74,
+   "id": "f5a964df-958e-4758-8ca2-1139c59a7585",
+   "metadata": {
+    "nbgrader": {
+     "grade": false,
+     "grade_id": "two_sum",
+     "locked": false,
+     "schema_version": 3,
+     "solution": true,
+     "task": false
+    },
+    "tags": []
+   },
+   "outputs": [],
+   "source": [
+    "def two_sum(nums, target: int):\n",
+    "    ### BEGIN SOLUTION\n",
+    "    for i in range(len(nums)):\n",
+    "        for j in range(i+1,len(nums)):\n",
+    "            if(nums[i]+nums[j]==target):\n",
+    "                return([i,j])\n",
+    "    return -1\n",
+    "    ### END SOLUTION"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 75,
+   "id": "1cec37b0-5d27-4973-b53a-053a46992c0c",
+   "metadata": {
+    "tags": []
+   },
+   "outputs": [
+    {
+     "data": {
+      "text/plain": [
+       "[0, 2]"
+      ]
+     },
+     "execution_count": 75,
+     "metadata": {},
+     "output_type": "execute_result"
+    }
+   ],
+   "source": [
+    "two_sum([1, 2, 3, 4, 5], 4)"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 78,
+   "id": "395cb69f-b99a-4c60-88f5-11216a5ec857",
+   "metadata": {
+    "nbgrader": {
+     "grade": true,
+     "grade_id": "correct_two_sum",
+     "locked": true,
+     "points": 1,
+     "schema_version": 3,
+     "solution": false,
+     "task": false
+    },
+    "tags": []
+   },
+   "outputs": [],
+   "source": [
+    "assert two_sum([2, 7, 11, 15], 9) == [0, 1]  # 2 + 7 = 9\n",
+    "assert two_sum([3, 2, 4], 6) == [1, 2]       # 2 + 4 = 6\n",
+    "assert two_sum([3, 3], 6) == [0, 1]          # 3 + 3 = 6\n",
+    "assert two_sum([3, 3], 123) == -1            # not possible"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "id": "dc4f4361-5dee-4e19-b3fd-d18ea40d341e",
+   "metadata": {
+    "tags": []
+   },
+   "source": [
+    "## Exercice 3: find the minimum distance between two points\n",
+    "\n",
+    "_Given a list of points find the minimum distance between all the pairs of points._\n",
+    "\n",
+    "- write a `dist`function using \n",
+    "- define a `closest_point_naive`function using `math.inf`as initial value\n",
+    "\n",
+    "Tip: make sure you do not use the same point twice!"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 79,
+   "id": "f73f28a4-d39c-497d-9cbb-1c4edd1c628f",
+   "metadata": {
+    "tags": []
+   },
+   "outputs": [],
+   "source": [
+    "import math"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 81,
+   "id": "0be305c3-c054-4092-b041-bd7e705e2178",
+   "metadata": {
+    "nbgrader": {
+     "grade": false,
+     "grade_id": "cell-8738237c4c6682e4",
+     "locked": false,
+     "schema_version": 3,
+     "solution": true,
+     "task": false
+    },
+    "tags": []
+   },
+   "outputs": [],
+   "source": [
+    "def dist(point1, point2):\n",
+    "    ### BEGIN SOLUTION\n",
+    "    return math.sqrt((point1[0] - point2[0])**2 + (point1[1] - point2[1])**2)\n",
+    "    ### END SOLUTION"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 91,
+   "id": "c0e25948-eefd-4cb0-a893-c3d5e34ff0ee",
+   "metadata": {
+    "nbgrader": {
+     "grade": false,
+     "grade_id": "cell-9ca280911ed42034",
+     "locked": false,
+     "schema_version": 3,
+     "solution": true,
+     "task": false
+    },
+    "tags": []
+   },
+   "outputs": [],
+   "source": [
+    "def closest_point_naive(P):\n",
+    "    ### BEGIN SOLUTION\n",
+    "    min_dist = math.inf\n",
+    "    n = len(P)\n",
+    "    for i in range(n):\n",
+    "        for j in range(i + 1, n):\n",
+    "            if dist(P[i], P[j]) < min_dist:\n",
+    "                min_dist = dist(P[i], P[j])\n",
+    "    return min_dist\n",
+    "    ### END SOLUTION"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 92,
+   "id": "965d8274-470e-4a3e-8b88-60d458de74e2",
+   "metadata": {
+    "tags": []
+   },
+   "outputs": [
+    {
+     "data": {
+      "text/plain": [
+       "1.4142135623730951"
+      ]
+     },
+     "execution_count": 92,
+     "metadata": {},
+     "output_type": "execute_result"
+    }
+   ],
+   "source": [
+    "points = [(1, 2), (4, 6), (7, 8), (3, 5)]\n",
+    "closest_point_naive(points)"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 95,
+   "id": "5d875175-45c3-4594-a434-23e15cfb88f7",
+   "metadata": {
+    "nbgrader": {
+     "grade": true,
+     "grade_id": "cell-618f956021833284",
+     "locked": true,
+     "points": 1,
+     "schema_version": 3,
+     "solution": false,
+     "task": false
+    },
+    "tags": []
+   },
+   "outputs": [
+    {
+     "data": {
+      "text/plain": [
+       "0.0"
+      ]
+     },
+     "execution_count": 95,
+     "metadata": {},
+     "output_type": "execute_result"
+    }
+   ],
+   "source": [
+    "points1 = [(1, 2), (4, 6), (0, 0), (0, 0)]\n",
+    "closest_point_naive(points1)"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 96,
+   "id": "755116cb-456e-48ad-8dfe-bd72617488d9",
+   "metadata": {
+    "tags": []
+   },
+   "outputs": [],
+   "source": [
+    "assert math.isclose(closest_point_naive(points1), 0.0, rel_tol=1e-9)"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "id": "4d521622-f4b7-4859-b501-2583b943d0e7",
+   "metadata": {},
+   "source": [
+    "## Exercice 4: display the minimum distance\n",
+    "\n",
+    "_Update the previous function to take a single list of points `P`as input and return the closest points and draw the line that connects them._"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 97,
+   "id": "a5902565-9c98-482a-8e63-9cc37214beb2",
+   "metadata": {
+    "tags": []
+   },
+   "outputs": [],
+   "source": [
+    "from matplotlib import pyplot as plt\n",
+    "import random\n",
+    "\n",
+    "points_count = 10\n",
+    "x = [random.gauss(0, 1) for _ in range(points_count)]\n",
+    "y = [random.gauss(0, 1) for _ in range(points_count)]\n",
+    "\n",
+    "def draw_points(x, y):\n",
+    "    color = \"blue\"\n",
+    "    plt.figure(figsize=(10, 7))\n",
+    "    _ = plt.plot(x, y, '.', markersize=14, color=color)"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 98,
+   "id": "e35557a8-54cb-4324-b280-4479835685db",
+   "metadata": {
+    "tags": []
+   },
+   "outputs": [
+    {
+     "data": {
+      "image/png": "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WOKudEDFuasQAFANQ2mDAS6PBjh9R+8qBAAwWjmVDgAASJ4wAgAAkieMAACA5AkjAAAgecIIAABInjACAACSJ4wAAIDkCSMAACB5wggAABg2PT0RBw/mX8cSYQQAAJy29vaIlSsj6uoipkzJv65cmY+PBcIIAAA4LRs3RjQ2RmzYEFEu52Plcv68sTF/fbQTRgAAwClrb49obo44ciSiu7vva93d+Xhz8+g/ciSMAACAU7ZuXUSh0P+cQiGfN5oJIwAA4JT09OSnyR1/pOh43d35vCwbmXWdCmEEAACckkOHjl1TNJByOZ8/WgkjAADglEyaFFEsDm5usZjPH62EEQAAcEpqaiKamiJqa/ufV1ubzxvoWqRqEkYAAMApW7164GuHsiyfN5oJIwAA4JQtWBCxfn3EuHEnHjmqrc3H16/P541mwggAADgtTU0Rra0RN9987JqjYjF/3tqavz7aFbJsNN80b+i6urqiVCpFZ2dn1NfXV3s5AACQlJ6e/O5zdXXVv6ZoKG0wwGVSAAAAg1dTEzF5crVXMXROpQMAAJInjAAAgOQJIwAAIHnCCAAASJ4wAgAAkieMAACA5AkjAAAgecIIAABInjACAACSJ4wAAIDkCSMAACB5wggAAEieMAIAAJInjAAAgOQJIwAAIHnCCAAASJ4wAgAAkieMAACA5AkjAAAgecIIAABInjACAACSJ4wAAIDkCSMAACB5wggAAEieMAIAAJInjAAAgOQJIwAAIHnCCAAASJ4wAgAAkieMAACA5AkjAAAgecIIAABInjACAACSJ4wAAIDkCSMAACB5wggAAEieMAIAAJInjAAAgOQJIwAAIHnCCAAASJ4wAgAAkieMAACA5AkjAAAgecIIAABInjACAACSJ4wAAIDkCSMAACB5wggAAEieMAIAAJInjAAAgOQJIwAAIHnCCAAASJ4wAgAAkieMAACA5AkjAAAgecIIAABInjACAACSJ4wAAIDkCSMAACB5wggAAEieMAIAAJInjAAAgORVPIwefvjhmDt3bkycODEaGxvjxRdf/Mi527Zti0KhcMLjjTfeqPQyAQCAhFU0jJ566qlYvXp13HvvvdHW1hbLli2Lq666Knbv3t3v+958883Yu3dv7+MTn/hEJZcJAAAkrpBlWVapP/ySSy6Jiy66KB555JHesQsuuCCuu+66WLt27Qnzt23bFp/5zGfi/fffj7POOmtQ36NcLke5XO593tXVFbNnz47Ozs6or68/7Z8BAAAYm7q6uqJUKg2qDSp2xOjw4cPR2toay5cv7zO+fPny2LFjR7/vXbhwYcycOTMuv/zy2Lp1a79z165dG6VSqfcxe/bs0147AACQloqF0f79++PIkSMxY8aMPuMzZsyIjo6Ok75n5syZ8dhjj8WmTZvi6aefjnnz5sXll18eL7zwwkd+nzVr1kRnZ2fvY8+ePcP6cwAAAGe+2kp/g0Kh0Od5lmUnjB01b968mDdvXu/zJUuWxJ49e+J73/teXHrppSd9T7FYjGKxOHwLBgAAklOxI0bTpk2LcePGnXB0aN++fSccRerP4sWL46233hru5QEAAPSqWBhNmDAhGhsbY8uWLX3Gt2zZEkuXLh30n9PW1hYzZ84c7uUBAAD0quipdHfeeWc0NzfHokWLYsmSJfHYY4/F7t27Y9WqVRGRXx/0zjvvxE9+8pOIiFi3bl2cc8458clPfjIOHz4cGzZsiE2bNsWmTZsquUwAACBxFQ2jG264Id5777341re+FXv37o358+fHs88+G3PmzImIiL179/b5TKPDhw/HXXfdFe+8805MmjQpPvnJT8YzzzwTV199dSWXCQAAJK6in2NUDUO5VzkAAHDmGhWfYwQAADBWCCMAACB5wggAAEieMAIAAJInjAAAgOQJIwAAIHnCCAAASJ4wAgAAkieMAACA5AkjAAAgecIIAABInjACAACSJ4wAAIDkCSMAACB5wggAAEieMAIAAJInjAAAgOQJIwAAIHnCCAAASJ4wAgAAkieMAACA5AkjAAAgecIIAABInjACAACSJ4wAAIDkCSMAACB5wggAAEieMAIAAJInjAAAgOQJIwAAIHnCCAAASJ4wAgAAkieMAACA5AkjAAAgecIIAABInjACAACSJ4wAAIDkCSMAACB5wggAAEieMAIAAJInjAAAgOQJIwAAIHnCCAAASJ4wAgAAkieMAACA5AkjAAAgecIIAABInjACAACSJ4wAAIDkCSMAACB5wggAAEieMAIAAJInjAAAgOQJIwAAIHnCCAAASJ4wAgAAkieMAACA5AkjAAAgecIIAABInjACAACSJ4wAAIDkCSMAACB5wggAAEieMAIAAJInjAAAgOQJIwAAIHnCCAAASJ4wAgAAkieMAACA5AkjAAAgecIIAABInjACAACSJ4wAAIDkCSMAACB5wggAAEieMAIAAJInjAAAGBV6eiIOHsy/wkgTRgAAVFV7e8TKlRF1dRFTpuRfV67Mx2GkCCMAAKpm48aIxsaIDRsiyuV8rFzOnzc25q/DSBBGAABURXt7RHNzxJEjEd3dfV/r7s7Hm5sdOWJkCCMAAKpi3bqIQqH/OYVCPg8qTRgBADDienry0+SOP1J0vO7ufF6Wjcy6SJcwAgBgxB06dOyaooGUy/l8qCRhBADAiJs0KaJYHNzcYjGfD5UkjAAAGHE1NRFNTRG1tf3Pq63N5w10LRKcLmEEAEBVrF498LVDWZbPg0oTRgAAVMWCBRHr10eMG3fikaPa2nx8/fp8HlSaMAIAoGqamiJaWyNuvvnYNUfFYv68tTV/HUZCIcvOrJsfdnV1RalUis7Ozqivr6/2cgAAGKSenvzuc3V1rilieAylDQa43A0AAEZGTU3E5MnVXgWpciodAACQvIqH0cMPPxxz586NiRMnRmNjY7z44ov9zt++fXs0NjbGxIkT49xzz41HH3200ksEAAASV9Eweuqpp2L16tVx7733RltbWyxbtiyuuuqq2L1790nn79q1K66++upYtmxZtLW1xT333BO33357bNq0qZLLBAAAElfRmy9ccsklcdFFF8UjjzzSO3bBBRfEddddF2vXrj1h/te//vX42c9+Fq+//nrv2KpVq6K9vT1aWloG9T3dfAEAAIgYWhtU7IjR4cOHo7W1NZYvX95nfPny5bFjx46TvqelpeWE+VdccUW8/PLL8eGHH570PeVyObq6uvo8AAAAhqJiYbR///44cuRIzJgxo8/4jBkzoqOj46Tv6ejoOOn87u7u2L9//0nfs3bt2iiVSr2P2bNnD88PAAAAJKPiN18oHHcT+izLThgbaP7Jxo9as2ZNdHZ29j727NlzmisGAABSU7HPMZo2bVqMGzfuhKND+/btO+Go0FENDQ0nnV9bWxtnn332Sd9TLBajePRjkgEAAE5BxY4YTZgwIRobG2PLli19xrds2RJLly496XuWLFlywvznn38+Fi1aFOPHj6/UUgEAgMRV9FS6O++8M/71X/81fvSjH8Xrr78ed9xxR+zevTtWrVoVEflpcH/7t3/bO3/VqlXx9ttvx5133hmvv/56/OhHP4rHH3887rrrrkou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",
+      "text/plain": [
+       "<Figure size 1000x700 with 1 Axes>"
+      ]
+     },
+     "metadata": {},
+     "output_type": "display_data"
+    }
+   ],
+   "source": [
+    "draw_points(x, y)"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 99,
+   "id": "6c504c53-d3fc-44a1-904c-49ceff572638",
+   "metadata": {
+    "nbgrader": {
+     "grade": false,
+     "grade_id": "closest_point_naive_pair",
+     "locked": false,
+     "schema_version": 3,
+     "solution": true,
+     "task": false
+    },
+    "tags": []
+   },
+   "outputs": [],
+   "source": [
+    "def closest_point_naive_pair(P):\n",
+    "    ### BEGIN SOLUTION\n",
+    "    n = len(P)\n",
+    "    min_dist = math.inf\n",
+    "    closest_point1 = None\n",
+    "    closest_point2 = None\n",
+    "\n",
+    "    for i in range(n):\n",
+    "        for j in range(i + 1, n):\n",
+    "            distance = dist(P[i], P[j])\n",
+    "            if distance < min_dist:\n",
+    "                min_dist = distance\n",
+    "                closest_point1 = P[i]\n",
+    "                closest_point2 = P[j]\n",
+    "\n",
+    "    ### END SOLUTION\n",
+    "    return closest_point1, closest_point2"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 100,
+   "id": "4266685c-19f9-4d2f-bb71-4d047bb54787",
+   "metadata": {
+    "nbgrader": {
+     "grade": true,
+     "grade_id": "correct_closest_point_naive_pair",
+     "locked": true,
+     "points": 1,
+     "schema_version": 3,
+     "solution": false,
+     "task": false
+    },
+    "tags": []
+   },
+   "outputs": [
+    {
+     "data": {
+      "image/png": "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iieMAACA4gkjAACgeMIIAAAonjACAACKJ4wAAIDiCSMAAKB4wggAACieMAIAAIonjAAAgOIJIwAAoHjCCAAAKJ4wAgAAiieMAACA4gkjAACgeMIIAAAoXsPC6IknnkhHR0fa2trS1taWjo6OPPnkkwM+5oILLkhTU1O/2wknnNCoKQIAACRJWhr1jd/1rnflpz/9aW677bYkye///u+no6Mj//Iv/zLg404//fRcf/31fdvjxo1r1BQBAACSNCiMHnzwwdx222351re+leOPPz5J8jd/8zeZN29eHnroocyePfsFH9va2ppp06bt8c/q7u5Od3d333ZXV9fQJw4AABSpIW+lW7VqVdra2vqiKElOOOGEtLW15Z577hnwsStXrsyhhx6aI488MhdeeGEeffTRAcdfffXVfW/Xa2try8yZM/fJ7wAAAJSjIWG0adOmHHrooTvtP/TQQ7Np06YXfNwZZ5yRG2+8MV//+tfzsY99LPfdd1/e8IY39DsitKPLL788nZ2dfbcNGzbsk98BAAAox6DeSnfllVfmqquuGnDMfffdlyRpamra6b6qqna5/znnnntu338fffTROe644zJr1qzccsstefvb377Lx7S2tqa1tXVPpg8AALBLgwqjiy++OOedd96AYw4//PB85zvfyS9+8Yud7vvlL3+ZqVOn7vHPmz59embNmpWHH354MNMEGDa9vcmWLcmECUmzD0QAgAPGoMJoypQpmTJlym7HzZs3L52dnfn2t7+d3/7t306S3Hvvvens7MyJJ564xz/v8ccfz4YNGzJ9+vTBTBNgv1u3LlmyJFm2LOnuTlpbkwULksWLk7lzh3t2AMDuNOTvma985Stz+umn58ILL8y3vvWtfOtb38qFF16Ys846q98V6ebMmZMVK1YkSZ566qlcdtllWbVqVX784x9n5cqVectb3pIpU6bkd3/3dxsxTYB9YtmypL09ueGGOoqS+usNN9T7ly0b3vkBALvXsDd63HjjjXn1q1+d+fPnZ/78+XnNa16TpUuX9hvz0EMPpbOzM0kyZsyY/Pu//3ve9ra35cgjj8z555+fI488MqtWrcrBBx/cqGkC7JV165KOjmTbtqSnp/99PT31/o6OehwAMHI1VVVVDfck9qWurq60tbWls7MzkydPHu7pAKPcokX1kaEdo+j5WlqShQuT5312NQCM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HSl6josvAAAAxRNGAABA8YRRg7W2tuZ//+//ndbW1uGeyqhiXRvDujaGdW0ca9sY1rUxrGtjWNfGKW1tR93FFwAAAAbLESMAAKB4wggAACieMAIAAIonjAAAgOIJIwAAoHjCaC898cQT6ejoSFtbW9ra2tLR0ZEnn3xywMdccMEFaWpq6nc74YQT+o3p7u7O//gf/yNTpkzJpEmT8ta3vjU//elPG/ibjCyDXdetW7fmAx/4QF796ldn0qRJmTFjRt7znvfk5z//eb9xr3/963da+/POO6/Bv83w+sxnPpMjjjgi48ePT3t7e77xjW8MOP6uu+5Ke3t7xo8fn5e//OX53Oc+t9OY5cuX56ijjkpra2uOOuqorFixolHTH7EGs64333xzTjvttLz0pS/N5MmTM2/evHz1q1/tN+bzn//8Ts/Npqam/OpXv2r0rzKiDGZdV65cucs1+8EPftBvnOfr4NZ1V/9GNTU15VWvelXfGM/X5O67785b3vKWzJgxI01NTfnSl76028d4fd0zg11br7F7ZrDrWuJrrDDaS+9617uydu3a3Hbbbbntttuydu3adHR07PZxp59+ejZu3Nh3u/XWW/vdv3jx4qxYsSJf/OIX881vfjNPPfVUzjrrrGzbtq1Rv8qIMth1feaZZ/LAAw/kT/7kT/LAAw/k5ptvzg9/+MO89a1v3WnshRde2G/t//qv/7qRv8qwuummm7J48eJcccUVWbNmTU466aScccYZWb9+/S7HP/LIIznzzDNz0kknZc2aNfnQhz6USy65JMuXL+8bs2rVqpx77rnp6OjIunXr0tHRkXPOOSf33nvv/vq1ht1g1/Xuu+/OaaedlltvvTWrV6/O7/zO7+Qtb3lL1qxZ02/c5MmT+z03N27cmPHjx++PX2lEGOy6Puehhx7qt2aveMUr+u7zfB38un7iE5/ot54bNmzIIYcckne+8539xpX+fH366aczd+7cfOpTn9qj8V5f99xg19Zr7J4Z7Lo+p6jX2Ioh+/73v18lqb71rW/17Vu1alWVpPrBD37wgo87//zzq7e97W0veP+TTz5ZjR07tvriF7/Yt+9nP/tZ1dzcXN122237ZO4j2VDXdUff/va3qyTVT37yk759p5xySvU//+f/3JfTHdF++7d/u7rooov67ZszZ071wQ9+cJfj3//+91dz5szpt+8P/uAPqhNOOKFv+5xzzqlOP/30fmPe9KY3Veedd94+mvXIN9h13ZWjjjqquuqqq/q2r7/++qqtrW1fTfGANNh1vfPOO6sk1RNPPPGC39Pzde+frytWrKiampqqH//4x337PF/7S1KtWLFiwDFeX4dmT9Z2V7zGDmxP1rXE11hHjPbCqlWr0tbWluOPP75v3wknnJC2trbcc889Az525cqVOfTQQ3PkkUfmwgsvzKOPPtp33+rVq7N169bMnz+/b9+MGTNy9NFH7/b7jgZ7s67P19nZmaamprzoRS/qt//GG2/MlClT8qpXvSqXXXZZNm/evK+mPqI8++yzWb16db/nUZLMnz//Bddx1apVO41/05velPvvvz9bt24dcEwJz81kaOu6o97e3mzevDmHHHJIv/1PPfVUZs2alcMOOyxnnXXWTn/tHM32Zl2POeaYTJ8+PaeeemruvPPOfvd5vu798/Xaa6/NG9/4xsyaNavf/pKfr0Ph9XX/8Rq7b5X0GiuM9sKmTZty6KGH7rT/0EMPzaZNm17wcWeccUZuvPHGfP3rX8/HPvax3HfffXnDG96Q7u7uvu87bty4vPjFL+73uKlTpw74fUeLoa7r8/3qV7/KBz/4wbzrXe/K5MmT+/a/+93vzrJly7Jy5cr8yZ/8SZYvX563v/3t+2zuI8ljjz2Wbdu2ZerUqf32D/Q82rRp0y7H9/T05LHHHhtwTAnPzWRo67qjj33sY3n66adzzjnn9O2bM2dOPv/5z+fLX/5yli1blvHjx+e1r31tHn744X06/5FqKOs6ffr0XHPNNVm+fHluvvnmzJ49O6eeemruvvvuvjGer3v3fN24cWO+8pWv5Pd+7/f67S/9+ToUXl/3H6+x+0aJr7Etwz2BkejKK6/MVVddNeCY++67L0nS1NS0031VVe1y/3POPffcvv8++uijc9xxx2XWrFm55ZZbBvw/6bv7viNdo9f1OVu3bs15552X3t7efOYzn+l334UXXtj330cffXRe8YpX5LjjjssDDzyQY489dk9+jQPOjmu2u3Xc1fgd9w/2e45GQ12DZcuW5corr8w///M/9/sDwAknnNDvIiyvfe1rc+yxx+av/uqv8slPfnLfTXyEG8y6zp49O7Nnz+7bnjdvXjZs2JC//Mu/zMknnzyk7zlaDXUNPv/5z+dFL3pRzj777H77PV+Hxutr43mN3XdKfI0VRrtw8cUX7/ZKZYcffni+853v5Be/+MVO9/3yl7/cqZ4HMn369MyaNavvrxbTpk3Ls88+myeeeKLfUaNHH300J5544h5/35Fmf6zr1q1bc8455+SRRx7J17/+9X5Hi3bl2GOPzdixY/Pwww+PujCaMmVKxowZs9NfbR599NEXXMdp06btcnxLS0te8pKXDDhmMM/5A9lQ1vU5N910U9773vfmH//xH/PGN75xwLHNzc35rd/6rWL+mrk36/p8J5xwQm644Ya+bc/Xoa9rVVW57rrr0tHRkXHjxg04trTn61B4fW08r7GNN9pfY72VbhemTJmSOXPmDHgbP3585s2bl87Oznz729/ue+y9996bzs7OQQXM448/ng0bNmT69OlJkvb29owdOzZ33HFH35iNGzfmu9/97gEdRo1e1+ei6OGHH87Xvva1vn9oBvK9730vW7du7Vv70WTcuHFpb2/v9zxKkjvuuOMF13HevHk7jb/99ttz3HHHZezYsQOOOZCfm4MxlHVN6r9iXnDBBfnCF76QN7/5zbv9OVVVZe3ataPyubkrQ13XHa1Zs6bfmnm+Dn1d77rrrvzoRz/Ke9/73t3+nNKer0Ph9bWxvMbuH6P+NXa/X+5hlDn99NOr17zmNdWqVauqVatWVa9+9aurs846q9+Y2bNnVzfffHNVVVW1efPm6o//+I+re+65p3rkkUeqO++8s5o3b171a7/2a1VXV1ffYy666KLqsMMOq772ta9VDzzwQPWGN7yhmjt3btXT07Nff7/hMth13bp1a/XWt761Ouyww6q1a9dWGzdu7Lt1d3dXVVVVP/rRj6qrrrqquu+++6pHHnmkuuWWW6o5c+ZUxxxzzKhd1y9+8YvV2LFjq2uvvbb6/ve/Xy1evLiaNGlS39WlPvjBD1YdHR194//zP/+zmjhxYvW+972v+v73v19de+211dixY6t/+qd/6hvzb//2b9WYMWOqj370o9WDDz5YffSjH61aWlr6XUVwtBvsun7hC1+oWlpaqk9/+tP9nptPPvlk35grr7yyuu2226r/+I//qNasWVMtWrSoamlpqe699979/vsNl8Gu6//9v/+3WrFiRfXDH/6w+u53v1t98IMfrJJUy5cv7xvj+Tr4dX3OwoULq+OPP36X39Pztf73fM2aNdWaNWuqJNXHP/7xas2aNX1XQvX6OnSDXVuvsXtmsOta4musMNpLjz/+ePXud7+7Ovjgg6uDDz64eve7373TZQ2TVNdff31VVVX1zDPPVPPnz69e+tKXVmPHjq1e9rKXVeeff361fv36fo/ZsmVLdfHFF1eHHHJINWHChOqss87aacxoNth1feSRR6oku7zdeeedVVVV1fr166uTTz65OuSQQ6px48ZVv/7rv15dcskl1eOPP75/f7n97NOf/nQ1a9asaty4cdWxxx5b3XXXXX33nX/++dUpp5zSb/zKlSurY445pho3blx1+OGHV5/97Gd3+p7/+I//WM2ePbsaO3ZsNWfOnH4vkqUYzLqecsopu3xunn/++X1jFi9eXL3sZS+rxo0bV730pS+t5s+fX91zzz378TcaGQazrn/+539e/fqv/3o1fvz46sUvfnH1ute9rrrlllt2+p6er4N/HXjyySerCRMmVNdcc80uv5/n6/ZLGb/Q/669vg7dYNfWa+yeGey6lvga21RV/+/MPwAAgEI5xwgAACieMAIAAIonjAAAgOIJIwAAoHjCCAAAKJ4wAgAAiieMAACA4gkjAACgeMIIAAAonjACAACKJ4wAAIDi/f9G6OJAiKBZUQAAAABJRU5ErkJggg==",
+      "text/plain": [
+       "<Figure size 1000x700 with 1 Axes>"
+      ]
+     },
+     "metadata": {},
+     "output_type": "display_data"
+    }
+   ],
+   "source": [
+    "from matplotlib import pyplot as plt\n",
+    "import random\n",
+    "import math\n",
+    "\n",
+    "points_count = 10\n",
+    "color = \"blue\"\n",
+    "x = [random.gauss(0, 1) for _ in range(points_count)]\n",
+    "y = [random.gauss(0, 1) for _ in range(points_count)]\n",
+    "\n",
+    "points = list(zip(x, y))\n",
+    "\n",
+    "closest_point1, closest_point2 = closest_point_naive_pair(points)\n",
+    "\n",
+    "plt.figure(figsize=(10, 7))\n",
+    "_ = plt.plot(x, y, '.', markersize=14, color=color)\n",
+    "plt.plot([closest_point1[0], closest_point2[0]], [closest_point1[1], closest_point2[1]], '-', color='red', linewidth=2)\n",
+    "\n",
+    "plt.show()"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 103,
+   "id": "bcec1dfc-6ce9-4b08-bc1c-f8d0887aa876",
+   "metadata": {
+    "tags": []
+   },
+   "outputs": [
+    {
+     "data": {
+      "text/plain": [
+       "((0, 0), (1, 1))"
+      ]
+     },
+     "execution_count": 103,
+     "metadata": {},
+     "output_type": "execute_result"
+    }
+   ],
+   "source": [
+    "points1 = [(0, 0), (1, 1), (3, 3), (5, 5)]\n",
+    "closest_point_naive_pair(points1)"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 104,
+   "id": "aad82edd-144d-4117-9ee6-485b9e739251",
+   "metadata": {
+    "tags": []
+   },
+   "outputs": [],
+   "source": [
+    "assert closest_point_naive_pair(points1) == ((0, 0), (1, 1))"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "id": "52ede988-1834-489d-9cca-e9882e90f9af",
+   "metadata": {},
+   "source": [
+    "## Exercice 5: implement the merge sort\n",
+    "\n",
+    "0. Find a base case\n",
+    "1. Finding the mid of the array \n",
+    "2. Divide the array elements  into 2 halves \n",
+    "3. Sorting the first half and the second half independantly\n",
+    "4. merge by copying arrays into a final one"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 108,
+   "id": "b835049a-27a7-4d45-b819-b9e4d813fdcf",
+   "metadata": {
+    "nbgrader": {
+     "grade": false,
+     "grade_id": "merge_sort",
+     "locked": false,
+     "schema_version": 3,
+     "solution": true,
+     "task": false
+    },
+    "tags": []
+   },
+   "outputs": [],
+   "source": [
+    "def merge_sort(arr): \n",
+    "    ### BEGIN SOLUTION\n",
+    "    if len(arr) > 1: \n",
+    "        mid = len(arr) // 2 \n",
+    "        L = arr[:mid]\n",
+    "        R = arr[mid:]\n",
+    "  \n",
+    "        merge_sort(L) \n",
+    "        merge_sort(R)\n",
+    "  \n",
+    "        i = j = k = 0\n",
+    "    \n",
+    "        while i < len(L) and j < len(R): \n",
+    "            if L[i] < R[j]: \n",
+    "                arr[k] = L[i] \n",
+    "                i+=1\n",
+    "            else: \n",
+    "                arr[k] = R[j] \n",
+    "                j+=1\n",
+    "            k+=1\n",
+    "            \n",
+    "        while i < len(L): \n",
+    "            arr[k] = L[i] \n",
+    "            i+=1\n",
+    "            k+=1\n",
+    "          \n",
+    "        while j < len(R): \n",
+    "            arr[k] = R[j] \n",
+    "            j+=1\n",
+    "            k+=1\n",
+    "        \n",
+    "        return arr\n",
+    "    ### END SOLUTION"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 109,
+   "id": "4ad36fe3-7e9e-4ae8-9df6-f816e24d6c28",
+   "metadata": {
+    "tags": []
+   },
+   "outputs": [
+    {
+     "data": {
+      "text/plain": [
+       "[1, 3, 6]"
+      ]
+     },
+     "execution_count": 109,
+     "metadata": {},
+     "output_type": "execute_result"
+    }
+   ],
+   "source": [
+    "merge_sort([3, 6, 1])"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 110,
+   "id": "85865859-828f-4a6b-aad8-51ba0de8ac5b",
+   "metadata": {
+    "nbgrader": {
+     "grade": true,
+     "grade_id": "correct_merge_sort",
+     "locked": true,
+     "points": 1,
+     "schema_version": 3,
+     "solution": false,
+     "task": false
+    },
+    "tags": []
+   },
+   "outputs": [],
+   "source": [
+    "assert merge_sort([4, 2, 3]) == sorted([4, 2, 3])\n",
+    "assert merge_sort([7, 2, 1]) == [1, 2, 7]"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "id": "e5b7304d-7b64-42df-9465-8f4491525a8b",
+   "metadata": {},
+   "source": [
+    "# Exercice 6: organize a schedule\n",
+    "\n",
+    "_Propose a greedy algorithm that returns a list of time slots that do not overlap._\n",
+    "\n",
+    "In this question you may prioritize the ones that end last, so you may sort by [reverse order](https://docs.python.org/3/howto/sorting.html)."
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 175,
+   "id": "e0ed0841-1255-4bdb-b7f8-e689c2a953af",
+   "metadata": {
+    "nbgrader": {
+     "grade": false,
+     "grade_id": "interval_scheduling",
+     "locked": false,
+     "schema_version": 3,
+     "solution": true,
+     "task": false
+    },
+    "tags": []
+   },
+   "outputs": [],
+   "source": [
+    "def interval_scheduling(intervals):\n",
+    "    ### BEGIN SOLUTION\n",
+    "\n",
+    "    intervals.sort(key=lambda x: x[1], reverse=True)\n",
+    "    \n",
+    "    selected_intervals = []\n",
+    "    current_end_time = float('-inf')\n",
+    "    \n",
+    "    for interval in intervals:\n",
+    "        start_time, end_time = interval\n",
+    "        if start_time >= current_end_time:\n",
+    "            selected_intervals.append(interval)\n",
+    "            current_end_time = end_time\n",
+    "    return selected_intervals\n",
+    "    ### END SOLUTION"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 176,
+   "id": "d6a50280-f016-4686-8515-1b4a136c0fd9",
+   "metadata": {
+    "tags": []
+   },
+   "outputs": [
+    {
+     "data": {
+      "text/plain": [
+       "[(0, 2), (2, 4)]"
+      ]
+     },
+     "execution_count": 176,
+     "metadata": {},
+     "output_type": "execute_result"
+    }
+   ],
+   "source": [
+    "interval_scheduling([(0, 2), (2, 4), (1, 3)])"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 178,
+   "id": "bd38d673-077d-44b1-b81c-ac7448f5c01c",
+   "metadata": {
+    "nbgrader": {
+     "grade": true,
+     "grade_id": "correct_interval_scheduling",
+     "locked": true,
+     "points": 1,
+     "schema_version": 3,
+     "solution": false,
+     "task": false
+    },
+    "tags": []
+   },
+   "outputs": [],
+   "source": [
+    "assert interval_scheduling([(0, 2), (2, 4), (1, 3)]) == [(0, 2), (2, 4)]"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 179,
+   "id": "de2c9857-9925-4477-96e4-341fa5bc4ec8",
+   "metadata": {
+    "tags": []
+   },
+   "outputs": [],
+   "source": [
+    "assert interval_scheduling([(0, 2), (2, 4), (1,3)]) == [(0, 2), (2, 4)]"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "id": "c142c3b3-2f01-48d0-8596-601bb133542b",
+   "metadata": {
+    "tags": []
+   },
+   "source": [
+    "Now you may prioritize the ones that are the longest."
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 181,
+   "id": "095836b8-2612-4d58-a9ce-b7968489418c",
+   "metadata": {
+    "nbgrader": {
+     "grade": false,
+     "grade_id": "interval_scheduling_longest",
+     "locked": false,
+     "schema_version": 3,
+     "solution": true,
+     "task": false
+    },
+    "tags": []
+   },
+   "outputs": [],
+   "source": [
+    "def interval_scheduling_longest(intervals):\n",
+    "    ### BEGIN SOLUTION\n",
+    "    intervals.sort(key=lambda x: x[1] - x[0], reverse=True)\n",
+    "    \n",
+    "    selected_intervals = []\n",
+    "    current_end_time = float('-inf')\n",
+    "    \n",
+    "    for interval in intervals:\n",
+    "        start_time, end_time = interval\n",
+    "        if start_time >= current_end_time:\n",
+    "            selected_intervals.append(interval)\n",
+    "            current_end_time = end_time\n",
+    "    return selected_intervals\n",
+    "    ### END SOLUTION"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 182,
+   "id": "c87ae1e2-7497-4920-9597-d1b3cddf8580",
+   "metadata": {
+    "tags": []
+   },
+   "outputs": [
+    {
+     "data": {
+      "text/plain": [
+       "[(0, 4), (5, 7)]"
+      ]
+     },
+     "execution_count": 182,
+     "metadata": {},
+     "output_type": "execute_result"
+    }
+   ],
+   "source": [
+    "interval_scheduling_longest([(0, 4), (3, 5), (5, 7)])"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 183,
+   "id": "afcf3a69-aa36-4b71-93a8-218337ed88b9",
+   "metadata": {
+    "nbgrader": {
+     "grade": true,
+     "grade_id": "correct_interval_scheduling_longest",
+     "locked": true,
+     "points": 1,
+     "schema_version": 3,
+     "solution": false,
+     "task": false
+    },
+    "tags": []
+   },
+   "outputs": [],
+   "source": [
+    "assert interval_scheduling_longest([(0, 4), (3, 5), (5, 7)]) == [(0, 4), (5, 7)]"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "id": "a559e4db-9ef2-4d20-bb9f-cb638d8c1f24",
+   "metadata": {},
+   "source": [
+    "# Exercice 7: knapsack problem\n",
+    "\n",
+    "Propose a greedy solution for the Kanpsack problem defined as follows:\n",
+    "\n",
+    "$\\sum_{i=1}^n w_i x_i \\leq W$ and $x_i \\in \\{0,1,2,\\dots,c\\}$\n",
+    "\n",
+    "Which selects the item with the least weight that can fit within the knapsack's capacity at each step "
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "id": "5833bde3-1960-43ad-b140-381ac6dd228c",
+   "metadata": {},
+   "source": [
+    "`W:` The maximum weight capacity of the knapsack.\n",
+    "\n",
+    "`w:` A list of item weights.\n",
+    "\n",
+    "`n:` The number of items available to choose from.\n",
+    "\n",
+    "Tip:\n",
+    "\n",
+    "- Initialize with all the item indices of the remaining items\n",
+    "- Start with an empty knapsack of total weight 0\n",
+    "- Create a loop that selects the best item from the remaining (with least weight)\n",
+    "- Add the item to the knapsack and remove it from the list of items\n",
+    "- Return the total weight and list of items used"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 134,
+   "id": "46947633-3f5f-420b-b416-500a0dab4fcb",
+   "metadata": {
+    "nbgrader": {
+     "grade": false,
+     "grade_id": "cell-0bf75b2bfe8e2e4c",
+     "locked": false,
+     "schema_version": 3,
+     "solution": true,
+     "task": false
+    },
+    "tags": []
+   },
+   "outputs": [],
+   "source": [
+    "def greedy_knapsack(W, w):\n",
+    "    ### BEGIN SOLUTION\n",
+    "    w.sort(reverse=True)\n",
+    "    n = len(w)\n",
+    "    remaining_items = list(range(n))\n",
+    "\n",
+    "    total_weight = 0\n",
+    "    knapsack = []\n",
+    "\n",
+    "    while remaining_items and total_weight < W:\n",
+    "        best_weight = float('inf')\n",
+    "        best_item = None\n",
+    "\n",
+    "        for i in remaining_items:\n",
+    "            if w[i] < best_weight:\n",
+    "                best_weight = w[i]\n",
+    "                best_item = i\n",
+    "\n",
+    "        if best_item is not None:\n",
+    "            weight = w[best_item]\n",
+    "            knapsack.append(weight)\n",
+    "            total_weight += weight\n",
+    "            remaining_items.remove(best_item)\n",
+    "\n",
+    "    return total_weight, knapsack\n",
+    "    ### END SOLUTION"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 135,
+   "id": "737df134-4ee1-49a9-9034-da3b0267ae84",
+   "metadata": {
+    "tags": []
+   },
+   "outputs": [
+    {
+     "name": "stdout",
+     "output_type": "stream",
+     "text": [
+      "Total weight: 5 and selected weights: [2, 3]\n"
+     ]
+    }
+   ],
+   "source": [
+    "weights = [5, 3, 4, 2]\n",
+    "max_weight = 5\n",
+    "\n",
+    "result, selected_weights = greedy_knapsack(max_weight, weights)\n",
+    "print(\"Total weight:\", result, \"and selected weights:\", selected_weights)"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 136,
+   "id": "a66c6e52-2d60-4423-bc3a-a3dcef38da26",
+   "metadata": {
+    "tags": []
+   },
+   "outputs": [],
+   "source": [
+    "assert greedy_knapsack(5, [2, 3, 4, 5]) == (5, [2, 3])"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "id": "37ff64e9-fc2c-4593-b85a-d83982445b9d",
+   "metadata": {},
+   "source": [
+    "Propose a dynamic programming solution following the general case:\n",
+    "\n",
+    "$\n",
+    "dp[i][w] = \n",
+    "\\begin{cases}\n",
+    "0 & \\text{if } i = 0 \\text{ or } w = 0 \\\\\n",
+    "dp[i-1][w] & \\text{if } w_i > w \\\\\n",
+    "\\max(dp[i-1][w], w_i + dp[i-1][w - w_i]) & \\text{otherwise}\n",
+    "\\end{cases}$"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 137,
+   "id": "2be5f2f7-d9a5-4cf0-afe4-5a5a54ee0434",
+   "metadata": {
+    "nbgrader": {
+     "grade": false,
+     "grade_id": "cell-5dc5571a7aca5b0f",
+     "locked": false,
+     "schema_version": 3,
+     "solution": true,
+     "task": false
+    },
+    "tags": []
+   },
+   "outputs": [],
+   "source": [
+    "def dynamic_knapsack(W, wt):\n",
+    "    ### BEGIN SOLUTION\n",
+    "    n = len(wt)\n",
+    "\n",
+    "    dp = [[0 for _ in range(W + 1)] for _ in range(n + 1)]\n",
+    "\n",
+    "    for i in range(n + 1):\n",
+    "        for w in range(W + 1):\n",
+    "            if i == 0 or w == 0:\n",
+    "                dp[i][w] = 0\n",
+    "            elif wt[i - 1] <= w:\n",
+    "                dp[i][w] = max(wt[i - 1] + dp[i - 1][w - wt[i - 1]], dp[i - 1][w])\n",
+    "            else:\n",
+    "                dp[i][w] = dp[i - 1][w]\n",
+    "\n",
+    "    max_weight = dp[n][W]\n",
+    "\n",
+    "    selected_items = []\n",
+    "    w = W\n",
+    "    for i in range(n, 0, -1):\n",
+    "        if dp[i][w] != dp[i - 1][w]:\n",
+    "            selected_items.append(wt[i - 1])\n",
+    "            w -= wt[i - 1]\n",
+    "\n",
+    "    return max_weight, selected_items\n",
+    "    ### END SOLUTION"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 138,
+   "id": "5adf0e0e-73c4-4656-b546-5b02347f1a28",
+   "metadata": {},
+   "outputs": [
+    {
+     "name": "stdout",
+     "output_type": "stream",
+     "text": [
+      "Total weight: 5 and selected weights: [3, 2]\n"
+     ]
+    }
+   ],
+   "source": [
+    "weights = [2, 3, 4, 5]\n",
+    "max_weight = 5\n",
+    "result, selected_weights = dynamic_knapsack(max_weight, weights)\n",
+    "print(\"Total weight:\", result, \"and selected weights:\", selected_weights)"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 139,
+   "id": "935873d5-14ee-4b79-9e6a-c692d1c73a9a",
+   "metadata": {},
+   "outputs": [],
+   "source": [
+    "assert dynamic_knapsack(max_weight, weights) == (5, [3, 2])"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": null,
+   "id": "ef953a29-7632-4475-8230-54a8a110d19a",
+   "metadata": {},
+   "outputs": [],
+   "source": []
+  },
+  {
+   "cell_type": "code",
+   "execution_count": null,
+   "id": "e7dd8b57-0d0d-43d0-b228-b9c994043f81",
+   "metadata": {},
+   "outputs": [],
+   "source": []
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 155,
+   "id": "a066e026-8a09-46ca-a919-53bc90c8a308",
+   "metadata": {
+    "tags": []
+   },
+   "outputs": [],
+   "source": []
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 156,
+   "id": "80c70549-29c1-49ff-a7de-f47dbce004a9",
+   "metadata": {
+    "tags": []
+   },
+   "outputs": [
+    {
+     "data": {
+      "text/plain": [
+       "[(2, 4), (0, 2)]"
+      ]
+     },
+     "execution_count": 156,
+     "metadata": {},
+     "output_type": "execute_result"
+    }
+   ],
+   "source": [
+    "greedy_intevals([(0, 2), (2, 4), (1,3)])"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": null,
+   "id": "41e37d95-4e71-42f0-81dd-fd6122fc9023",
+   "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.10.9"
+  }
+ },
+ "nbformat": 4,
+ "nbformat_minor": 5
+}
-- 
GitLab