diff --git a/02-recursion-exercices.ipynb b/02-recursion-exercices.ipynb
deleted file mode 100644
index 0ae7ffe7e33d32b044afb7e260e7b1afc2b9b742..0000000000000000000000000000000000000000
--- a/02-recursion-exercices.ipynb
+++ /dev/null
@@ -1,1145 +0,0 @@
-{
- "cells": [
-  {
-   "cell_type": "markdown",
-   "id": "bca30313",
-   "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": "6f6a3d43",
-   "metadata": {},
-   "outputs": [],
-   "source": [
-    "ID = \"\"\n",
-    "COLLABORATORS_ID = []"
-   ]
-  },
-  {
-   "cell_type": "markdown",
-   "id": "c5b97c1c",
-   "metadata": {},
-   "source": [
-    "---"
-   ]
-  },
-  {
-   "cell_type": "markdown",
-   "id": "a4e4fad3",
-   "metadata": {
-    "slideshow": {
-     "slide_type": "slide"
-    }
-   },
-   "source": [
-    "# Recursion"
-   ]
-  },
-  {
-   "cell_type": "markdown",
-   "id": "a8adef9b",
-   "metadata": {
-    "slideshow": {
-     "slide_type": "skip"
-    }
-   },
-   "source": [
-    "---"
-   ]
-  },
-  {
-   "cell_type": "markdown",
-   "id": "568202fd",
-   "metadata": {
-    "slideshow": {
-     "slide_type": "subslide"
-    }
-   },
-   "source": [
-    "### Exercise 0: Find the maximum value in a list (iterative)\n",
-    "\n",
-    "Write a function `find_maximum_iterative` that takes a list of numbers as input and returns the maximum value in the list. For this question, you are  not allowed to use built-in functions like `max()``."
-   ]
-  },
-  {
-   "cell_type": "code",
-   "execution_count": null,
-   "id": "431fe8c1-91d1-40f3-a7a4-f4a3770a4a01",
-   "metadata": {
-    "deletable": false,
-    "nbgrader": {
-     "cell_type": "code",
-     "checksum": "8b23d599da9ca2bdba48b9bcdd6e1165",
-     "grade": false,
-     "grade_id": "find_maximum_iterative",
-     "locked": false,
-     "schema_version": 3,
-     "solution": true,
-     "task": false
-    },
-    "tags": []
-   },
-   "outputs": [],
-   "source": [
-    "def find_maximum_iterative(L):\n",
-    "    # YOUR CODE HERE\n",
-    "    raise NotImplementedError()"
-   ]
-  },
-  {
-   "cell_type": "code",
-   "execution_count": null,
-   "id": "f6baae3c-3660-4add-ab4b-48016cba3030",
-   "metadata": {
-    "tags": []
-   },
-   "outputs": [],
-   "source": [
-    "find_maximum_iterative([1, 3, 5, 7, 9])"
-   ]
-  },
-  {
-   "cell_type": "code",
-   "execution_count": null,
-   "id": "e68b3e9a-418f-4950-9f27-18bb0fe90794",
-   "metadata": {
-    "deletable": false,
-    "editable": false,
-    "nbgrader": {
-     "cell_type": "code",
-     "checksum": "9cb3441fa27dd28ce74e368375de8080",
-     "grade": true,
-     "grade_id": "correct_find_maximum_iterative",
-     "locked": true,
-     "points": 1,
-     "schema_version": 3,
-     "solution": false,
-     "task": false
-    },
-    "tags": []
-   },
-   "outputs": [],
-   "source": [
-    "assert find_maximum_iterative([1, 3, 5, 7, 9]) == 9\n",
-    "assert find_maximum_iterative([-1, -5, -3]) == -1\n",
-    "assert find_maximum_iterative([42]) == 42\n",
-    "assert find_maximum_iterative([4, 8, 8, 2, 7]) == 8\n",
-    "assert find_maximum_iterative([-10, -5, -8, -2, -7]) == -2"
-   ]
-  },
-  {
-   "cell_type": "markdown",
-   "id": "612dc873-419b-42c5-be36-0accd03ffa79",
-   "metadata": {},
-   "source": [
-    "### Exercise 1: Find the maximum value in a list (recursive)\n",
-    "\n",
-    "Write a recursive version of the previous function; you may use the `max()` function for the recursive call."
-   ]
-  },
-  {
-   "cell_type": "code",
-   "execution_count": null,
-   "id": "07668fd8",
-   "metadata": {
-    "deletable": false,
-    "nbgrader": {
-     "cell_type": "code",
-     "checksum": "fcd4348ffdf05fa800f15e7dba033d8e",
-     "grade": false,
-     "grade_id": "find_maximum_recursive",
-     "locked": false,
-     "schema_version": 3,
-     "solution": true,
-     "task": false
-    },
-    "tags": []
-   },
-   "outputs": [],
-   "source": [
-    "def find_maximum_recursive(L):\n",
-    "    # YOUR CODE HERE\n",
-    "    raise NotImplementedError()"
-   ]
-  },
-  {
-   "cell_type": "code",
-   "execution_count": null,
-   "id": "f9784710-4b2b-434c-bc47-da46fa410749",
-   "metadata": {
-    "tags": []
-   },
-   "outputs": [],
-   "source": [
-    "find_maximum_recursive([1, 3, 5, 7, 9])"
-   ]
-  },
-  {
-   "cell_type": "code",
-   "execution_count": null,
-   "id": "9b0161f8-0539-4e5e-921c-1886e61c0783",
-   "metadata": {
-    "deletable": false,
-    "editable": false,
-    "nbgrader": {
-     "cell_type": "code",
-     "checksum": "1aae7ba6a868f7afd015deedcdf48aa4",
-     "grade": true,
-     "grade_id": "correct_find_maximum_recursive",
-     "locked": true,
-     "points": 1,
-     "schema_version": 3,
-     "solution": false,
-     "task": false
-    },
-    "tags": []
-   },
-   "outputs": [],
-   "source": [
-    "assert find_maximum_iterative([-10, -5, -8, -2, -7]) == find_maximum_recursive([-10, -5, -8, -2, -7])"
-   ]
-  },
-  {
-   "cell_type": "markdown",
-   "id": "005efd41-baa1-4505-b80e-3644d61ea094",
-   "metadata": {},
-   "source": [
-    "### Exercise 2: Sum of digits"
-   ]
-  },
-  {
-   "cell_type": "code",
-   "execution_count": null,
-   "id": "de424156-0b9b-41d0-8e38-ce335f35cec0",
-   "metadata": {
-    "deletable": false,
-    "nbgrader": {
-     "cell_type": "code",
-     "checksum": "3872f4f922847e273bc5a45cd425c458",
-     "grade": false,
-     "grade_id": "sum_of_digits",
-     "locked": false,
-     "schema_version": 3,
-     "solution": true,
-     "task": false
-    },
-    "tags": []
-   },
-   "outputs": [],
-   "source": [
-    "def sum_of_digits(n):\n",
-    "    # YOUR CODE HERE\n",
-    "    raise NotImplementedError()"
-   ]
-  },
-  {
-   "cell_type": "code",
-   "execution_count": null,
-   "id": "cec0caca-cb2c-4e4d-b004-27b3cf2ff611",
-   "metadata": {
-    "tags": []
-   },
-   "outputs": [],
-   "source": [
-    "sum_of_digits(10)"
-   ]
-  },
-  {
-   "cell_type": "code",
-   "execution_count": null,
-   "id": "bf276ca2-48ed-4e87-80f2-776f54b7062b",
-   "metadata": {
-    "deletable": false,
-    "editable": false,
-    "nbgrader": {
-     "cell_type": "code",
-     "checksum": "57a72fe3b7f20a42f9306fdde4b142f6",
-     "grade": true,
-     "grade_id": "correct_sum_of_digits",
-     "locked": true,
-     "points": 1,
-     "schema_version": 3,
-     "solution": false,
-     "task": false
-    },
-    "tags": []
-   },
-   "outputs": [],
-   "source": [
-    "assert sum_of_digits(10) == sum_of_digits(100000)"
-   ]
-  },
-  {
-   "cell_type": "markdown",
-   "id": "e2de630a-f9bd-4d45-959b-430e34cc9044",
-   "metadata": {
-    "tags": []
-   },
-   "source": [
-    "### Exercise 3: Calculate the power"
-   ]
-  },
-  {
-   "cell_type": "code",
-   "execution_count": null,
-   "id": "abca03a0-7bcd-4ee6-b109-ff2f2da52bb6",
-   "metadata": {
-    "deletable": false,
-    "nbgrader": {
-     "cell_type": "code",
-     "checksum": "c8c385784b4dd53e96c693511e7a2e80",
-     "grade": false,
-     "grade_id": "power",
-     "locked": false,
-     "schema_version": 3,
-     "solution": true,
-     "task": false
-    },
-    "tags": []
-   },
-   "outputs": [],
-   "source": [
-    "def power(base, exponent):\n",
-    "    # YOUR CODE HERE\n",
-    "    raise NotImplementedError()"
-   ]
-  },
-  {
-   "cell_type": "code",
-   "execution_count": null,
-   "id": "abddd3b1-f75f-4cb6-a09e-54eed489c5b0",
-   "metadata": {
-    "tags": []
-   },
-   "outputs": [],
-   "source": [
-    "power(2, 10)"
-   ]
-  },
-  {
-   "cell_type": "code",
-   "execution_count": null,
-   "id": "8a6605fe-4f6f-45de-84a3-7601e2e2e6f6",
-   "metadata": {
-    "deletable": false,
-    "editable": false,
-    "nbgrader": {
-     "cell_type": "code",
-     "checksum": "c08d387ba43f0468538bfde5b39407d6",
-     "grade": true,
-     "grade_id": "correct_power",
-     "locked": true,
-     "points": 1,
-     "schema_version": 3,
-     "solution": false,
-     "task": false
-    },
-    "tags": []
-   },
-   "outputs": [],
-   "source": [
-    "assert power(2, 10) == 1024"
-   ]
-  },
-  {
-   "cell_type": "markdown",
-   "id": "715100d3-fc21-49b9-a66d-b5243b4a279d",
-   "metadata": {
-    "tags": []
-   },
-   "source": [
-    "### Exercise 4: Reverse a string"
-   ]
-  },
-  {
-   "cell_type": "code",
-   "execution_count": null,
-   "id": "ddc9826a-0863-4777-a08d-81b66652b5a5",
-   "metadata": {
-    "deletable": false,
-    "nbgrader": {
-     "cell_type": "code",
-     "checksum": "762d91a747e5399677a26e44c5d8a041",
-     "grade": false,
-     "grade_id": "reverse_string",
-     "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": "13acad7e-d03c-4ea6-ad86-baf02e0910eb",
-   "metadata": {
-    "tags": []
-   },
-   "outputs": [],
-   "source": [
-    "reverse_string(\"Romain\")"
-   ]
-  },
-  {
-   "cell_type": "code",
-   "execution_count": null,
-   "id": "453c8e04-6cd9-4581-a206-dd479b6115cd",
-   "metadata": {
-    "deletable": false,
-    "editable": false,
-    "nbgrader": {
-     "cell_type": "code",
-     "checksum": "d42cbfb82df47fb4eb82e1530fa8f3cb",
-     "grade": true,
-     "grade_id": "correct_reverse_string",
-     "locked": true,
-     "points": 1,
-     "schema_version": 3,
-     "solution": false,
-     "task": false
-    },
-    "tags": []
-   },
-   "outputs": [],
-   "source": [
-    "assert reverse_string(\"\") == \"\"\n",
-    "assert reverse_string(\"AA\") == \"AA\"\n",
-    "assert reverse_string(\"ABC\") == \"CBA\""
-   ]
-  },
-  {
-   "cell_type": "markdown",
-   "id": "a0c5c115-1f3c-43f3-8098-930c707cd863",
-   "metadata": {},
-   "source": [
-    "def iterative_reverse_string(s):\n",
-    "    reversed_str = \"\"\n",
-    "    for char in s:\n",
-    "        reversed_str = char + reversed_str\n",
-    "    return reversed_str"
-   ]
-  },
-  {
-   "cell_type": "code",
-   "execution_count": null,
-   "id": "43e10b0c",
-   "metadata": {},
-   "outputs": [],
-   "source": []
-  },
-  {
-   "cell_type": "markdown",
-   "id": "5ab8f3c9-ddee-45ab-a013-fdd67d9853e0",
-   "metadata": {},
-   "source": [
-    "### Example 5: convert an interative suite into a recursive tail and non-tail function"
-   ]
-  },
-  {
-   "cell_type": "code",
-   "execution_count": null,
-   "id": "219add7f",
-   "metadata": {
-    "slideshow": {
-     "slide_type": "subslide"
-    },
-    "tags": []
-   },
-   "outputs": [],
-   "source": [
-    "def sequence(n):\n",
-    "    u = 1\n",
-    "    while n > 0:\n",
-    "        u = 2 * u + 1\n",
-    "        n -= 1\n",
-    "    return u"
-   ]
-  },
-  {
-   "cell_type": "code",
-   "execution_count": null,
-   "id": "0787df24-8234-4286-b910-5f9e456dd279",
-   "metadata": {
-    "tags": []
-   },
-   "outputs": [],
-   "source": [
-    "print(\"The result is {}\".format(sequence(3)))"
-   ]
-  },
-  {
-   "cell_type": "code",
-   "execution_count": null,
-   "id": "9c17cf1b-6d05-4589-af2b-c05cfcc33202",
-   "metadata": {
-    "deletable": false,
-    "nbgrader": {
-     "cell_type": "code",
-     "checksum": "2137e4ccdef7bccaa7b7ed6b52f305a8",
-     "grade": false,
-     "grade_id": "sequence_recursive_tail",
-     "locked": false,
-     "schema_version": 3,
-     "solution": true,
-     "task": false
-    },
-    "tags": []
-   },
-   "outputs": [],
-   "source": [
-    "def sequence_recursive_tail(n):\n",
-    "    # YOUR CODE HERE\n",
-    "    raise NotImplementedError()"
-   ]
-  },
-  {
-   "cell_type": "code",
-   "execution_count": null,
-   "id": "43507c43-de61-414d-b389-c0a771ad9e0c",
-   "metadata": {
-    "tags": []
-   },
-   "outputs": [],
-   "source": [
-    "print(\"The result is still {}\".format(sequence_recursive_tail(3)))"
-   ]
-  },
-  {
-   "cell_type": "code",
-   "execution_count": null,
-   "id": "921939d8",
-   "metadata": {
-    "deletable": false,
-    "nbgrader": {
-     "cell_type": "code",
-     "checksum": "0a1a74cd37dac7bf2b7e0090f1a418d1",
-     "grade": false,
-     "grade_id": "sequence_recursive_non_tail",
-     "locked": false,
-     "schema_version": 3,
-     "solution": true,
-     "task": false
-    },
-    "tags": []
-   },
-   "outputs": [],
-   "source": [
-    "def sequence_recursive_non_tail(n, acc=1):\n",
-    "    # YOUR CODE HERE\n",
-    "    raise NotImplementedError()"
-   ]
-  },
-  {
-   "cell_type": "code",
-   "execution_count": null,
-   "id": "b754bf67-3d8d-42d9-a7ca-c43e2995837d",
-   "metadata": {
-    "tags": []
-   },
-   "outputs": [],
-   "source": [
-    "print(\"The result is still  {}\".format(sequence_recursive_non_tail(3)))"
-   ]
-  },
-  {
-   "cell_type": "code",
-   "execution_count": null,
-   "id": "dd923b7c-0cab-4678-8dc3-aad2ab9b25f9",
-   "metadata": {
-    "deletable": false,
-    "editable": false,
-    "nbgrader": {
-     "cell_type": "code",
-     "checksum": "357a18b503c50448c4d736ab9159a64c",
-     "grade": true,
-     "grade_id": "correct_sequence_recursive_non_tail",
-     "locked": true,
-     "points": 1,
-     "schema_version": 3,
-     "solution": false,
-     "task": false
-    },
-    "slideshow": {
-     "slide_type": "slide"
-    },
-    "tags": []
-   },
-   "outputs": [],
-   "source": [
-    "assert sequence_recursive_tail(3) == sequence_recursive_non_tail(3)"
-   ]
-  },
-  {
-   "cell_type": "markdown",
-   "id": "3c28b36a",
-   "metadata": {
-    "slideshow": {
-     "slide_type": "subslide"
-    }
-   },
-   "source": [
-    "### Example 6: check if a word is an annagram\n",
-    "\n",
-    "Check if a word can be read backwards."
-   ]
-  },
-  {
-   "cell_type": "code",
-   "execution_count": null,
-   "id": "51bb3d08",
-   "metadata": {
-    "deletable": false,
-    "nbgrader": {
-     "cell_type": "code",
-     "checksum": "c25b0fb5ce11b015f40949352274cfdf",
-     "grade": false,
-     "grade_id": "annagram_rec",
-     "locked": false,
-     "schema_version": 3,
-     "solution": true,
-     "task": false
-    },
-    "tags": []
-   },
-   "outputs": [],
-   "source": [
-    "def annagram_rec(mot):\n",
-    "    # YOUR CODE HERE\n",
-    "    raise NotImplementedError()"
-   ]
-  },
-  {
-   "cell_type": "code",
-   "execution_count": null,
-   "id": "0c279628-9b96-4687-8e20-a954ab646e0f",
-   "metadata": {
-    "tags": []
-   },
-   "outputs": [],
-   "source": [
-    "annagram_rec(\"laval\")"
-   ]
-  },
-  {
-   "cell_type": "code",
-   "execution_count": null,
-   "id": "cf6fa61a-7c6f-4a32-96c2-b9fd50deacc6",
-   "metadata": {
-    "deletable": false,
-    "editable": false,
-    "nbgrader": {
-     "cell_type": "code",
-     "checksum": "94bbbbee3a4c7c005e8f9552a29ed556",
-     "grade": true,
-     "grade_id": "correct_annagram_rec",
-     "locked": true,
-     "points": 1,
-     "schema_version": 3,
-     "solution": false,
-     "task": false
-    },
-    "tags": []
-   },
-   "outputs": [],
-   "source": [
-    "assert annagram_rec(\"\")\n",
-    "assert annagram_rec(\"AA\")\n",
-    "assert not annagram_rec(\"ABC\")\n",
-    "assert annagram_rec(\"ABA\")"
-   ]
-  },
-  {
-   "cell_type": "markdown",
-   "id": "798c2875-7940-488a-8458-ad08f6a71c70",
-   "metadata": {},
-   "source": [
-    "### Example 7: Calculate GCD\n"
-   ]
-  },
-  {
-   "cell_type": "code",
-   "execution_count": null,
-   "id": "48c65c83-be0c-41c4-8c04-1d29ac4415cb",
-   "metadata": {
-    "tags": []
-   },
-   "outputs": [],
-   "source": [
-    "def iterative_gcd(a, b):\n",
-    "    while b:\n",
-    "        a, b = b, a % b\n",
-    "    return a"
-   ]
-  },
-  {
-   "cell_type": "code",
-   "execution_count": null,
-   "id": "bf6e1a76",
-   "metadata": {
-    "deletable": false,
-    "nbgrader": {
-     "cell_type": "code",
-     "checksum": "45353cb0fdd92b57e6f6f1739ed430b3",
-     "grade": false,
-     "grade_id": "recursive_gcd",
-     "locked": false,
-     "schema_version": 3,
-     "solution": true,
-     "task": false
-    },
-    "tags": []
-   },
-   "outputs": [],
-   "source": [
-    "def recursive_gcd(a, b):\n",
-    "    # YOUR CODE HERE\n",
-    "    raise NotImplementedError()"
-   ]
-  },
-  {
-   "cell_type": "code",
-   "execution_count": null,
-   "id": "4f1feace",
-   "metadata": {},
-   "outputs": [],
-   "source": [
-    "recursive_gcd(10, 2)"
-   ]
-  },
-  {
-   "cell_type": "code",
-   "execution_count": null,
-   "id": "e6ff1765-ff4b-49a5-80d3-684d2627e961",
-   "metadata": {
-    "deletable": false,
-    "editable": false,
-    "nbgrader": {
-     "cell_type": "code",
-     "checksum": "ed3ae90c2a4be5ff93a5d68b688f0f96",
-     "grade": true,
-     "grade_id": "correct_recursive_gcd",
-     "locked": true,
-     "points": 1,
-     "schema_version": 3,
-     "solution": false,
-     "task": false
-    },
-    "tags": []
-   },
-   "outputs": [],
-   "source": [
-    "assert iterative_gcd(10, 2) == recursive_gcd(10, 2)"
-   ]
-  },
-  {
-   "cell_type": "markdown",
-   "id": "d8b05edf-9536-4fc1-bfcc-ddbbeee426fc",
-   "metadata": {},
-   "source": [
-    "### Example 8: Calculate average of a list"
-   ]
-  },
-  {
-   "cell_type": "code",
-   "execution_count": null,
-   "id": "1661dfb5-88f2-411f-8fe2-63bbaa29ce72",
-   "metadata": {
-    "deletable": false,
-    "nbgrader": {
-     "cell_type": "code",
-     "checksum": "3dfcf16aa7e5f7e1f4e46a799e964624",
-     "grade": false,
-     "grade_id": "calculate_average_recursive",
-     "locked": false,
-     "schema_version": 3,
-     "solution": true,
-     "task": false
-    },
-    "tags": []
-   },
-   "outputs": [],
-   "source": [
-    "def calculate_average_recursive(lst, index=0):\n",
-    "    # YOUR CODE HERE\n",
-    "    raise NotImplementedError()"
-   ]
-  },
-  {
-   "cell_type": "code",
-   "execution_count": null,
-   "id": "0c5c72c6-3237-4f98-ab96-50a1838b833f",
-   "metadata": {},
-   "outputs": [],
-   "source": [
-    "calculate_average_recursive([1, 2, 3])"
-   ]
-  },
-  {
-   "cell_type": "code",
-   "execution_count": null,
-   "id": "9f18b6b7-d980-4a72-a2a8-3aa201003d21",
-   "metadata": {
-    "deletable": false,
-    "editable": false,
-    "nbgrader": {
-     "cell_type": "code",
-     "checksum": "27294a77eaee1e794183e6a31f145be1",
-     "grade": true,
-     "grade_id": "correct_calculate_average_recursive",
-     "locked": true,
-     "points": 1,
-     "schema_version": 3,
-     "solution": false,
-     "task": false
-    },
-    "tags": []
-   },
-   "outputs": [],
-   "source": [
-    "assert calculate_average_recursive([1, 2, 3]) == 2.5"
-   ]
-  },
-  {
-   "cell_type": "markdown",
-   "id": "79eef392-1d3d-46c0-aeee-ac805686e6f1",
-   "metadata": {},
-   "source": [
-    "### Example 9: Check for prime number"
-   ]
-  },
-  {
-   "cell_type": "code",
-   "execution_count": null,
-   "id": "ac374a08-11c9-47e6-ba11-419549911266",
-   "metadata": {
-    "deletable": false,
-    "nbgrader": {
-     "cell_type": "code",
-     "checksum": "58fec5e697f40d4e1934bdce3ae87647",
-     "grade": false,
-     "grade_id": "is_prime_recursive",
-     "locked": false,
-     "schema_version": 3,
-     "solution": true,
-     "task": false
-    },
-    "tags": []
-   },
-   "outputs": [],
-   "source": [
-    "def is_prime_recursive(n, divisor=2):\n",
-    "    # YOUR CODE HERE\n",
-    "    raise NotImplementedError()"
-   ]
-  },
-  {
-   "cell_type": "code",
-   "execution_count": null,
-   "id": "996fc91f",
-   "metadata": {},
-   "outputs": [],
-   "source": [
-    "is_prime_recursive(3)"
-   ]
-  },
-  {
-   "cell_type": "code",
-   "execution_count": null,
-   "id": "5be1051c-3b60-4810-b855-6f8575ad6380",
-   "metadata": {
-    "deletable": false,
-    "editable": false,
-    "nbgrader": {
-     "cell_type": "code",
-     "checksum": "f571ff3e3a5bc53ffbc828b255bfb6cb",
-     "grade": true,
-     "grade_id": "correct_is_prime_recursive",
-     "locked": true,
-     "points": 1,
-     "schema_version": 3,
-     "solution": false,
-     "task": false
-    },
-    "tags": []
-   },
-   "outputs": [],
-   "source": [
-    "assert is_prime_recursive(3) "
-   ]
-  },
-  {
-   "cell_type": "markdown",
-   "id": "5423682d-c31f-4a8d-9a0f-6812de7b1ae3",
-   "metadata": {},
-   "source": [
-    "### Example 10: Count occurrences of a given element in a list"
-   ]
-  },
-  {
-   "cell_type": "code",
-   "execution_count": null,
-   "id": "cfeb0ad0-ed82-499e-9af3-64923291a0e7",
-   "metadata": {
-    "deletable": false,
-    "nbgrader": {
-     "cell_type": "code",
-     "checksum": "01c4970fffe483944b93049b5d8404a0",
-     "grade": false,
-     "grade_id": "count_occurrences",
-     "locked": false,
-     "schema_version": 3,
-     "solution": true,
-     "task": false
-    },
-    "tags": []
-   },
-   "outputs": [],
-   "source": [
-    "def count_occurrences(arr, target, index=0):\n",
-    "    # YOUR CODE HERE\n",
-    "    raise NotImplementedError()"
-   ]
-  },
-  {
-   "cell_type": "code",
-   "execution_count": null,
-   "id": "49daec07-00b3-412e-ad44-5bafadbd9f36",
-   "metadata": {
-    "tags": []
-   },
-   "outputs": [],
-   "source": [
-    "count_occurrences([1, 2, 3, 4, 2, 2, 5, 6, 2], 2)"
-   ]
-  },
-  {
-   "cell_type": "code",
-   "execution_count": null,
-   "id": "14a2eb85-1126-4506-93bb-4bf624d046b6",
-   "metadata": {
-    "deletable": false,
-    "editable": false,
-    "nbgrader": {
-     "cell_type": "code",
-     "checksum": "5df4afd6ed2f7dfd102b8c21f8ced2e7",
-     "grade": true,
-     "grade_id": "correct_count_occurrences",
-     "locked": true,
-     "points": 1,
-     "schema_version": 3,
-     "solution": false,
-     "task": false
-    },
-    "tags": []
-   },
-   "outputs": [],
-   "source": [
-    "assert count_occurrences([1, 2, 3, 4, 2, 2, 5, 6, 2], 2) == 4"
-   ]
-  },
-  {
-   "cell_type": "markdown",
-   "id": "bb1784f5-2426-4661-aa13-dba96743ceb5",
-   "metadata": {},
-   "source": [
-    "# Bonus points"
-   ]
-  },
-  {
-   "cell_type": "markdown",
-   "id": "7fdcd705-dc0b-4614-8e27-9ba62f8fe442",
-   "metadata": {},
-   "source": [
-    "### Exercise 1: Find the maximum value in a list (iterative)\n",
-    "\n",
-    "Check that an empty lists raises a `ValueError` exception with a `\"The list is empty.\"` message."
-   ]
-  },
-  {
-   "cell_type": "code",
-   "execution_count": null,
-   "id": "f9334f32-f760-46c0-a649-c82f267aba5b",
-   "metadata": {
-    "tags": []
-   },
-   "outputs": [],
-   "source": [
-    "try:\n",
-    "    result = find_maximum_iterative([])\n",
-    "    assert False, \"Exception not raised\"\n",
-    "except ValueError as e:\n",
-    "    assert str(e) == \"The list is empty.\", f\"Expected error message: 'The list is empty.' but got '{str(e)}'\""
-   ]
-  },
-  {
-   "cell_type": "markdown",
-   "id": "c121315a-4aaa-4e04-912f-73f56555be56",
-   "metadata": {},
-   "source": [
-    "### Exercise 1: Find the maximum value in a list (recursive)\n",
-    "\n",
-    "Witout using the built-in `max` function"
-   ]
-  },
-  {
-   "cell_type": "code",
-   "execution_count": null,
-   "id": "775b7e32-a5ae-431b-9987-fcd3671fd022",
-   "metadata": {
-    "tags": []
-   },
-   "outputs": [],
-   "source": [
-    "def find_maximum_recursive_no_max_func(L): \n",
-    "    # Base case: If the list is empty, raise a ValueError\n",
-    "    if not L:\n",
-    "        raise ValueError(\"The list is empty.\")\n",
-    "    \n",
-    "    # Base case: If there's only one element in the list, return it as the maximum\n",
-    "    if len(L) == 1:\n",
-    "        return L[0]\n",
-    "    \n",
-    "    # Recursive case: Compare the first element with the maximum of the rest of the list\n",
-    "    rest_max = find_maximum_recursive(L[1:])\n",
-    "    return L[0] if L[0] > rest_max else rest_max"
-   ]
-  },
-  {
-   "cell_type": "code",
-   "execution_count": null,
-   "id": "f76ed657-3288-4b36-9175-21168d2eb761",
-   "metadata": {
-    "tags": []
-   },
-   "outputs": [],
-   "source": [
-    "assert not calls_builtin_max(find_maximum_recursive_no_max_func)"
-   ]
-  },
-  {
-   "cell_type": "markdown",
-   "id": "bbe7023a-aabd-489d-bae6-3b71566e22ef",
-   "metadata": {},
-   "source": [
-    "# Additional tests (do not change)"
-   ]
-  },
-  {
-   "cell_type": "code",
-   "execution_count": null,
-   "id": "b8bc657e-d491-4851-aa8c-ac2f2eac0841",
-   "metadata": {
-    "tags": []
-   },
-   "outputs": [],
-   "source": [
-    "# checks if a function uses another function, eg \"max\"\n",
-    "import inspect\n",
-    "\n",
-    "def calls_builtin_max(func):\n",
-    "    source_code = inspect.getsource(func)\n",
-    "    return 'max(' in source_code\n",
-    "\n",
-    "# Example of such function using max\n",
-    "def my_function(lst):\n",
-    "    return max(lst)"
-   ]
-  },
-  {
-   "cell_type": "code",
-   "execution_count": null,
-   "id": "1c73ad0e-ddc9-483d-85a1-f2a65d04f30b",
-   "metadata": {
-    "tags": []
-   },
-   "outputs": [],
-   "source": [
-    "assert calls_builtin_max(my_function)\n",
-    "assert not calls_builtin_max(find_maximum_iterative)"
-   ]
-  },
-  {
-   "cell_type": "code",
-   "execution_count": null,
-   "id": "8ce960f5-08da-449e-9e6f-dae215bc1b6a",
-   "metadata": {
-    "tags": []
-   },
-   "outputs": [],
-   "source": [
-    "# generates more examples for a given function\n",
-    "def gen_examples(fnct, n=10):\n",
-    "    return [fnct(i) for i in range(0, n)]"
-   ]
-  },
-  {
-   "cell_type": "code",
-   "execution_count": null,
-   "id": "d601b2f3-c33b-4ed2-81be-639ce1ffab76",
-   "metadata": {},
-   "outputs": [],
-   "source": []
-  },
-  {
-   "cell_type": "code",
-   "execution_count": null,
-   "id": "1f252530-7817-444c-ae10-d7b3bca87f2d",
-   "metadata": {},
-   "outputs": [],
-   "source": []
-  },
-  {
-   "cell_type": "code",
-   "execution_count": null,
-   "id": "0976f7c2-4375-4d76-a6c1-9e729a6c8aeb",
-   "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
-}
diff --git a/README.md b/README.md
index 982339cbed75c4be08395aa1b5ba169bb6f3dfa2..813e1d5158d9a12ee7acc6049a5df4bbb0cc0857 100644
--- a/README.md
+++ b/README.md
@@ -13,19 +13,19 @@ Instructor: [Romain Vuillemot](romain.vuillemot@ec-lyon.fr)
 
 ## Outline
 
-### Lecture 1 - **Data structures and complexity** | [notebook](01-introduction.ipynb) | [slides](01-introduction-slides.pdf) | [exercices](01-introduction-exercices.ipynb)
+### Lecture 1 - **Data structures and complexity** | [notebook](01-introduction.ipynb) | [exercices](01-introduction-exercices.ipynb)
 
 📖 [Python for Everybody](pdf/pythonlearn.pdf) chapter 9 (dictionnaries), chapter 10 (tuples)
 
-### Lecture 2 - **Recursion** | [notebook](02-recursion.ipynb) | [slides](02-recursion-slides.pdf) | [exercices](02-recursion-exercices.ipynb)
+### Lecture 2 - **Recursion** | [notebook](02-recursion.ipynb) | [exercices](exercises/02-recursion-exercices.ipynb)
 
 📖 [Think Python](pdf/thinkpython2.pdf) chapter 5 (Conditionals and recursion) and Real Python [recursion](https://realpython.com/python-recursion/).
 
-### Lecture 3 - **Lists, search, sort** | [notebook](03-lists-search-sort.ipynb) | [slides](03-lists-search-sort-slides.pdf) | [exercices](03-lists-search-sort-exercises.ipynb)
+### Lecture 3 - **Lists, search, sort** | [notebook](03-lists-search-sort.ipynb) | [exercices](exercises/03-lists-search-sort-exercises.ipynb)
 
 📖 [Think Python](pdf/thinkpython2.pdf) chapter 11 (lists), chapter 12 (tuples), [Python for Everybody](pdf/pythonlearn.pdf) chapter 8 (lists) and Real Python [lists](https://realpython.com/python-list/) and [sorts](https://realpython.com/sorting-algorithms-python/).
 
-### Lecture 4 - **Programming strategies: divide and conquer** | [notebook](04-) | [slides](03-lists-search-sort-slides.pdf) | [exercices](03-lists-search-sort-exercises.ipynb)
+### Lecture 4 - **Programming strategies: divide and conquer** | [notebook](04-programming-strategies.ipynb) | [exercices](exercises/04-05-06-programming-strategies-exercises.ipynb)
 
 📖 [Divide & conquer](https://en.wikibooks.org/wiki/Algorithms/Divide_and_Conquer)
 
@@ -39,40 +39,44 @@ Instructor: [Romain Vuillemot](romain.vuillemot@ec-lyon.fr)
 
 ### Lecture 7 - **Stacks and queues**
 
-📖 [Problem Solving with Algorithms](pdf/problemsolving.pdf) chapter 6 (trees and tree algorithms)
+chapter 1.2.1 (Queue/Stacks), [Open Data Structures](pdf/ods-python.pdf) 
+
 
 --- 
 
-📝 Assignment 1 - Analyzing a simple dataset
+📝 Assignment 1 - Analyzing a dataset
 
 ---
 
-### Lecture 8 - **Trees**
+### Lecture 8 - **Binary trees**
 
 📖 [Problem Solving with Algorithms](pdf/problemsolving.pdf) chapter 6 (trees and tree algorithms)
 
+### Lecture 9 - **Binary trees traversals**
 
-Next topics:
-
+📖 [Problem Solving with Algorithms](pdf/problemsolving.pdf) chapter 6.7 (trees traversal)
 
-1. **Advanced data structures**
+### Lecture 10 - **Trees**
 
-2. **Hashing**
+### Lecture 11 - **Trees algorithms**
 
-3. **Tree algorithms**
+### Lecture 12 - **Graphs**
 
-4. **Binary and n-trees**
+### Lecture 13 - **Graphs spanning trees**
 
-5. **Graphs**
+### Lecture 14 - **Graphs matrices**
 
-6. **Graphs algorithms**
+### Lecture 15 - **Graphs shortest paths**
 
-7. **Graphs shortest path algorithm**
 
 ## Books and ressources
 
 - [Think Python](pdf/thinkpython2.pdf), 2nd edition, by Allen B. Downey
 - [Python for Everybody](pdf/pythonlearn.pdf), by Charles Severance
 - [Problem Solving with Algorithms and Data Structures using Python](pdf/problemsolving.pdf), by Brad Miller and David Ranum
+- [ODS Pyhon](pdf/ods-python.pdf), by Pat Morin ([url](https://opendatastructures.org/ods-python/))
+
+Other ressources:
+
 - https://en.wikibooks.org/wiki/Algorithms/
 - List of [computer science books](https://freecomputerbooks.com/compscAlgorithmBooks.html)
\ No newline at end of file
diff --git a/01-data-structures-complexity-exercises.ipynb b/exercises/01-data-structures-complexity-exercises.ipynb
similarity index 99%
rename from 01-data-structures-complexity-exercises.ipynb
rename to exercises/01-data-structures-complexity-exercises.ipynb
index de69cd4c5ad1b13fd3f0174560b7b1cac9776cdb..0be737d823b8270c6f727b80d3d3dfc798baae8e 100644
--- a/01-data-structures-complexity-exercises.ipynb
+++ b/exercises/01-data-structures-complexity-exercises.ipynb
@@ -2,7 +2,7 @@
  "cells": [
   {
    "cell_type": "markdown",
-   "id": "136ec072",
+   "id": "59aef681",
    "metadata": {},
    "source": [
     "# UE5 Fundamentals of Algorithms\n",
@@ -23,7 +23,7 @@
   {
    "cell_type": "code",
    "execution_count": null,
-   "id": "b8c8e619",
+   "id": "88952ac5",
    "metadata": {},
    "outputs": [],
    "source": [
@@ -33,7 +33,7 @@
   },
   {
    "cell_type": "markdown",
-   "id": "986b50e4",
+   "id": "b779c274",
    "metadata": {},
    "source": [
     "---"
diff --git a/02-recursion-exercises.ipynb b/exercises/02-recursion-exercises.ipynb
similarity index 96%
rename from 02-recursion-exercises.ipynb
rename to exercises/02-recursion-exercises.ipynb
index 09f693bc94c760e53416868a7624f5cc95adff8f..5f854e39a6f1e92ed01267baa4bfea467c61cfb1 100644
--- a/02-recursion-exercises.ipynb
+++ b/exercises/02-recursion-exercises.ipynb
@@ -2,7 +2,7 @@
  "cells": [
   {
    "cell_type": "markdown",
-   "id": "996ed570",
+   "id": "a14c054e",
    "metadata": {},
    "source": [
     "# UE5 Fundamentals of Algorithms\n",
@@ -23,7 +23,7 @@
   {
    "cell_type": "code",
    "execution_count": null,
-   "id": "a0151651",
+   "id": "b13780a7",
    "metadata": {},
    "outputs": [],
    "source": [
@@ -33,7 +33,7 @@
   },
   {
    "cell_type": "markdown",
-   "id": "86da338c",
+   "id": "67ead887",
    "metadata": {},
    "source": [
     "---"
@@ -958,7 +958,7 @@
    "id": "7fdcd705-dc0b-4614-8e27-9ba62f8fe442",
    "metadata": {},
    "source": [
-    "### Exercise 1: Find the maximum value in a list (iterative)\n",
+    "### Exercise: Find the maximum value in a list (iterative)\n",
     "\n",
     "Check that an empty lists raises a `ValueError` exception with a `\"The list is empty.\"` message."
    ]
@@ -984,7 +984,7 @@
    "id": "c121315a-4aaa-4e04-912f-73f56555be56",
    "metadata": {},
    "source": [
-    "### Exercise 1: Find the maximum value in a list (recursive)\n",
+    "### Exercise: Find the maximum value in a list (recursive)\n",
     "\n",
     "Witout using the built-in `max` function"
    ]
@@ -1049,16 +1049,6 @@
     "# Additional tests (do not change)"
    ]
   },
-  {
-   "cell_type": "code",
-   "execution_count": null,
-   "id": "b8bc657e-d491-4851-aa8c-ac2f2eac0841",
-   "metadata": {
-    "tags": []
-   },
-   "outputs": [],
-   "source": []
-  },
   {
    "cell_type": "code",
    "execution_count": null,
@@ -1085,30 +1075,6 @@
     "def gen_examples(fnct, n=10):\n",
     "    return [fnct(i) for i in range(0, n)]"
    ]
-  },
-  {
-   "cell_type": "code",
-   "execution_count": null,
-   "id": "d601b2f3-c33b-4ed2-81be-639ce1ffab76",
-   "metadata": {},
-   "outputs": [],
-   "source": []
-  },
-  {
-   "cell_type": "code",
-   "execution_count": null,
-   "id": "1f252530-7817-444c-ae10-d7b3bca87f2d",
-   "metadata": {},
-   "outputs": [],
-   "source": []
-  },
-  {
-   "cell_type": "code",
-   "execution_count": null,
-   "id": "0976f7c2-4375-4d76-a6c1-9e729a6c8aeb",
-   "metadata": {},
-   "outputs": [],
-   "source": []
   }
  ],
  "metadata": {
diff --git a/03-lists-search-sort-exercises.ipynb b/exercises/03-lists-search-sort-exercises.ipynb
similarity index 91%
rename from 03-lists-search-sort-exercises.ipynb
rename to exercises/03-lists-search-sort-exercises.ipynb
index ad1a42338c11168e2ea4e7e157da587798ab075b..2ff574110dcfc0a1b629bd8cddc1b1781ed34e55 100644
--- a/03-lists-search-sort-exercises.ipynb
+++ b/exercises/03-lists-search-sort-exercises.ipynb
@@ -2,7 +2,7 @@
  "cells": [
   {
    "cell_type": "markdown",
-   "id": "5cbf5ca9",
+   "id": "f8151910",
    "metadata": {},
    "source": [
     "# UE5 Fundamentals of Algorithms\n",
@@ -23,7 +23,7 @@
   {
    "cell_type": "code",
    "execution_count": null,
-   "id": "43da1f45",
+   "id": "94c8f6d3",
    "metadata": {},
    "outputs": [],
    "source": [
@@ -33,7 +33,7 @@
   },
   {
    "cell_type": "markdown",
-   "id": "4d0c6ee6",
+   "id": "9e5bf33f",
    "metadata": {},
    "source": [
     "---"
@@ -67,6 +67,61 @@
     "list_complexities = [\"O(1)\", \"O(log(n))\", \"O(n)\", \"O(n^2)\", \"O(nlog(n))\", \"O(n^3)\", \"O(2^n)\", \"O(n!)\", \"O(n^n)\"]"
    ]
   },
+  {
+   "cell_type": "markdown",
+   "id": "11a124a7-1279-469a-b091-2833d3fd1a0f",
+   "metadata": {},
+   "source": [
+    "## Exercise 0: Search the index first occurence of a target value\n",
+    "\n",
+    "_Write a Python function `search_list(L, v)` that takes a list `L` and a target element `v` as input. The function should return the index of the first occurrence of the target element in the list `L`._"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": null,
+   "id": "665c7b64-428d-468a-860b-65d0d12e98e1",
+   "metadata": {
+    "tags": []
+   },
+   "outputs": [],
+   "source": [
+    "def search_list(L, target):\n",
+    "    for n, i in enumerate(L):\n",
+    "        if i == target:\n",
+    "            return n\n",
+    "    return -1"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": null,
+   "id": "d776ca94-1ed2-4443-91e2-a1591a1690b8",
+   "metadata": {
+    "tags": []
+   },
+   "outputs": [],
+   "source": [
+    "search_list([1, 2, 2], 2)"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": null,
+   "id": "e7b5950c-a6f0-4795-995b-903d717f35c9",
+   "metadata": {
+    "tags": []
+   },
+   "outputs": [],
+   "source": [
+    "assert search_list([1, 2, 3, 4, 5], 3) == 2\n",
+    "assert search_list([1, 2, 3, 4, 5], 6) == -1\n",
+    "assert search_list([1, 2, 3, 4, 5], 6) == -1\n",
+    "assert search_list([], 42) == -1\n",
+    "assert search_list([7, 2, 3, 4, 5], 7) == 0\n",
+    "assert search_list([1, 2, 3, 4, 5, 6], 7) == -1"
+   ]
+  },
   {
    "cell_type": "markdown",
    "id": "9d813205-b709-42ab-b414-6f3fc947022a",
@@ -123,7 +178,7 @@
     "editable": false,
     "nbgrader": {
      "cell_type": "code",
-     "checksum": "68b51ac31cc882ccdf9200c444d4e30d",
+     "checksum": "6054e435b1f5635d18f61f94bfb05e62",
      "grade": true,
      "grade_id": "correct_correct_search_list",
      "locked": true,
@@ -140,7 +195,7 @@
     "assert search_list([1, 2, 3, 4, 5], 6) == -1\n",
     "assert search_list([1, 2, 3, 4, 5, 6], 6) == -1\n",
     "assert search_list([], 42) == -1\n",
-    "assert search_list([7, 2, 3, 4, 5], 7) == 0\n",
+    "assert search_list([7, 2, 3, 4, 5, 7], 7) == 0\n",
     "assert search_list([1, 2, 3, 4, 5, 6], 6) == -1"
    ]
   },
@@ -605,7 +660,7 @@
   {
    "cell_type": "code",
    "execution_count": null,
-   "id": "74d4e305-f42d-4813-9a77-072989bb7e62",
+   "id": "2cc14fc2-2714-4242-83e2-31907b8a19f5",
    "metadata": {},
    "outputs": [],
    "source": []
diff --git a/04-programming-strategies-exercises.ipynb b/exercises/04-05-06-programming-strategies-exercises.ipynb
similarity index 57%
rename from 04-programming-strategies-exercises.ipynb
rename to exercises/04-05-06-programming-strategies-exercises.ipynb
index 386d6b5d20dfa493a190419bf8d89d26f5d28abc..e79716bbd73ef9d85a0250452eb7e90e62b6d225 100644
--- a/04-programming-strategies-exercises.ipynb
+++ b/exercises/04-05-06-programming-strategies-exercises.ipynb
@@ -2,7 +2,7 @@
  "cells": [
   {
    "cell_type": "markdown",
-   "id": "1523c46c",
+   "id": "8fa9ea2e",
    "metadata": {},
    "source": [
     "# UE5 Fundamentals of Algorithms\n",
@@ -23,7 +23,7 @@
   {
    "cell_type": "code",
    "execution_count": null,
-   "id": "c984c437",
+   "id": "6017bb23",
    "metadata": {},
    "outputs": [],
    "source": [
@@ -33,7 +33,7 @@
   },
   {
    "cell_type": "markdown",
-   "id": "81f8cbf6",
+   "id": "7dd0e72c",
    "metadata": {},
    "source": [
     "---"
@@ -141,7 +141,7 @@
    "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`._"
+    "_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._"
    ]
   },
   {
@@ -178,7 +178,7 @@
    },
    "outputs": [],
    "source": [
-    "print(two_sum([1, 2, 3, 4, 5], 4))"
+    "two_sum([1, 2, 3, 4, 5], 4)"
    ]
   },
   {
@@ -190,7 +190,7 @@
     "editable": false,
     "nbgrader": {
      "cell_type": "code",
-     "checksum": "dce1654749f72d16fa3d21a731f0a7ff",
+     "checksum": "71cc7d97ace17ad8446e79c255727951",
      "grade": true,
      "grade_id": "correct_two_sum",
      "locked": true,
@@ -205,7 +205,8 @@
    "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"
+    "assert two_sum([3, 3], 6) == [0, 1]          # 3 + 3 = 6\n",
+    "assert two_sum([3, 3], 123) == -1            # not possible"
    ]
   },
   {
@@ -219,8 +220,22 @@
     "\n",
     "_Given a list of points find the minimum distance between all the pairs of points._\n",
     "\n",
-    "- write a `dist`function\n",
-    "- define a `closest_point_naive`function using `math.inf`as initial value"
+    "- 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": null,
+   "id": "f73f28a4-d39c-497d-9cbb-1c4edd1c628f",
+   "metadata": {
+    "tags": []
+   },
+   "outputs": [],
+   "source": [
+    "import math"
    ]
   },
   {
@@ -231,7 +246,7 @@
     "deletable": false,
     "nbgrader": {
      "cell_type": "code",
-     "checksum": "ad1d7f9ad703f728fac843c9b6d4cbe1",
+     "checksum": "e00cddc47958defae9cbbdc89056c923",
      "grade": false,
      "grade_id": "cell-8738237c4c6682e4",
      "locked": false,
@@ -243,7 +258,6 @@
    },
    "outputs": [],
    "source": [
-    "import math\n",
     "def dist(point1, point2):\n",
     "    # YOUR CODE HERE\n",
     "    raise NotImplementedError()"
@@ -257,7 +271,7 @@
     "deletable": false,
     "nbgrader": {
      "cell_type": "code",
-     "checksum": "a5504d9e67deeb2651dfc058b5314bb8",
+     "checksum": "d578bae1b972f9331bf0c4e8918312da",
      "grade": false,
      "grade_id": "cell-9ca280911ed42034",
      "locked": false,
@@ -269,7 +283,7 @@
    },
    "outputs": [],
    "source": [
-    "def closest_point_naive(P, n):\n",
+    "def closest_point_naive(P):\n",
     "    # YOUR CODE HERE\n",
     "    raise NotImplementedError()"
    ]
@@ -284,7 +298,7 @@
    "outputs": [],
    "source": [
     "points = [(1, 2), (4, 6), (7, 8), (3, 5)]\n",
-    "closest_point_naive(points, len(points))"
+    "closest_point_naive(points)"
    ]
   },
   {
@@ -296,7 +310,7 @@
     "editable": false,
     "nbgrader": {
      "cell_type": "code",
-     "checksum": "17cb3a74f60bcbe305bce69a5b45da65",
+     "checksum": "7a40093d879cf398bc8ccc735d221027",
      "grade": true,
      "grade_id": "cell-618f956021833284",
      "locked": true,
@@ -310,12 +324,19 @@
    "outputs": [],
    "source": [
     "points1 = [(1, 2), (4, 6), (0, 0), (0, 0)]\n",
-    "n1 = len(points1)\n",
-    "\n",
-    "result1 = closest_point_naive(points1, n1)\n",
-    "expected_result1 = 0.0 \n",
-    "print(result1)\n",
-    "assert math.isclose(result1, expected_result1, rel_tol=1e-9), f\"Test Case 1 failed: {result1} != {expected_result1}\""
+    "closest_point_naive(points1)"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": null,
+   "id": "755116cb-456e-48ad-8dfe-bd72617488d9",
+   "metadata": {
+    "tags": []
+   },
+   "outputs": [],
+   "source": [
+    "assert math.isclose(closest_point_naive(points1), 0.0, rel_tol=1e-9)"
    ]
   },
   {
@@ -440,8 +461,19 @@
    "outputs": [],
    "source": [
     "points1 = [(0, 0), (1, 1), (3, 3), (5, 5)]\n",
-    "closest1 = closest_point_naive_pair(points1)\n",
-    "assert closest1 == ((0, 0), (1, 1))"
+    "closest_point_naive_pair(points1)"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": null,
+   "id": "aad82edd-144d-4117-9ee6-485b9e739251",
+   "metadata": {
+    "tags": []
+   },
+   "outputs": [],
+   "source": [
+    "assert closest_point_naive_pair(points1) == ((0, 0), (1, 1))"
    ]
   },
   {
@@ -504,7 +536,7 @@
     "editable": false,
     "nbgrader": {
      "cell_type": "code",
-     "checksum": "3ca9c06b9c5d3b2b5728138d821e650c",
+     "checksum": "06abbc717c29465f92ec2b6bc8dc596b",
      "grade": true,
      "grade_id": "correct_merge_sort",
      "locked": true,
@@ -517,8 +549,305 @@
    },
    "outputs": [],
    "source": [
-    "L = [4, 2, 3]\n",
-    "assert merge_sort(L) == sorted(L)"
+    "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": null,
+   "id": "e0ed0841-1255-4bdb-b7f8-e689c2a953af",
+   "metadata": {
+    "deletable": false,
+    "nbgrader": {
+     "cell_type": "code",
+     "checksum": "240106e7faa5c05dfe9e32f64f68e3cf",
+     "grade": false,
+     "grade_id": "interval_scheduling",
+     "locked": false,
+     "schema_version": 3,
+     "solution": true,
+     "task": false
+    },
+    "tags": []
+   },
+   "outputs": [],
+   "source": [
+    "def interval_scheduling(intervals):\n",
+    "    # YOUR CODE HERE\n",
+    "    raise NotImplementedError()"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": null,
+   "id": "d6a50280-f016-4686-8515-1b4a136c0fd9",
+   "metadata": {
+    "tags": []
+   },
+   "outputs": [],
+   "source": [
+    "intervals = [(1, 3), (2, 4), (3, 5), (5, 7), (6, 8)]"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": null,
+   "id": "bd38d673-077d-44b1-b81c-ac7448f5c01c",
+   "metadata": {
+    "deletable": false,
+    "editable": false,
+    "nbgrader": {
+     "cell_type": "code",
+     "checksum": "a1c5ab0cb1fbb052b5567e17549a9723",
+     "grade": true,
+     "grade_id": "correct_interval_scheduling",
+     "locked": true,
+     "points": 1,
+     "schema_version": 3,
+     "solution": false,
+     "task": false
+    },
+    "tags": []
+   },
+   "outputs": [],
+   "source": [
+    "assert interval_scheduling(intervals) == [(1, 3), (3, 5), (5, 7)]"
+   ]
+  },
+  {
+   "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": null,
+   "id": "095836b8-2612-4d58-a9ce-b7968489418c",
+   "metadata": {
+    "deletable": false,
+    "nbgrader": {
+     "cell_type": "code",
+     "checksum": "b448fda533da03916276f3f7701f1a59",
+     "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",
+    "    # YOUR CODE HERE\n",
+    "    raise NotImplementedError()"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": null,
+   "id": "c87ae1e2-7497-4920-9597-d1b3cddf8580",
+   "metadata": {
+    "tags": []
+   },
+   "outputs": [],
+   "source": [
+    "interval_scheduling_longest([(0, 4), (3, 5), (5, 7)])"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": null,
+   "id": "afcf3a69-aa36-4b71-93a8-218337ed88b9",
+   "metadata": {
+    "deletable": false,
+    "editable": false,
+    "nbgrader": {
+     "cell_type": "code",
+     "checksum": "5eb8ff6c627cab5c24af63f377eb221e",
+     "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": null,
+   "id": "46947633-3f5f-420b-b416-500a0dab4fcb",
+   "metadata": {
+    "deletable": false,
+    "nbgrader": {
+     "cell_type": "code",
+     "checksum": "4d258685229c335d689928bcd6c973ec",
+     "grade": false,
+     "grade_id": "cell-0bf75b2bfe8e2e4c",
+     "locked": false,
+     "schema_version": 3,
+     "solution": true,
+     "task": false
+    },
+    "tags": []
+   },
+   "outputs": [],
+   "source": [
+    "def greedy_knapsack(W, wt):\n",
+    "    # YOUR CODE HERE\n",
+    "    raise NotImplementedError()"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": null,
+   "id": "737df134-4ee1-49a9-9034-da3b0267ae84",
+   "metadata": {
+    "tags": []
+   },
+   "outputs": [],
+   "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": null,
+   "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": null,
+   "id": "2be5f2f7-d9a5-4cf0-afe4-5a5a54ee0434",
+   "metadata": {
+    "deletable": false,
+    "nbgrader": {
+     "cell_type": "code",
+     "checksum": "f5b1cc2b31e32e2468be56b84bf67cb3",
+     "grade": false,
+     "grade_id": "cell-5dc5571a7aca5b0f",
+     "locked": false,
+     "schema_version": 3,
+     "solution": true,
+     "task": false
+    },
+    "tags": []
+   },
+   "outputs": [],
+   "source": [
+    "def dynamic_knapsack(W, wt):\n",
+    "    # YOUR CODE HERE\n",
+    "    raise NotImplementedError()"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": null,
+   "id": "5adf0e0e-73c4-4656-b546-5b02347f1a28",
+   "metadata": {},
+   "outputs": [],
+   "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": null,
+   "id": "935873d5-14ee-4b79-9e6a-c692d1c73a9a",
+   "metadata": {},
+   "outputs": [],
+   "source": [
+    "assert dynamic_knapsack(max_weight, weights) == (5, [3, 2])"
    ]
   }
  ],
diff --git a/exercises/07-stacks-queues.ipynb b/exercises/07-stacks-queues.ipynb
new file mode 100644
index 0000000000000000000000000000000000000000..de89e546f9532bc55e4f57f47f9ed17ceeeb8bb5
--- /dev/null
+++ b/exercises/07-stacks-queues.ipynb
@@ -0,0 +1,333 @@
+{
+ "cells": [
+  {
+   "cell_type": "markdown",
+   "id": "bfc5eefb",
+   "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": "ebe01f37",
+   "metadata": {},
+   "outputs": [],
+   "source": [
+    "ID = \"\"\n",
+    "COLLABORATORS_ID = []"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "id": "796b04b3",
+   "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"
+   ]
+  }
+ ],
+ "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/pdf/ods-python.pdf b/pdf/ods-python.pdf
new file mode 100644
index 0000000000000000000000000000000000000000..889d9885a3e556c266e44b4a2d26d093250bb5c2
Binary files /dev/null and b/pdf/ods-python.pdf differ
diff --git a/solutions/02-recursion-exercises.ipynb b/solutions/02-recursion-exercises.ipynb
index 57912ddc91d787d2ef465d35b515b1701c6fac17..0329eb812a2711ec2472efb6a87dd81a37e74a7d 100644
--- a/solutions/02-recursion-exercises.ipynb
+++ b/solutions/02-recursion-exercises.ipynb
@@ -1025,7 +1025,7 @@
    "id": "7fdcd705-dc0b-4614-8e27-9ba62f8fe442",
    "metadata": {},
    "source": [
-    "### Exercise 1: Find the maximum value in a list (iterative)\n",
+    "### Exercise: Find the maximum value in a list (iterative)\n",
     "\n",
     "Check that an empty lists raises a `ValueError` exception with a `\"The list is empty.\"` message."
    ]
@@ -1051,7 +1051,7 @@
    "id": "c121315a-4aaa-4e04-912f-73f56555be56",
    "metadata": {},
    "source": [
-    "### Exercise 1: Find the maximum value in a list (recursive)\n",
+    "### Exercise: Find the maximum value in a list (recursive)\n",
     "\n",
     "Witout using the built-in `max` function"
    ]
@@ -1116,16 +1116,6 @@
     "# Additional tests (do not change)"
    ]
   },
-  {
-   "cell_type": "code",
-   "execution_count": 45,
-   "id": "b8bc657e-d491-4851-aa8c-ac2f2eac0841",
-   "metadata": {
-    "tags": []
-   },
-   "outputs": [],
-   "source": []
-  },
   {
    "cell_type": "code",
    "execution_count": 66,
@@ -1152,30 +1142,6 @@
     "def gen_examples(fnct, n=10):\n",
     "    return [fnct(i) for i in range(0, n)]"
    ]
-  },
-  {
-   "cell_type": "code",
-   "execution_count": null,
-   "id": "d601b2f3-c33b-4ed2-81be-639ce1ffab76",
-   "metadata": {},
-   "outputs": [],
-   "source": []
-  },
-  {
-   "cell_type": "code",
-   "execution_count": null,
-   "id": "1f252530-7817-444c-ae10-d7b3bca87f2d",
-   "metadata": {},
-   "outputs": [],
-   "source": []
-  },
-  {
-   "cell_type": "code",
-   "execution_count": null,
-   "id": "0976f7c2-4375-4d76-a6c1-9e729a6c8aeb",
-   "metadata": {},
-   "outputs": [],
-   "source": []
   }
  ],
  "metadata": {
diff --git a/solutions/03-lists-search-sort-exercises.ipynb b/solutions/03-lists-search-sort-exercises.ipynb
new file mode 100644
index 0000000000000000000000000000000000000000..0edce773392da83e24246b94abb9cf5301d71aaf
--- /dev/null
+++ b/solutions/03-lists-search-sort-exercises.ipynb
@@ -0,0 +1,685 @@
+{
+ "cells": [
+  {
+   "cell_type": "markdown",
+   "id": "e58599e3-9ab7-4d43-bb22-aeccade424ce",
+   "metadata": {},
+   "source": [
+    "# Lists, search, sort"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "id": "691b3c38-0e83-4bb2-ac90-ef76d2dd9a7a",
+   "metadata": {},
+   "source": [
+    "---"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 2,
+   "id": "1095285f-26e2-43ce-a1c5-9358c5256a0b",
+   "metadata": {
+    "tags": []
+   },
+   "outputs": [],
+   "source": [
+    "list_complexities = [\"O(1)\", \"O(log(n))\", \"O(n)\", \"O(n^2)\", \"O(nlog(n))\", \"O(n^3)\", \"O(2^n)\", \"O(n!)\", \"O(n^n)\"]"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "id": "11a124a7-1279-469a-b091-2833d3fd1a0f",
+   "metadata": {},
+   "source": [
+    "## Exercise 0: Search the index first occurence of a target value\n",
+    "\n",
+    "_Write a Python function `search_list(L, v)` that takes a list `L` and a target element `v` as input. The function should return the index of the first occurrence of the target element in the list `L`._"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 15,
+   "id": "665c7b64-428d-468a-860b-65d0d12e98e1",
+   "metadata": {
+    "tags": []
+   },
+   "outputs": [],
+   "source": [
+    "def search_list(L, target):\n",
+    "    for n, i in enumerate(L):\n",
+    "        if i == target:\n",
+    "            return n\n",
+    "    return -1"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 16,
+   "id": "d776ca94-1ed2-4443-91e2-a1591a1690b8",
+   "metadata": {
+    "tags": []
+   },
+   "outputs": [
+    {
+     "data": {
+      "text/plain": [
+       "1"
+      ]
+     },
+     "execution_count": 16,
+     "metadata": {},
+     "output_type": "execute_result"
+    }
+   ],
+   "source": [
+    "search_list([1, 2, 2], 2)"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 14,
+   "id": "e7b5950c-a6f0-4795-995b-903d717f35c9",
+   "metadata": {
+    "tags": []
+   },
+   "outputs": [],
+   "source": [
+    "assert search_list([1, 2, 3, 4, 5], 3) == 2\n",
+    "assert search_list([1, 2, 3, 4, 5], 6) == -1\n",
+    "assert search_list([1, 2, 3, 4, 5], 6) == -1\n",
+    "assert search_list([], 42) == -1\n",
+    "assert search_list([7, 2, 3, 4, 5], 7) == 0\n",
+    "assert search_list([1, 2, 3, 4, 5, 6], 7) == -1"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "id": "9d813205-b709-42ab-b414-6f3fc947022a",
+   "metadata": {},
+   "source": [
+    "## Exercise 1: Search in a list with an odd index\n",
+    "\n",
+    "_Write a Python function `search_list(L, v)` that takes a list `L` and a target element `v` as input. The function should return the index of the first occurrence of the target element in the list `L`._"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 2,
+   "id": "f3b233ec-7077-479d-9c04-f1a4c35f3111",
+   "metadata": {
+    "nbgrader": {
+     "grade": false,
+     "grade_id": "search_list",
+     "locked": false,
+     "schema_version": 3,
+     "solution": true,
+     "task": false
+    },
+    "tags": []
+   },
+   "outputs": [],
+   "source": [
+    "def search_list(L, target):\n",
+    "    ### BEGIN SOLUTION\n",
+    "    for i, element in enumerate(L):\n",
+    "        if element == target and i % 2 == 0:\n",
+    "            return i\n",
+    "    return -1\n",
+    "    ### END SOLUTION"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 3,
+   "id": "f280eeea-4812-4a30-80b5-3fe1cafa9283",
+   "metadata": {
+    "tags": []
+   },
+   "outputs": [
+    {
+     "data": {
+      "text/plain": [
+       "-1"
+      ]
+     },
+     "execution_count": 3,
+     "metadata": {},
+     "output_type": "execute_result"
+    }
+   ],
+   "source": [
+    "search_list([1, 2, 2], 3)"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 4,
+   "id": "423d2637-8bd6-4e8f-95ff-2765dae5bce7",
+   "metadata": {
+    "nbgrader": {
+     "grade": true,
+     "grade_id": "correct_correct_search_list",
+     "locked": true,
+     "points": 1,
+     "schema_version": 3,
+     "solution": false,
+     "task": false
+    },
+    "tags": []
+   },
+   "outputs": [],
+   "source": [
+    "assert search_list([1, 2, 3, 4, 5], 3) == 2\n",
+    "assert search_list([1, 2, 3, 4, 5], 6) == -1\n",
+    "assert search_list([1, 2, 3, 4, 5, 6], 6) == -1\n",
+    "assert search_list([], 42) == -1\n",
+    "assert search_list([7, 2, 3, 4, 5, 7], 7) == 0\n",
+    "assert search_list([1, 2, 3, 4, 5, 6], 6) == -1"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "id": "6d8dc6cd-aad0-42a9-b768-6a1a5289e354",
+   "metadata": {},
+   "source": [
+    "## Exercise 2: Sort a list of tuples\n",
+    "\n",
+    "_Given a list of lists of length N, sort by the N-th element of the list._"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 6,
+   "id": "8271ff47-efb4-48a0-ac4c-bba6ede7e578",
+   "metadata": {
+    "nbgrader": {
+     "grade": false,
+     "grade_id": "sort_list_of_lists_by_nth_element",
+     "locked": false,
+     "schema_version": 3,
+     "solution": true,
+     "task": false
+    },
+    "tags": []
+   },
+   "outputs": [],
+   "source": [
+    "def sort_list_of_lists_by_nth_element(list_of_lists, N):\n",
+    "    ### BEGIN SOLUTION\n",
+    "    sorted_list = sorted(list_of_lists, key=lambda x: x[N])\n",
+    "    return sorted_list\n",
+    "    ### END SOLUTION"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 7,
+   "id": "4577bd24-9e50-4172-8246-d1bccfa21618",
+   "metadata": {
+    "tags": []
+   },
+   "outputs": [
+    {
+     "name": "stdout",
+     "output_type": "stream",
+     "text": [
+      "[[3, 5, 1], [2, 8, 3], [7, 4, 6], [1, 2, 9]]\n"
+     ]
+    }
+   ],
+   "source": [
+    "list_of_lists = [[3, 5, 1], [1, 2, 9], [7, 4, 6], [2, 8, 3]]\n",
+    "sorted_list = sort_list_of_lists_by_nth_element(list_of_lists, 2)\n",
+    "print(sorted_list)"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 8,
+   "id": "ed3cdeed-07fa-461f-b7ae-210e1605ca76",
+   "metadata": {
+    "nbgrader": {
+     "grade": true,
+     "grade_id": "correct_sort_list_of_lists_by_nth_element",
+     "locked": true,
+     "points": 1,
+     "schema_version": 3,
+     "solution": false,
+     "task": false
+    },
+    "tags": []
+   },
+   "outputs": [],
+   "source": [
+    "list1 = [[3, 5, 1], [1, 2, 9], [7, 4, 6], [2, 8, 3]]\n",
+    "sorted_list1 = sort_list_of_lists_by_nth_element(list1, 2)\n",
+    "assert sorted_list1 == [[3, 5, 1], [2, 8, 3], [7, 4, 6], [1, 2, 9]], \"Test Case 1 Failed\"\n",
+    "\n",
+    "list2 = [[9, 5, 7], [3, 6, 1], [0, 2, 4], [8, 1, 5]]\n",
+    "sorted_list2 = sort_list_of_lists_by_nth_element(list2, 0)\n",
+    "assert sorted_list2 == [[0, 2, 4], [3, 6, 1], [8, 1, 5], [9, 5, 7]], \"Test Case 2 Failed\"\n",
+    "\n",
+    "list3 = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]\n",
+    "sorted_list3 = sort_list_of_lists_by_nth_element(list3, 1)\n",
+    "assert sorted_list3 == [[1, 2, 3], [4, 5, 6], [7, 8, 9]], \"Test Case 3 Failed\"\n"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "id": "0bbda1ba-a5e7-4a1d-a742-84d0215b1e24",
+   "metadata": {},
+   "source": [
+    "## Exercise 3: Access a list element\n",
+    "\n",
+    "_Given an input list `L`, and `index` value, access a given `key` and return the value._"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 9,
+   "id": "2d6a6f11-d24b-4f0e-a7d2-298243e35c4d",
+   "metadata": {
+    "nbgrader": {
+     "grade": false,
+     "grade_id": "cell-1ab0b636df63501a",
+     "locked": false,
+     "schema_version": 3,
+     "solution": true,
+     "task": false
+    },
+    "tags": []
+   },
+   "outputs": [],
+   "source": [
+    "def access_dict_element(L, index, key):\n",
+    "    ### BEGIN SOLUTION\n",
+    "    if 0 <= index < len(L):\n",
+    "        if key in L[index]:\n",
+    "            return L[index][key]\n",
+    "    ### END SOLUTION"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 10,
+   "id": "ea0883dc-d08c-40ea-9e0b-4f0a3abc517f",
+   "metadata": {
+    "tags": []
+   },
+   "outputs": [
+    {
+     "name": "stdout",
+     "output_type": "stream",
+     "text": [
+      "Alice\n"
+     ]
+    }
+   ],
+   "source": [
+    "example_list = [{'name': 'Alice', 'age': 30}, {'name': 'Bob', 'age': 25}]\n",
+    "result = access_dict_element(example_list, 0, 'name')\n",
+    "print(result) "
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 11,
+   "id": "88ae441e-58b1-4d6c-a639-530919658d03",
+   "metadata": {
+    "nbgrader": {
+     "grade": true,
+     "grade_id": "correct_access_dict_element",
+     "locked": true,
+     "points": 1,
+     "schema_version": 3,
+     "solution": false,
+     "task": false
+    },
+    "tags": []
+   },
+   "outputs": [],
+   "source": [
+    "example_list = [{'name': 'Alice', 'age': 30}, {'name': 'Bob', 'age': 25}]\n",
+    "assert access_dict_element(example_list, 0, 'name') == 'Alice'\n",
+    "assert access_dict_element(example_list, 1, 'city') is None\n",
+    "assert access_dict_element(example_list, 2, 'name') is None\n",
+    "assert access_dict_element(example_list, 0, 'city') is None"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "id": "98405b12-ad61-4007-8c9f-6955d238df41",
+   "metadata": {
+    "tags": []
+   },
+   "source": [
+    "## Exercise 4: Remove Elements from a List\n",
+    "\n",
+    "_Write a Python function `remove_elements(L, condition)` that takes a list `L` and a function `condition` as input._"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 12,
+   "id": "e079e47b-2f9e-42d1-a78b-56c92ad84d63",
+   "metadata": {
+    "tags": []
+   },
+   "outputs": [],
+   "source": [
+    "def is_odd(x):\n",
+    "    return x % 2 != 0"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 13,
+   "id": "536734bd-d4cc-4f83-8042-3c0e774c4034",
+   "metadata": {
+    "nbgrader": {
+     "grade": false,
+     "grade_id": "remove_elements",
+     "locked": false,
+     "schema_version": 3,
+     "solution": true,
+     "task": false
+    },
+    "tags": []
+   },
+   "outputs": [],
+   "source": [
+    "def remove_elements(lst, condition):\n",
+    "    ### BEGIN SOLUTION\n",
+    "    lst[:] = [x for x in lst if not condition(x)]\n",
+    "    ### END SOLUTION"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 14,
+   "id": "a65bb6f1-b7c7-4156-ba8b-9b72a25616f3",
+   "metadata": {
+    "tags": []
+   },
+   "outputs": [
+    {
+     "name": "stdout",
+     "output_type": "stream",
+     "text": [
+      "[2, 4, 6, 8]\n"
+     ]
+    }
+   ],
+   "source": [
+    "my_list = [1, 2, 3, 4, 5, 6, 7, 8, 9]\n",
+    "remove_elements(my_list, is_odd)\n",
+    "print(my_list)  # Should print [2, 4, 6, 8]"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 15,
+   "id": "254155dc-b271-4881-ac65-5a11d13990ea",
+   "metadata": {
+    "nbgrader": {
+     "grade": true,
+     "grade_id": "correct_remove_elements",
+     "locked": true,
+     "points": 1,
+     "schema_version": 3,
+     "solution": false,
+     "task": false
+    },
+    "tags": []
+   },
+   "outputs": [],
+   "source": [
+    "test_list_1 = [12, 5, 18, 9, 25, 3, 15]\n",
+    "remove_elements(test_list_1, lambda x: x > 10)\n",
+    "assert test_list_1 == [5, 9, 3], \"Remove greater than 30\"\n",
+    "\n",
+    "test_list_2 = [-3, 7, -9, 2, 0, -1, 8]\n",
+    "remove_elements(test_list_2, lambda x: x < 0)\n",
+    "assert test_list_2 == [7, 2, 0, 8], \"Remove negative elements\"\n",
+    "\n",
+    "def custom_condition(x):\n",
+    "    return x % 3 == 0\n",
+    "test_list_3 = [1, 2, 3, 4, 5, 6, 7, 8, 9]\n",
+    "remove_elements(test_list_3, custom_condition)\n",
+    "assert test_list_3 == [1, 2, 4, 5, 7, 8]\n",
+    "\n",
+    "test_list_4 = [42, 99, 101]\n",
+    "remove_elements(test_list_4, lambda x: True)\n",
+    "assert test_list_4 == [], \"Remove all elements\"\n",
+    "\n",
+    "test_list_5 = [10, 20, 30, 40]\n",
+    "remove_elements(test_list_5, lambda x: False)\n",
+    "assert test_list_5 == [10, 20, 30, 40], \"No element to remove\""
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "id": "d75dba4b-ac22-4f2c-9a6c-cf333b1ec5e8",
+   "metadata": {},
+   "source": [
+    "## Exercise 5: Sort a dictionnary by values\n",
+    "\n",
+    "List a dictionnary (not a list!) by value."
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 16,
+   "id": "556be9d8-b8c3-4f1d-bcb1-8f099968af9d",
+   "metadata": {
+    "nbgrader": {
+     "grade": false,
+     "grade_id": "sort_dict_by_values",
+     "locked": false,
+     "schema_version": 3,
+     "solution": true,
+     "task": false
+    },
+    "tags": []
+   },
+   "outputs": [],
+   "source": [
+    "def sort_dict_by_values(input_dict):\n",
+    "    ### BEGIN SOLUTION\n",
+    "    sorted_items = sorted(input_dict.items(), key=lambda item: item[1])\n",
+    "    sorted_dict = {}\n",
+    "    for key, value in sorted_items:\n",
+    "        sorted_dict[key] = value\n",
+    "    ### END SOLUTION\n",
+    "    return sorted_dict"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 17,
+   "id": "3c32c4ee-56f5-46b5-a8b6-b740e6d5fef5",
+   "metadata": {
+    "tags": []
+   },
+   "outputs": [],
+   "source": [
+    "test_dict3 = {'c': 3, 'b': 2, 'a': 1}\n",
+    "sorted_dict3 = sort_dict_by_values(test_dict3)\n",
+    "assert sorted_dict3 == {'a': 1, 'b': 2, 'c': 3}"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 18,
+   "id": "532e5225-a2d8-4c10-a036-1efde9acc5fd",
+   "metadata": {
+    "nbgrader": {
+     "grade": true,
+     "grade_id": "correct_sort_dict_by_values",
+     "locked": true,
+     "points": 0,
+     "schema_version": 3,
+     "solution": false,
+     "task": false
+    },
+    "tags": []
+   },
+   "outputs": [],
+   "source": [
+    "test_dict = {'banana': 3, 'apple': 1, 'cherry': 2}\n",
+    "sorted_dict = sort_dict_by_values(test_dict)\n",
+    "assert sorted_dict == {'apple': 1, 'cherry': 2, 'banana': 3}\n",
+    "\n",
+    "test_dict2 = {'zebra': 42, 'lion': 7, 'elephant': 15, 'giraffe': 23}\n",
+    "sorted_dict2 = sort_dict_by_values(test_dict2)\n",
+    "assert sorted_dict2 == {'lion': 7, 'elephant': 15, 'giraffe': 23, 'zebra': 42}\n",
+    "\n",
+    "test_dict3 = {'one': 3, 'two': 3, 'three': 3, 'four': 3}\n",
+    "sorted_dict3 = sort_dict_by_values(test_dict3)\n",
+    "assert sorted_dict3 == {'one': 3, 'two': 3, 'three': 3, 'four': 3}"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "id": "fef2ad7f-55ef-43f2-991d-5067bb085eb6",
+   "metadata": {},
+   "source": [
+    "## Exercise 6: insertion sort\n",
+    "\n",
+    "Implement the `insertion sort` that operates as follows:\n",
+    "\n",
+    "- Start with an unsorted list.\n",
+    "- Iterate through each element in the list.\n",
+    "- For each element, compare it with the elements to its left in the list.\n",
+    "- Move elements to the right until you find the correct position for the current element.\n",
+    "- Insert the current element into its proper place in the sorted portion of the list.\n",
+    "- Repeat this process for all elements, gradually building a sorted list from left to right."
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 19,
+   "id": "51a86852-f8e2-4c05-8053-13fdf2a4832b",
+   "metadata": {
+    "nbgrader": {
+     "grade": false,
+     "grade_id": "insertion_sort",
+     "locked": false,
+     "schema_version": 3,
+     "solution": true,
+     "task": false
+    },
+    "tags": []
+   },
+   "outputs": [],
+   "source": [
+    "def insertion_sort(arr):\n",
+    "    ### BEGIN SOLUTION\n",
+    "    for i in range(1, len(arr)):\n",
+    "        key = arr[i]\n",
+    "        j = i - 1\n",
+    "        while j >= 0 and key < arr[j]:\n",
+    "            arr[j + 1] = arr[j]\n",
+    "            j -= 1\n",
+    "        arr[j + 1] = key\n",
+    "    return arr\n",
+    "    ### END SOLUTION"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 20,
+   "id": "fbfa74f1-4675-452f-897b-21b0c7025f81",
+   "metadata": {
+    "tags": []
+   },
+   "outputs": [
+    {
+     "name": "stdout",
+     "output_type": "stream",
+     "text": [
+      "[1, 2, 3, 4, 5]\n"
+     ]
+    }
+   ],
+   "source": [
+    "print(insertion_sort([2, 1, 3, 4, 5]))"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 21,
+   "id": "266e89e0-4b59-441f-bb67-69ad4e35e2a9",
+   "metadata": {
+    "nbgrader": {
+     "grade": true,
+     "grade_id": "correct_insertion_sort",
+     "locked": true,
+     "points": 1,
+     "schema_version": 3,
+     "solution": false,
+     "task": false
+    },
+    "tags": []
+   },
+   "outputs": [],
+   "source": [
+    "# Test case 2: Already sorted list\n",
+    "arr = [1, 2, 3, 4, 5]\n",
+    "assert insertion_sort(arr) == arr\n",
+    "\n",
+    "# Test case 3: Reverse sorted list\n",
+    "arr = [5, 4, 3, 2, 1]\n",
+    "assert insertion_sort(arr) == [1, 2, 3, 4, 5]\n",
+    "\n",
+    "# Test case 4: Random order list\n",
+    "arr = [3, 1, 4, 1, 5, 9, 2, 6, 5, 3, 5]\n",
+    "assert insertion_sort(arr) == [1, 1, 2, 3, 3, 4, 5, 5, 5, 6, 9]"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "id": "ab78dd44-bb6a-451d-8642-223639d31bf9",
+   "metadata": {},
+   "source": [
+    "## Bonus\n",
+    "\n",
+    "You may get bonus points for the following answers:\n",
+    "\n",
+    "- add exceptions https://docs.python.org/3/library/exceptions.html\n",
+    "- add more test cases"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": null,
+   "id": "2cc14fc2-2714-4242-83e2-31907b8a19f5",
+   "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
+}