diff --git a/04-05-06-programming-strategies.ipynb b/04-05-06-programming-strategies.ipynb
new file mode 100644
index 0000000000000000000000000000000000000000..f1d734f362c05b95f6906995c1c4616a6889b547
--- /dev/null
+++ b/04-05-06-programming-strategies.ipynb
@@ -0,0 +1,1137 @@
+{
+ "cells": [
+  {
+   "cell_type": "markdown",
+   "id": "75778ca0",
+   "metadata": {
+    "slideshow": {
+     "slide_type": "slide"
+    }
+   },
+   "source": [
+    "# UE5 Fundamentals of Algorithms\n",
+    "## Lecture 4-5-6: Programming strategies\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": "f0c7488c",
+   "metadata": {
+    "slideshow": {
+     "slide_type": "subslide"
+    }
+   },
+   "source": [
+    "## Outline\n",
+    "- Definitions of programming strategies\n",
+    "- Divide and conquer\n",
+    "- Greedy algorithms\n",
+    "- Dynamic programming"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "id": "b3ce5394",
+   "metadata": {
+    "slideshow": {
+     "slide_type": "subslide"
+    }
+   },
+   "source": [
+    "# Programming strategies\n",
+    "\n",
+    "> A programming strategy are algorithms aimed at solving a specific problem in a precise manner.\n",
+    "\n",
+    "Examples of Strategies:\n",
+    "\n",
+    "- **Divide and Conquer:** Divide a problem into simpler sub-problems, solve the sub-problems, and then combine the solutions to solve the original problem.\n",
+    "\n",
+    "- **Dynamic Programming:** Solve a problem by breaking it down into sub-problems, calculating and memorizing the results of sub-problems to avoid unnecessary recomputation.\n",
+    "\n",
+    "- **Greedy Algorithm:** Make a series of choices that seem locally optimal at each step to find a solution, with the hope that the result will be globally optimal as well.\n",
+    "\n"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "id": "bd22ed47",
+   "metadata": {
+    "slideshow": {
+     "slide_type": "slide"
+    }
+   },
+   "source": [
+    "# Divide and conquer\n",
+    "\n",
+    "> The **Divide and Conquer** strategy involves breaking a complex problem into smaller, similar subproblems, solving them recursively, and then combining their solutions to address the original problem efficiently.\n",
+    "\n",
+    "1. **Divide:** Divide the original problem into subproblems of the same type.\n",
+    "\n",
+    "2. **Conquer:** Solve each of these subproblems recursively.\n",
+    "\n",
+    "3. **Combine:** Combine the answers appropriately.\n",
+    "\n",
+    "_It is very close to the recursive approach_\n"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "id": "d12319a6",
+   "metadata": {
+    "slideshow": {
+     "slide_type": "subslide"
+    }
+   },
+   "source": [
+    "\n",
+    "### Examples of divide and conquer algorithms:\n",
+    "\n",
+    "- Binary search\n",
+    "- Quick sort and merge sort\n",
+    "- Map Reduce\n",
+    "- Others: Fast multiplication (Karatsuba)"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "id": "fbb1b64c",
+   "metadata": {
+    "slideshow": {
+     "slide_type": "subslide"
+    }
+   },
+   "source": [
+    "## Binary search\n",
+    "\n",
+    "_Given a sorted list, find or insert a specific value while keeping the order._\n",
+    "\n",
+    "<img src=\"figures/recherche-dichotomique.png\" style=\"width:500px\">\n",
+    "\n",
+    "See [the notebook](03-lists-search-sort.ipynb)."
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "id": "bba7c4c6",
+   "metadata": {
+    "slideshow": {
+     "slide_type": "subslide"
+    }
+   },
+   "source": [
+    "## Quick sort\n",
+    "\n",
+    "Recursive sorting algorithm which works in two steps:\n",
+    "\n",
+    "1. select a pivot element \n",
+    "2. partitioning the array into smaller sub-arrays, then sorting those sub-arrays.\n",
+    "\n",
+    "<img src=\"figures/quicksort.png\" style=\"height:400px\">"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "id": "400d3619",
+   "metadata": {
+    "slideshow": {
+     "slide_type": "subslide"
+    }
+   },
+   "source": [
+    "## Merge sort\n",
+    "\n",
+    "Divide an array recursively into two halves (based on a _pivot_ value), sorting each half, and then merging the sorted halves back together. This process continues until the entire array is sorted.<br> Complexity: $O(n log(n))$.\n",
+    "\n",
+    "<img src=\"figures/tri-fusion.png\" style=\"width:500px\">"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "id": "7d33da6c",
+   "metadata": {
+    "slideshow": {
+     "slide_type": "subslide"
+    }
+   },
+   "source": [
+    "## Map reduce\n",
+    "\n",
+    "Divide a large dataset into smaller chunks and processes them independantly. Two main steps: \n",
+    "- the Map stage, where data is filtered and transformed into key-value pairs\n",
+    "- the Reduce stage, where data is aggregated and the final result is produced.\n",
+    "<img src=\"figures/Mapreduce.png\" style=\"width:700px\">"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "id": "a590fbe9",
+   "metadata": {
+    "slideshow": {
+     "slide_type": "subslide"
+    }
+   },
+   "source": [
+    "## Map reduce (without map reduce..)"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "id": "9f163e56",
+   "metadata": {},
+   "source": [
+    "_Calculate the sum of squares values from a list of numerical values._"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 49,
+   "id": "ba28ddd1",
+   "metadata": {},
+   "outputs": [],
+   "source": [
+    "data = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 60,
+   "id": "f34730fa",
+   "metadata": {
+    "slideshow": {
+     "slide_type": "fragment"
+    }
+   },
+   "outputs": [
+    {
+     "name": "stdout",
+     "output_type": "stream",
+     "text": [
+      "[(1, 1), (4, 2), (9, 3), (16, 4), (25, 5), (36, 6), (49, 7), (64, 8), (81, 9), (100, 10)]\n",
+      "385\n"
+     ]
+    }
+   ],
+   "source": [
+    "result = {}\n",
+    "for num in data:\n",
+    "    square = num * num\n",
+    "    result[square] = num\n",
+    "\n",
+    "final_result = list(result.items())\n",
+    "\n",
+    "print(final_result)\n",
+    "print(sum([x[0] for x in final_result]))"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "id": "261c7a2c",
+   "metadata": {
+    "slideshow": {
+     "slide_type": "subslide"
+    }
+   },
+   "source": [
+    "## Map reduce (Python)\n",
+    "\n",
+    "1. Divide the problem in sub-problems\n",
+    "2. Apply the mapping function\n",
+    "3. Reduce the results"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 69,
+   "id": "9ef9a5cc",
+   "metadata": {
+    "slideshow": {
+     "slide_type": "fragment"
+    }
+   },
+   "outputs": [
+    {
+     "name": "stdout",
+     "output_type": "stream",
+     "text": [
+      "385\n"
+     ]
+    }
+   ],
+   "source": [
+    "data = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]\n",
+    "\n",
+    "def mapper(numbers):\n",
+    "    result = []\n",
+    "    for num in numbers: # calculate the squares\n",
+    "        result.append((num, num * num))\n",
+    "    return result\n",
+    "\n",
+    "def reducer(pairs):\n",
+    "    result = {}\n",
+    "    for key, value in pairs: # sums the squares\n",
+    "        if key in result:\n",
+    "            result[key] += value \n",
+    "        else:\n",
+    "            result[key] = value\n",
+    "    return result.items()\n"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "id": "975a4b17",
+   "metadata": {
+    "slideshow": {
+     "slide_type": "subslide"
+    }
+   },
+   "source": [
+    "## Map reduce (Python)\n",
+    "\n",
+    "1. Divide the problem in sub-problems\n",
+    "2. Apply the mapping function\n",
+    "3. Reduce the results"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 5,
+   "id": "77215ac8",
+   "metadata": {},
+   "outputs": [
+    {
+     "ename": "NameError",
+     "evalue": "name 'data' is not defined",
+     "output_type": "error",
+     "traceback": [
+      "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m",
+      "\u001b[0;31mNameError\u001b[0m                                 Traceback (most recent call last)",
+      "Cell \u001b[0;32mIn[5], line 2\u001b[0m\n\u001b[1;32m      1\u001b[0m chunk_size \u001b[38;5;241m=\u001b[39m \u001b[38;5;241m2\u001b[39m\n\u001b[0;32m----> 2\u001b[0m chunks \u001b[38;5;241m=\u001b[39m [data[i:i\u001b[38;5;241m+\u001b[39mchunk_size] \u001b[38;5;28;01mfor\u001b[39;00m i \u001b[38;5;129;01min\u001b[39;00m \u001b[38;5;28mrange\u001b[39m(\u001b[38;5;241m0\u001b[39m, \u001b[38;5;28mlen\u001b[39m(\u001b[43mdata\u001b[49m), chunk_size)]\n\u001b[1;32m      4\u001b[0m mapped_data \u001b[38;5;241m=\u001b[39m [mapper(chunk) \u001b[38;5;28;01mfor\u001b[39;00m chunk \u001b[38;5;129;01min\u001b[39;00m chunks] \n\u001b[1;32m      6\u001b[0m grouped_data \u001b[38;5;241m=\u001b[39m {}\u001b[38;5;66;03m# map\u001b[39;00m\n",
+      "\u001b[0;31mNameError\u001b[0m: name 'data' is not defined"
+     ]
+    }
+   ],
+   "source": [
+    "\n",
+    "chunk_size = 2\n",
+    "chunks = [data[i:i+chunk_size] for i in range(0, len(data), chunk_size)]\n",
+    "\n",
+    "mapped_data = [mapper(chunk) for chunk in chunks] \n",
+    "\n",
+    "grouped_data = {}# map\n",
+    "for chunk in mapped_data:\n",
+    "    for key, value in chunk:\n",
+    "        if key in grouped_data:\n",
+    "            grouped_data[key].append(value)\n",
+    "        else:\n",
+    "            grouped_data[key] = [value]\n",
+    "\n",
+    "reduced_data = [reducer(list(grouped_data.items()))] # reduce\n",
+    "result = sum([x[1][0] for x in final_result])\n",
+    "\n",
+    "print(result)"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "id": "be8744c6",
+   "metadata": {
+    "slideshow": {
+     "slide_type": "subslide"
+    }
+   },
+   "source": [
+    "## Discussion on Divide and Conquer\n",
+    "\n",
+    "- Similarities with recursion by dividing a problem in a sub-problem\n",
+    "\n",
+    "- But with a combination step (which may hold most of the code difficulty)\n",
+    "\n",
+    "- Can be implemented in a non-recursive way\n",
+    "\n",
+    "- $n log(n)$ complexity when split the problem and solves each split"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "id": "c1f7b96a",
+   "metadata": {
+    "slideshow": {
+     "slide_type": "slide"
+    }
+   },
+   "source": [
+    "# Greedy algorithms\n",
+    "\n",
+    "> Algorithms that make a locally optimal choice.\n",
+    "\n",
+    "### Examples:\n",
+    "\n",
+    "- Change-making problem\n",
+    "- Knapsack problem\n",
+    "- Maze solving\n",
+    "- Graph coloring"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "id": "17867aaf",
+   "metadata": {
+    "slideshow": {
+     "slide_type": "subslide"
+    }
+   },
+   "source": [
+    "## Example: Change-making problem\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",
+    "Greedy solution:\n",
+    "\n",
+    "1. Sort the coins in descending order\n",
+    "\n",
+    "2. Initialize a variable to count coins used\n",
+    "\n",
+    "3. Substrack the number of coins used (if limited)\n",
+    "\n",
+    "4. Continue this process until amount becomes zero.\n"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "id": "adb8552d",
+   "metadata": {
+    "slideshow": {
+     "slide_type": "subslide"
+    }
+   },
+   "source": [
+    "## Example: Change-making problem (Python)\n",
+    "\n",
+    "_Greedy solution to return the minimal number of coins necessary._"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 82,
+   "id": "e900b357",
+   "metadata": {},
+   "outputs": [],
+   "source": [
+    "coins = [1, 2, 5]\n",
+    "amount = 11"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 83,
+   "id": "b4e91e95",
+   "metadata": {
+    "slideshow": {
+     "slide_type": "fragment"
+    }
+   },
+   "outputs": [],
+   "source": [
+    "def coin_change_greedy(coins, amount):\n",
+    "    coins.sort(reverse=True) # important! sort in descending order\n",
+    "    \n",
+    "    coin_count = 0\n",
+    "    remaining_amount = amount\n",
+    "    \n",
+    "    for coin in coins:\n",
+    "        while remaining_amount >= coin:\n",
+    "            remaining_amount -= coin\n",
+    "            coin_count += 1\n",
+    "    \n",
+    "    if remaining_amount == 0:\n",
+    "        return coin_count\n",
+    "    else:\n",
+    "        return -1"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 81,
+   "id": "131184bf",
+   "metadata": {},
+   "outputs": [
+    {
+     "name": "stdout",
+     "output_type": "stream",
+     "text": [
+      "3\n"
+     ]
+    }
+   ],
+   "source": [
+    "print(coin_change_greedy(coins, amount))  # 3 (11 = 5 + 5 + 1)"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "id": "3ab88980",
+   "metadata": {
+    "slideshow": {
+     "slide_type": "subslide"
+    }
+   },
+   "source": [
+    "## Example: Change-making problem (Python)\n",
+    "\n",
+    "_Greedy solution that returns the **list of coins** used._\n",
+    "\n",
+    "\n",
+    "Tip: use a list with the same structure as coins."
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 87,
+   "id": "9401818b",
+   "metadata": {
+    "slideshow": {
+     "slide_type": "fragment"
+    }
+   },
+   "outputs": [
+    {
+     "name": "stdout",
+     "output_type": "stream",
+     "text": [
+      "Minimum coins needed: 6\n",
+      "Coins used: [2, 1, 0, 3]\n"
+     ]
+    }
+   ],
+   "source": [
+    "def coin_change_greedy(coins, amount):\n",
+    "    coins.sort(reverse=True) \n",
+    "    \n",
+    "    coin_count = 0\n",
+    "    remaining_amount = amount\n",
+    "    used_coins = [0] * len(coins)\n",
+    "    \n",
+    "    for i, coin in enumerate(coins):\n",
+    "        while remaining_amount >= coin:\n",
+    "            remaining_amount -= coin\n",
+    "            coin_count += 1\n",
+    "            used_coins[i] += 1  \n",
+    "    \n",
+    "    if remaining_amount == 0:\n",
+    "        return coin_count, used_coins\n",
+    "    else:\n",
+    "        return -1, []\n",
+    "\n",
+    "coins = [25, 10, 5, 1]\n",
+    "amount = 63\n",
+    "min_coins, coins_used = coin_change_greedy(coins, amount)\n",
+    "\n",
+    "print(f\"Minimum coins needed: {min_coins}\")\n",
+    "print(\"Coins used:\", coins_used)"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "id": "1ae1863a",
+   "metadata": {
+    "slideshow": {
+     "slide_type": "subslide"
+    }
+   },
+   "source": [
+    "## Example: Change-making problem (Python)\n",
+    "\n",
+    "_Greedy solution that returns the **list of coins** used from **a limited availability of coins**._\n",
+    "\n",
+    "\n",
+    "Tip: use a list of coins availability of same structure as coins."
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 92,
+   "id": "8a936fe3",
+   "metadata": {},
+   "outputs": [],
+   "source": [
+    "coins = [25, 10, 5, 1]\n",
+    "amount = 63\n",
+    "coin_availability = [1, 2, 3, 4]"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 91,
+   "id": "1700c684",
+   "metadata": {
+    "slideshow": {
+     "slide_type": "fragment"
+    }
+   },
+   "outputs": [
+    {
+     "name": "stdout",
+     "output_type": "stream",
+     "text": [
+      "Minimum coins needed: 9\n",
+      "Coins used: [1, 2, 3, 3]\n"
+     ]
+    }
+   ],
+   "source": [
+    "def coin_change_greedy(coins, amount, coin_availability):\n",
+    "    coins.sort(reverse=True)\n",
+    "\n",
+    "    coin_count = 0\n",
+    "    remaining_amount = amount\n",
+    "    used_coins = [0] * len(coins)\n",
+    "    \n",
+    "    for i, coin in enumerate(coins):\n",
+    "        while remaining_amount >= coin and used_coins[i] < coin_availability[i]:\n",
+    "            remaining_amount -= coin\n",
+    "            coin_count += 1\n",
+    "            used_coins[i] += 1\n",
+    "    \n",
+    "    if remaining_amount == 0:\n",
+    "        return coin_count, used_coins\n",
+    "    else:\n",
+    "        return -1, []\n",
+    "\n",
+    "min_coins, coins_used = coin_change_greedy(coins, amount, coin_availability)\n",
+    "\n",
+    "\n",
+    "print(f\"Minimum coins needed: {min_coins}\")\n",
+    "print(\"Coins used:\", coins_used)"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "id": "7aeac877",
+   "metadata": {
+    "slideshow": {
+     "slide_type": "subslide"
+    }
+   },
+   "source": [
+    "## Discussion on Greedy algorithms\n",
+    "\n",
+    "- Often considered as an _heuristic_\n",
+    "- Easy to understand, implement and communicate\n",
+    "- They often lead to non-optimal solution"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "id": "5f36ec7b",
+   "metadata": {
+    "slideshow": {
+     "slide_type": "slide"
+    }
+   },
+   "source": [
+    "# Dynamic programming\n",
+    "\n",
+    "> **Dynamic programming** involves breaking down a problem into subproblems, *solving* these subproblems, and *combining* their solutions to obtain the solution to the original problem. The steps are as follows:\n",
+    "\n",
+    "1. Characterize the structure of an optimal solution.\n",
+    "2. Define the value of an optimal solution recursively.\n",
+    "3. Reconstruct the optimal solution from the computations.\n",
+    "\n",
+    "Notes :\n",
+    "- Applies to problems with optimal substructure.\n",
+    "- Also applies to problems where solutions are often interrelated (distinguishing it from divide and conquer).\n",
+    "- Utilizes a memoization approach, involving storing an intermediate solution (e.g., in a table).\n"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "id": "b125a618",
+   "metadata": {
+    "slideshow": {
+     "slide_type": "subslide"
+    }
+   },
+   "source": [
+    "### Examples of dynamic programming algorithms\n",
+    "\n",
+    "- Fibonacci Sequence\n",
+    "- Rod Cutting\n",
+    "- Sequence Alignment, Longest Subsequence Finding\n",
+    "- Shortest Path Findin"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "id": "3e3de7c4",
+   "metadata": {
+    "slideshow": {
+     "slide_type": "subslide"
+    }
+   },
+   "source": [
+    "## Fibonnacci  (reminder)\n",
+    "\n",
+    "To calculate the $n$-th number in the Fibonacci sequence, which is determined as follows:\n",
+    "\n",
+    "latex\n",
+    "Copy code\n",
+    "$fib(n) = fib(n-1) + fib(n-2)$, $n \\in \\mathbb{N}$\n",
+    "Where the sequence starts with 1, 1, and then continues as 2, 3, 5, 8, 13, 21, and so on, to find the 9th number ($n = 9$).\n",
+    "\n",
+    "Let's calculate the 9th Fibonacci number step by step:\n",
+    "\n",
+    "$fib(1) = 1$\n",
+    "\n",
+    "$fib(2) = 1$\n",
+    "\n",
+    "$fib(3) = fib(2) + fib(1) = 1 + 1 = 2$\n",
+    "\n"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "id": "cced97f7",
+   "metadata": {
+    "slideshow": {
+     "slide_type": "subslide"
+    }
+   },
+   "source": [
+    "## Fibonnacci  (naive)"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 4,
+   "id": "7bc7701a",
+   "metadata": {},
+   "outputs": [],
+   "source": [
+    "def fib(n):\n",
+    "    if n < 2:\n",
+    "        return n\n",
+    "    else:\n",
+    "        return fib(n - 1) + fib(n - 2)"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "id": "81eb2956",
+   "metadata": {},
+   "source": [
+    "Call tree (for $n = 6$):"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "id": "b588ca8b",
+   "metadata": {},
+   "source": [
+    "<img src=\"figures/fibonacci-tree.png\" style=\"width:400px\">"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "id": "42b6ecd1",
+   "metadata": {},
+   "source": [
+    "Requires to calculate the same F-value multiple times."
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "id": "fc74f400",
+   "metadata": {
+    "slideshow": {
+     "slide_type": "subslide"
+    }
+   },
+   "source": [
+    "## Fibonnacci (dynamic programming)\n",
+    "\n",
+    "_Optimized using a `lookup` table, which is a data structure to memoize values that have already been computed._"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 97,
+   "id": "9eae506b",
+   "metadata": {
+    "slideshow": {
+     "slide_type": "fragment"
+    }
+   },
+   "outputs": [
+    {
+     "name": "stdout",
+     "output_type": "stream",
+     "text": [
+      "6-th Fibonacci number is 8\n"
+     ]
+    }
+   ],
+   "source": [
+    "def fib(n, lookup):\n",
+    "    if n == 0 or n == 1:\n",
+    "        lookup[n] = n\n",
+    "\n",
+    "    if lookup[n] is None:\n",
+    "        lookup[n] = fib(n - 1, lookup) + fib(n - 2, lookup)\n",
+    "\n",
+    "    return lookup[n]\n",
+    "\n",
+    "def main():\n",
+    "    n = 6\n",
+    "\n",
+    "    lookup = [None] * (n + 1)\n",
+    "    result = fib(n, lookup)\n",
+    "    print(f\"{n}-th Fibonacci number is {result}\")\n",
+    "\n",
+    "if __name__==\"__main__\": \n",
+    "    main() "
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "id": "ac5e42aa",
+   "metadata": {
+    "slideshow": {
+     "slide_type": "subslide"
+    }
+   },
+   "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",
+    "\n",
+    "<img src=\"figures/rod-cutting.png\" style=\"width:500px\">"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "id": "2f933396",
+   "metadata": {},
+   "source": [
+    "| size (i) | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 |\n",
+    "|--------------|---|---|---|---|---|---|---|---|\n",
+    "| price (pi)    | 1 | 5 | 8 | 9 |10 |17 |17 |20 |\n"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "id": "47119bfb",
+   "metadata": {},
+   "source": [
+    "Solution: $2$ with $5 + 5 = 10$."
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "id": "61aa819a",
+   "metadata": {
+    "slideshow": {
+     "slide_type": "subslide"
+    }
+   },
+   "source": [
+    "## Rod cutting: check a solution\n",
+    "\n",
+    "Given the previous table of size and price, check the cost of a given solution by defining a function `check_rod_cutting(prices, n)`."
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 27,
+   "id": "c42b61d4",
+   "metadata": {
+    "slideshow": {
+     "slide_type": "fragment"
+    }
+   },
+   "outputs": [],
+   "source": [
+    "def check_rod_cutting(prices, n):\n",
+    "    table = [0] * (n + 1)\n",
+    "\n",
+    "    for i in range(1, n + 1):\n",
+    "        max_price = float('-inf')\n",
+    "        for j in range(1, i + 1):\n",
+    "            max_price = max(max_price, prices[j] + table[i - j])\n",
+    "        table[i] = max_price\n",
+    "\n",
+    "    return table[n]"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 30,
+   "id": "9a3bd3d3",
+   "metadata": {},
+   "outputs": [
+    {
+     "name": "stdout",
+     "output_type": "stream",
+     "text": [
+      "The maximum total price for a rod of length 2 is 5\n"
+     ]
+    }
+   ],
+   "source": [
+    "prices = [0, 1, 5, 8, 9, 10, 17, 17, 20]\n",
+    "n = 2\n",
+    "\n",
+    "max_total_price = check_rod_cutting(prices, n)\n",
+    "print(f\"The maximum total price for a rod of length {n} is {max_total_price}\")\n"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "id": "151c0a39",
+   "metadata": {
+    "slideshow": {
+     "slide_type": "subslide"
+    }
+   },
+   "source": [
+    "## Rod cutting (brute force)\n",
+    "\n",
+    "Let's solve the rod cutting problem using a brute force (naive) approach.\n",
+    "\n",
+    "1. define a value function\n",
+    "2. identify a base case\n",
+    "3. identify a recursion mechanism"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 33,
+   "id": "6e7a3a0d",
+   "metadata": {
+    "slideshow": {
+     "slide_type": "fragment"
+    }
+   },
+   "outputs": [],
+   "source": [
+    "def cut_brute_force(n, t):\n",
+    "    if n == 0:\n",
+    "        return 0\n",
+    "    max_valeur = float('-inf')\n",
+    "    for i in range(1, n + 1):\n",
+    "        valeur_courante = t[i] + coupe_brute_force(n - i, t)\n",
+    "        max_valeur = max(max_valeur, valeur_courante)\n",
+    "    return max_valeur"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 34,
+   "id": "1ee43707",
+   "metadata": {
+    "slideshow": {
+     "slide_type": "fragment"
+    }
+   },
+   "outputs": [
+    {
+     "name": "stdout",
+     "output_type": "stream",
+     "text": [
+      "The maximum value for a rod of length 2 is 5.\n"
+     ]
+    }
+   ],
+   "source": [
+    "lengths = [0, 1, 2, 3, 4, 5, 6, 7, 8]\n",
+    "values = [0, 1, 5, 8, 9, 10, 17, 17, 20]\n",
+    "rod_length = 2\n",
+    "max_value = coupe_brute_force(rod_length, values)\n",
+    "print(f\"The maximum value for a rod of length {rod_length} is {max_value}.\")"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "id": "1596f825",
+   "metadata": {
+    "slideshow": {
+     "slide_type": "subslide"
+    }
+   },
+   "source": [
+    "## Rod cutting (dynamic programming)\n",
+    "\n",
+    "\n",
+    "General case:\n",
+    "\n",
+    "- Cutting a rod of length $i$ optimally.\n",
+    "- Cutting a rod of length $(n - i)$ optimally.\n",
+    "\n",
+    "\n",
+    "<img src=\"figures/rod-cutting-tree.png\" style=\"width:500px\">\n",
+    "\n",
+    "General case: $V_{n} = max_{1 \\leq i \\leq n} (p_i + V_{n - i})$ "
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "id": "be5d9a15",
+   "metadata": {},
+   "source": [
+    "| size (i) | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 |\n",
+    "|--------------|---|---|---|---|---|---|---|---|\n",
+    "| price (pi)    | 1 | 5 | 8 | 9 |10 |17 |17 |20 |\n"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "id": "b2845bd5",
+   "metadata": {
+    "slideshow": {
+     "slide_type": "subslide"
+    }
+   },
+   "source": [
+    "$V_{3} = \\max_{1 \\leq i \\leq 3} (p_i + V_{3 - i})$\n",
+    "\n",
+    "Let's calculate `V_3` step by step for each possible value of `i`:\n",
+    "\n",
+    "1. If `i = 1`, we cut the rod into two pieces: one of length 1 and one of length 2.\n",
+    "   - $V_1 = p_1 = 2$\n",
+    "   - $V_{3 - 1} = V_2$\n",
+    "\n",
+    "2. If `i = 2`, we cut the rod into two pieces: one of length 2 and one of length 1.\n",
+    "   - $V_2 = p_2 = 5$\n",
+    "   - $V_{3 - 2} = V_1$\n",
+    "\n",
+    "3. If `i = 3`, we cut the rod into one piece of length 3.\n",
+    "   - $V_3 = p_3 = 9$\n",
+    "   - $V_{3 - 3} = V_0$ (Assuming that $V_0 = 0$ as a base case.)"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "id": "eb092761",
+   "metadata": {
+    "slideshow": {
+     "slide_type": "subslide"
+    }
+   },
+   "source": [
+    "Now, we can calculate the values for `V_2` and `V_1` recursively using the same formula:\n",
+    "\n",
+    "For `V_2`:\n",
+    "$$V_2 = \\max(p_1 + V_1, p_2 + V_0) = \\max(2 + V_1, 5 + 0) = \\max(2 + 2, 5 + 0) = \\max(4, 5) = 5$$\n",
+    "\n",
+    "For `V_1`:\n",
+    "$$V_1 = \\max(p_1 + V_0) = \\max(2 + 0) = 2$$\n",
+    "\n",
+    "So, `V_2` is 5 and `V_1` is 2.\n",
+    "\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$$"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "id": "0e097cbf",
+   "metadata": {
+    "slideshow": {
+     "slide_type": "subslide"
+    }
+   },
+   "source": [
+    "## Rod cutting (dynamic programming)"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 36,
+   "id": "5812781c",
+   "metadata": {
+    "slideshow": {
+     "slide_type": "fragment"
+    }
+   },
+   "outputs": [
+    {
+     "name": "stdout",
+     "output_type": "stream",
+     "text": [
+      "Max size cut 22 8\n"
+     ]
+    }
+   ],
+   "source": [
+    "INT_MIN = 0\n",
+    "\n",
+    "def cutRod(price, n): \n",
+    "\n",
+    "    # init cache tables\n",
+    "    val = [0 for x in range(n+1)] \n",
+    "    val[0] = 0\n",
+    "  \n",
+    "    for i in range(1, n+1): \n",
+    "        max_val = INT_MIN \n",
+    "        for j in range(i): \n",
+    "             max_val = max(max_val, price[j] + val[i-j-1]) \n",
+    "        val[i] = max_val \n",
+    "  \n",
+    "    return val[n] \n",
+    "  \n",
+    "if __name__==\"__main__\": \n",
+    "    arr = [1, 5, 8, 9, 10, 17, 17, 20] \n",
+    "    size = len(arr) \n",
+    "    print(\"Max size cut \" + str(cutRod(arr, size)), len(arr) ) "
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "id": "fd3e3af7",
+   "metadata": {
+    "slideshow": {
+     "slide_type": "subslide"
+    }
+   },
+   "source": [
+    "## Lessons on dynamic programming\n",
+    "\n",
+    "- It is necessary to study each problem on a case-by-case basis.\n",
+    "\n",
+    "- Storing a large number of partial results, which requires significant memory usage.\n",
+    "\n",
+    "- Suitable for only certain problems (min, max, counting the number of solutions).\n"
+   ]
+  }
+ ],
+ "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/07-stacks-queues.ipynb b/07-stacks-queues.ipynb
new file mode 100644
index 0000000000000000000000000000000000000000..e41de9135de4815f4639c2a95a4bb5861bfb8cf5
--- /dev/null
+++ b/07-stacks-queues.ipynb
@@ -0,0 +1,671 @@
+{
+ "cells": [
+  {
+   "cell_type": "markdown",
+   "id": "a4973a08",
+   "metadata": {
+    "slideshow": {
+     "slide_type": "slide"
+    }
+   },
+   "source": [
+    "# UE5 Fundamentals of Algorithms\n",
+    "## 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",
+    "---"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "id": "ffa36fea",
+   "metadata": {
+    "slideshow": {
+     "slide_type": "subslide"
+    }
+   },
+   "source": [
+    "## Outline\n",
+    "- Definitions\n",
+    "- Stacks\n",
+    "- Queues\n",
+    "- Priority queues"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "id": "cd2e76d7",
+   "metadata": {
+    "slideshow": {
+     "slide_type": "subslide"
+    }
+   },
+   "source": [
+    "## Defintions\n",
+    "\n",
+    "> Stacks and queues allow the manipulation of values (or objects) sequentially. They have many operations, the main ones are: addition (push) and removal (pop), but with different order strategies:\n",
+    "\n",
+    "<img src=\"figures/stacks-queues.png\" style=\"width:500px\">\n",
+    "\n",
+    "- `stacks` follow the Last-In, First-Out (LIFO) principle\n",
+    "- `queues`follows the First-In, First-Out (FIFO) principle\n",
+    "\n",
+    "Note that stacks and queues define the operations and their results, but not their implementation."
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "id": "cc2c4270",
+   "metadata": {
+    "slideshow": {
+     "slide_type": "subslide"
+    }
+   },
+   "source": [
+    "## Operations\n",
+    "\n",
+    "- `empty()`: Checks for emptiness.\n",
+    "- `full()`: Checks if it's full (if a maximum size was provided during creation).\n",
+    "- `get()`: Returns (and removes) an element.\n",
+    "- `push()`: Adds an element.\n",
+    "- `size()`: Returns the size of the list.\n",
+    "- `reverse()`: Reverses the order of elements.\n",
+    "- `peek()`: Returns an element (without removing it)."
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "id": "c0885103",
+   "metadata": {
+    "slideshow": {
+     "slide_type": "subslide"
+    }
+   },
+   "source": [
+    "### Stacks\n",
+    "\n",
+    "> A stack is an abstract data type that follows the Last-In, First-Out (LIFO) principle\n",
+    "\n",
+    "- It supports operations on a collection of elements.\n",
+    "- The element inserted last is at the _head_.\n",
+    "- Easily achievable with a simple list! See this [Python tutorial](https://docs.python.org/3/tutorial/datastructures.html)"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "id": "363737b7",
+   "metadata": {
+    "slideshow": {
+     "slide_type": "subslide"
+    }
+   },
+   "source": [
+    "### Stacks (using lists)"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 39,
+   "id": "6326e146",
+   "metadata": {},
+   "outputs": [],
+   "source": [
+    "stack = [3, 4, 5]\n",
+    "stack.append(6) # push\n",
+    "stack.append(7)"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 40,
+   "id": "6604a331",
+   "metadata": {},
+   "outputs": [
+    {
+     "name": "stdout",
+     "output_type": "stream",
+     "text": [
+      "[3, 4, 5, 6, 7]\n",
+      "[3, 4, 5, 6]\n",
+      "[3, 4]\n",
+      "4\n"
+     ]
+    }
+   ],
+   "source": [
+    "print(stack)\n",
+    "stack.pop() # get\n",
+    "print(stack)\n",
+    "stack.pop()\n",
+    "stack.pop()\n",
+    "print(stack)\n",
+    "print(stack[-1]) # peek"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "id": "075dc32b",
+   "metadata": {
+    "slideshow": {
+     "slide_type": "subslide"
+    }
+   },
+   "source": [
+    "### Stacks (using modules)\n",
+    "\n",
+    "https://docs.python.org/3/library/queue.html"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 41,
+   "id": "b467ca83",
+   "metadata": {},
+   "outputs": [
+    {
+     "name": "stdout",
+     "output_type": "stream",
+     "text": [
+      "4 3 2 1 0 "
+     ]
+    }
+   ],
+   "source": [
+    "import queue\n",
+    "pile = queue.LifoQueue()\n",
+    "\n",
+    "for i in range(5): pile.put(i)\n",
+    "\n",
+    "while not pile.empty(): \n",
+    "  print(pile.get(), end=\" \")"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "id": "697d2be8",
+   "metadata": {
+    "slideshow": {
+     "slide_type": "subslide"
+    }
+   },
+   "source": [
+    "### Stacks (using OOP)"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 17,
+   "id": "8ae9a611",
+   "metadata": {},
+   "outputs": [],
+   "source": [
+    "class Stack():\n",
+    "    def __init__(self, values = []):\n",
+    "        self.__values = []\n",
+    "        for v in values:\n",
+    "            self.push(v)\n",
+    "\n",
+    "    def push(self, v):\n",
+    "        self.__values.append(v)\n",
+    "        return v\n",
+    "\n",
+    "    def get(self):\n",
+    "        v = self.__values.pop()\n",
+    "        return v\n",
+    "\n",
+    "    def display(self):\n",
+    "        for v in self.__values:\n",
+    "            print(v)\n",
+    "\n",
+    "    def size(self):\n",
+    "        return len(self.__values)"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "id": "a0901fcb",
+   "metadata": {
+    "slideshow": {
+     "slide_type": "subslide"
+    }
+   },
+   "source": [
+    "### Stacks (using OOP)"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 42,
+   "id": "c61545dc",
+   "metadata": {},
+   "outputs": [
+    {
+     "name": "stdout",
+     "output_type": "stream",
+     "text": [
+      "A\n",
+      "B\n",
+      "C\n"
+     ]
+    }
+   ],
+   "source": [
+    "data = [\"A\", \"B\", \"C\"]\n",
+    "\n",
+    "s = Stack()\n",
+    "for d in data:\n",
+    "    s.push(d)\n",
+    "    e = s.pop()\n",
+    "    print(e)"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "id": "9145ef5e",
+   "metadata": {
+    "slideshow": {
+     "slide_type": "subslide"
+    }
+   },
+   "source": [
+    "## Queues\n",
+    "\n",
+    "> A stack is an abstract data type that follows the First-In, First-Out (FIFO) principle\n",
+    "\n",
+    "- Similar to a Srtack\n",
+    "- But the returned element is the first one inserted"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "id": "724ac3b7",
+   "metadata": {
+    "slideshow": {
+     "slide_type": "subslide"
+    }
+   },
+   "source": [
+    "## Queues (list)"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 44,
+   "id": "b2cc2dd0",
+   "metadata": {},
+   "outputs": [],
+   "source": [
+    "queue = [3, 4, 5]\n",
+    "queue.append(6)\n",
+    "queue.append(7) # push"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 45,
+   "id": "1157237e",
+   "metadata": {},
+   "outputs": [
+    {
+     "name": "stdout",
+     "output_type": "stream",
+     "text": [
+      "[3, 4, 5, 6, 7]\n",
+      "[4, 5, 6, 7]\n",
+      "[6, 7]\n",
+      "6\n"
+     ]
+    }
+   ],
+   "source": [
+    "print(queue) \n",
+    "queue.pop(0) # get\n",
+    "print(queue)\n",
+    "queue.pop(0)\n",
+    "queue.pop(0)\n",
+    "print(queue)\n",
+    "print(queue[0]) # peek"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "id": "78d3504a",
+   "metadata": {
+    "slideshow": {
+     "slide_type": "subslide"
+    }
+   },
+   "source": [
+    "## Queues (module)"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 33,
+   "id": "a6392890",
+   "metadata": {},
+   "outputs": [
+    {
+     "name": "stdout",
+     "output_type": "stream",
+     "text": [
+      "0 1 2 3 4 "
+     ]
+    }
+   ],
+   "source": [
+    "import queue\n",
+    "\n",
+    "q = queue.Queue()\n",
+    "\n",
+    "for i in range (5): q.put(i)\n",
+    "\n",
+    "while not q.empty(): \n",
+    "    print(q.get(), end=\" \")"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "id": "c2269f3b",
+   "metadata": {
+    "slideshow": {
+     "slide_type": "subslide"
+    }
+   },
+   "source": [
+    "## Priority queues\n",
+    "\n",
+    "> A **priority queue** is a queue (or stack or list) that returns an element based on the characteristics of a variable (priority).\n",
+    "\n",
+    "- For a quantitative variable, it's the minimum or maximum of the queue. For other types of variables (e.g., categories), any order relation is valid.\n",
+    "\n",
+    "- Queues can exhibit the same behavior but have a different internal state: either constantly updated or updated after reads/writes.\n",
+    "\n",
+    "- The internal state can be preserved with a sorting function, thus optimizing the complexity of the data structure.\n"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "id": "a46609ab",
+   "metadata": {
+    "slideshow": {
+     "slide_type": "subslide"
+    }
+   },
+   "source": [
+    "## Priority queues (module)\n"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 46,
+   "id": "6a31eba0",
+   "metadata": {},
+   "outputs": [],
+   "source": [
+    "from heapq import heapify, heappush, heappop\n",
+    "heap = [10, 8, 1, 2, 4, 9, 3, 4, 7]\n",
+    "heapify(heap)"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 47,
+   "id": "0fbe9868",
+   "metadata": {},
+   "outputs": [
+    {
+     "data": {
+      "text/plain": [
+       "[1, 2, 3, 4, 4, 9, 10, 8, 7]"
+      ]
+     },
+     "execution_count": 47,
+     "metadata": {},
+     "output_type": "execute_result"
+    }
+   ],
+   "source": [
+    "heap"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 48,
+   "id": "c72a1070",
+   "metadata": {},
+   "outputs": [
+    {
+     "data": {
+      "text/plain": [
+       "1"
+      ]
+     },
+     "execution_count": 48,
+     "metadata": {},
+     "output_type": "execute_result"
+    }
+   ],
+   "source": [
+    "heappop(heap)"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 49,
+   "id": "be80320d",
+   "metadata": {},
+   "outputs": [
+    {
+     "data": {
+      "text/plain": [
+       "[2, 4, 3, 4, 7, 9, 10, 8]"
+      ]
+     },
+     "execution_count": 49,
+     "metadata": {},
+     "output_type": "execute_result"
+    }
+   ],
+   "source": [
+    "heap"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 50,
+   "id": "2aa86e2e",
+   "metadata": {},
+   "outputs": [],
+   "source": [
+    "heappush(heap, 5)"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 51,
+   "id": "5d5f290a",
+   "metadata": {},
+   "outputs": [
+    {
+     "data": {
+      "text/plain": [
+       "[2, 4, 3, 4, 7, 9, 10, 8, 5]"
+      ]
+     },
+     "execution_count": 51,
+     "metadata": {},
+     "output_type": "execute_result"
+    }
+   ],
+   "source": [
+    "heap"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "id": "b841cc1f",
+   "metadata": {
+    "slideshow": {
+     "slide_type": "subslide"
+    }
+   },
+   "source": [
+    "## Priority queues (using OOP)"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 56,
+   "id": "e34b0c73",
+   "metadata": {},
+   "outputs": [],
+   "source": [
+    "class PriorityQueue(object): \n",
+    "    def __init__(self): \n",
+    "        self.__queue = [] \n",
+    "  \n",
+    "    def __str__(self): \n",
+    "        return ' '.join([str(i) for i in self.__queue]) \n",
+    "  \n",
+    "    def isEmpty(self): \n",
+    "        return len(self.__queue) == 0\n",
+    "  \n",
+    "    def insert(self, data): \n",
+    "        self.__queue.append(data) \n",
+    "       \n",
+    "    def size(self): \n",
+    "        return len(self.__queue)\n",
+    "\n",
+    "    def delete(self): \n",
+    "        min = 0\n",
+    "        for i in range(0,len(self.__queue)): \n",
+    "            if self.__queue[i][2] < self.__queue[min][2]: \n",
+    "                min = i \n",
+    "        item = self.__queue[min] \n",
+    "        del self.__queue[min] \n",
+    "        return item \n"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 60,
+   "id": "0e326166",
+   "metadata": {
+    "slideshow": {
+     "slide_type": "subslide"
+    }
+   },
+   "outputs": [
+    {
+     "name": "stdout",
+     "output_type": "stream",
+     "text": [
+      "1\n",
+      "7\n",
+      "12\n",
+      "14\n"
+     ]
+    }
+   ],
+   "source": [
+    "import queue\n",
+    "\n",
+    "myQueue = queue.PriorityQueue()\n",
+    "\n",
+    "# Insert elements into the priority queue\n",
+    "myQueue.put(12)\n",
+    "myQueue.put(1)\n",
+    "myQueue.put(14)\n",
+    "myQueue.put(7)\n",
+    "\n",
+    "# Print the contents of the priority queue\n",
+    "while not myQueue.empty():\n",
+    "    print(myQueue.get())"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "id": "01f5f437",
+   "metadata": {
+    "slideshow": {
+     "slide_type": "subslide"
+    }
+   },
+   "source": [
+    " ## Improvements\n",
+    "\n",
+    "- Handle empty lists"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": null,
+   "id": "5aa5a7ad",
+   "metadata": {},
+   "outputs": [],
+   "source": [
+    "\n",
+    "def dequeue(self):\n",
+    "    if not self.is_empty():\n",
+    "        return self.items.pop(0)\n",
+    "    else:\n",
+    "        raise IndexError(\"Queue is empty\")\n",
+    "            "
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": null,
+   "id": "89407366",
+   "metadata": {},
+   "outputs": [],
+   "source": [
+    "import queue\n",
+    "q = queue.Queue(5000)\n",
+    "# q.put([1,2,3,4])\n",
+    "q.put([2,3,4,5])\n",
+    "try:\n",
+    "    [x1, x2, x3, x4] = q.get(block=True)\n",
+    "except queue.Empty:\n",
+    "    print(\"Problème : aucun élément dans la file\")\n",
+    "else:\n",
+    "    print([x1, x2, x3, x4])\n",
+    "\n"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": null,
+   "id": "1bf32fdb",
+   "metadata": {},
+   "outputs": [],
+   "source": []
+  }
+ ],
+ "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
+}