diff --git a/01-data-structures-complexity-exercices.ipynb b/01-data-structures-complexity-exercices.ipynb index 6a7e9d4b9a1fcf6c02bdecf46e1fdf3e6dc66ad8..b46fdf73fcba8c5fae1186c007f213a51fcfafdb 100644 --- a/01-data-structures-complexity-exercices.ipynb +++ b/01-data-structures-complexity-exercices.ipynb @@ -2,7 +2,7 @@ "cells": [ { "cell_type": "markdown", - "id": "2bb7e285", + "id": "608c95b1", "metadata": {}, "source": [ "# UE5 Fundamentals of Algorithms\n", @@ -23,7 +23,7 @@ { "cell_type": "code", "execution_count": null, - "id": "20dd5861", + "id": "a934feef", "metadata": {}, "outputs": [], "source": [ @@ -33,7 +33,7 @@ }, { "cell_type": "markdown", - "id": "f00472a3", + "id": "b498a6a2", "metadata": {}, "source": [ "---" @@ -63,6 +63,14 @@ "---" ] }, + { + "cell_type": "markdown", + "id": "827ebb43-1e5d-4756-83ba-97af3e36b6af", + "metadata": {}, + "source": [ + "_For the following question, if a complexity is needed please pick one in this list_" + ] + }, { "cell_type": "code", "execution_count": null, @@ -72,8 +80,7 @@ }, "outputs": [], "source": [ - "list_complexities = [\"O(1)\", \"O(log(n))\", \"O(n)\", \"O(n^2)\", \"O(nlog(n))\", \n", - " \"O(n^3)\", \"O(2^n)\", \"O(n!)\", \"O(n^n)\"]" + "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)\"]" ] }, { @@ -229,6 +236,28 @@ "# YOUR CODE HERE\n", "raise NotImplementedError()" ] + }, + { + "cell_type": "markdown", + "id": "87b4921b-ef55-4083-b4f1-a3ca5bb7b011", + "metadata": {}, + "source": [ + "### Additional checks (do not change)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "6e8f2878-ce5f-4cd8-a5a5-7bce8f655ab8", + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "assert nested_loop_example_complexity in list_complexities\n", + "assert fibonacci_recursive_complexity in list_complexities\n", + "assert binary_searche_complexity in list_complexities" + ] } ], "metadata": { diff --git a/02-recursion-exercices.ipynb b/02-recursion-exercices.ipynb index 5173c4a16bb209c77e0e1d6f6cc742823ac7599b..0ae7ffe7e33d32b044afb7e260e7b1afc2b9b742 100644 --- a/02-recursion-exercices.ipynb +++ b/02-recursion-exercices.ipynb @@ -2,7 +2,7 @@ "cells": [ { "cell_type": "markdown", - "id": "dadeb4a2", + "id": "bca30313", "metadata": {}, "source": [ "# UE5 Fundamentals of Algorithms\n", @@ -23,7 +23,7 @@ { "cell_type": "code", "execution_count": null, - "id": "7c45a2a5", + "id": "6f6a3d43", "metadata": {}, "outputs": [], "source": [ @@ -33,7 +33,7 @@ }, { "cell_type": "markdown", - "id": "f14bc602", + "id": "c5b97c1c", "metadata": {}, "source": [ "---" @@ -602,9 +602,9 @@ } }, "source": [ - "### Example 6: check if annagram\n", + "### Example 6: check if a word is an annagram\n", "\n", - "Écrire une fonction \\texttt{palindrome} qui indique si un mot peut être lu de manière identique dans les deux sens. Donnez la forme itérative et récursive.\n" + "Check if a word can be read backwards." ] }, { @@ -771,7 +771,7 @@ "deletable": false, "nbgrader": { "cell_type": "code", - "checksum": "ccdab0e0b54c6ff4e1835b4a57a4ac72", + "checksum": "3dfcf16aa7e5f7e1f4e46a799e964624", "grade": false, "grade_id": "calculate_average_recursive", "locked": false, @@ -785,7 +785,7 @@ "source": [ "def calculate_average_recursive(lst, index=0):\n", " # YOUR CODE HERE\n", - " raise NotImplementedError()\n" + " raise NotImplementedError()" ] }, { diff --git a/03-lists-search-sort-exercises.ipynb b/03-lists-search-sort-exercises.ipynb new file mode 100644 index 0000000000000000000000000000000000000000..3d5c261bef217345cb2f9c87138028f365855172 --- /dev/null +++ b/03-lists-search-sort-exercises.ipynb @@ -0,0 +1,631 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "id": "d8056b8c", + "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": "9c5894f5", + "metadata": {}, + "outputs": [], + "source": [ + "ID = \"\"\n", + "COLLABORATORS_ID = []" + ] + }, + { + "cell_type": "markdown", + "id": "838b13ee", + "metadata": {}, + "source": [ + "---" + ] + }, + { + "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": "markdown", + "id": "9d813205-b709-42ab-b414-6f3fc947022a", + "metadata": {}, + "source": [ + "## Exerccise 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`. If the target element is not in the list, return -1. The target index should also be of an odd value (eg 0, 2, 4, ..)." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "f3b233ec-7077-479d-9c04-f1a4c35f3111", + "metadata": { + "deletable": false, + "nbgrader": { + "cell_type": "code", + "checksum": "2791444cbfd4f0f74f1ce7f2a330ecec", + "grade": false, + "grade_id": "search_list", + "locked": false, + "schema_version": 3, + "solution": true, + "task": false + }, + "tags": [] + }, + "outputs": [], + "source": [ + "def search_list(L, target):\n", + " # YOUR CODE HERE\n", + " raise NotImplementedError()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "f280eeea-4812-4a30-80b5-3fe1cafa9283", + "metadata": { + "deletable": false, + "editable": false, + "nbgrader": { + "cell_type": "code", + "checksum": "e508e1baca64296eb559208993ee6289", + "grade": true, + "grade_id": "correct_search_list", + "locked": true, + "points": 1, + "schema_version": 3, + "solution": false, + "task": false + }, + "tags": [] + }, + "outputs": [], + "source": [ + "search_list([1, 2, 2], 3)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "423d2637-8bd6-4e8f-95ff-2765dae5bce7", + "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], 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], 6) == -1" + ] + }, + { + "cell_type": "markdown", + "id": "6d8dc6cd-aad0-42a9-b768-6a1a5289e354", + "metadata": {}, + "source": [ + "## Exerccise 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": null, + "id": "8271ff47-efb4-48a0-ac4c-bba6ede7e578", + "metadata": { + "deletable": false, + "nbgrader": { + "cell_type": "code", + "checksum": "d36956e43a1d9a594625212c58f4560a", + "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", + " # YOUR CODE HERE\n", + " raise NotImplementedError()\n", + "# Example usage:\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "4577bd24-9e50-4172-8246-d1bccfa21618", + "metadata": { + "tags": [] + }, + "outputs": [], + "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": null, + "id": "ed3cdeed-07fa-461f-b7ae-210e1605ca76", + "metadata": { + "deletable": false, + "editable": false, + "nbgrader": { + "cell_type": "code", + "checksum": "135ef51ad6ac5ce059a50fccc46a99e4", + "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": [ + "## Exerccise 3: Access a list element" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "2d6a6f11-d24b-4f0e-a7d2-298243e35c4d", + "metadata": { + "deletable": false, + "nbgrader": { + "cell_type": "code", + "checksum": "df3e8c605c7e96af2267865e04990e5a", + "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", + " # YOUR CODE HERE\n", + " raise NotImplementedError()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "ea0883dc-d08c-40ea-9e0b-4f0a3abc517f", + "metadata": { + "tags": [] + }, + "outputs": [], + "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": null, + "id": "88ae441e-58b1-4d6c-a639-530919658d03", + "metadata": { + "deletable": false, + "editable": false, + "nbgrader": { + "cell_type": "code", + "checksum": "c77eefc574735feb146d00c86553b601", + "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", + "\n", + "# Example 2: Accessing a non-existing key in a dictionary at a valid index\n", + "assert access_dict_element(example_list, 1, 'city') is None\n", + "\n", + "# Example 3: Accessing an index that is out of range\n", + "assert access_dict_element(example_list, 2, 'name') is None\n", + "\n", + "# Example 4: Accessing a valid index but with a key that doesn't exist\n", + "assert access_dict_element(example_list, 0, 'city') is None" + ] + }, + { + "cell_type": "markdown", + "id": "98405b12-ad61-4007-8c9f-6955d238df41", + "metadata": { + "tags": [] + }, + "source": [ + "## Exerccise 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. The `condition` is a function that accepts an element from the list as its argument and returns a boolean value. The function `remove_elements` should remove all elements from the list for which the `condition` function returns `True`." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "e079e47b-2f9e-42d1-a78b-56c92ad84d63", + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "def is_odd(x):\n", + " return x % 2 != 0" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "536734bd-d4cc-4f83-8042-3c0e774c4034", + "metadata": { + "deletable": false, + "nbgrader": { + "cell_type": "code", + "checksum": "46e9b2d0caa1061f9d00cf2859441701", + "grade": false, + "grade_id": "remove_elements", + "locked": false, + "schema_version": 3, + "solution": true, + "task": false + }, + "tags": [] + }, + "outputs": [], + "source": [ + "def remove_elements(lst, condition):\n", + " # YOUR CODE HERE\n", + " raise NotImplementedError()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "a65bb6f1-b7c7-4156-ba8b-9b72a25616f3", + "metadata": { + "tags": [] + }, + "outputs": [], + "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": null, + "id": "254155dc-b271-4881-ac65-5a11d13990ea", + "metadata": { + "deletable": false, + "editable": false, + "nbgrader": { + "cell_type": "code", + "checksum": "7d18e8b7e4619abfc3e78fb2f2801892", + "grade": true, + "grade_id": "correct_remove_elements", + "locked": true, + "points": 1, + "schema_version": 3, + "solution": false, + "task": false + }, + "tags": [] + }, + "outputs": [], + "source": [ + "# Test 1: Remove elements greater than 10\n", + "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]\n", + "\n", + "# Test 2: Remove negative elements\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]\n", + "\n", + "# Test 3: Remove elements based on a custom condition\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 elements 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": null, + "id": "556be9d8-b8c3-4f1d-bcb1-8f099968af9d", + "metadata": { + "deletable": false, + "nbgrader": { + "cell_type": "code", + "checksum": "6bfb51c12c41947733534307eb1cf5c4", + "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", + " # YOUR CODE HERE\n", + " raise NotImplementedError()\n", + " return sorted_dict" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "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": null, + "id": "532e5225-a2d8-4c10-a036-1efde9acc5fd", + "metadata": { + "deletable": false, + "editable": false, + "nbgrader": { + "cell_type": "code", + "checksum": "8a4001090e87ce0c5d773621ed0a3ea9", + "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": null, + "id": "51a86852-f8e2-4c05-8053-13fdf2a4832b", + "metadata": { + "deletable": false, + "nbgrader": { + "cell_type": "code", + "checksum": "84421b7199764b6fe3485117b23fb0a1", + "grade": false, + "grade_id": "insertion_sort", + "locked": false, + "schema_version": 3, + "solution": true, + "task": false + }, + "tags": [] + }, + "outputs": [], + "source": [ + "def insertion_sort(arr):\n", + " # YOUR CODE HERE\n", + " raise NotImplementedError()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "fbfa74f1-4675-452f-897b-21b0c7025f81", + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "print(insertion_sort([2, 1, 3, 4, 5]))" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "266e89e0-4b59-441f-bb67-69ad4e35e2a9", + "metadata": { + "deletable": false, + "editable": false, + "nbgrader": { + "cell_type": "code", + "checksum": "dc6fc6f16aa2c62a5e1e39382106b0bf", + "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": "74d4e305-f42d-4813-9a77-072989bb7e62", + "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/03-lists-search-sort-slides.pdf b/03-lists-search-sort-slides.pdf new file mode 100644 index 0000000000000000000000000000000000000000..f8b682986e73fda8cb61e2b475265c0d1d112b68 Binary files /dev/null and b/03-lists-search-sort-slides.pdf differ diff --git a/03-lists-search-sort.ipynb b/03-lists-search-sort.ipynb new file mode 100644 index 0000000000000000000000000000000000000000..380986258b08a8025f158a66146ef2c90535ffbc --- /dev/null +++ b/03-lists-search-sort.ipynb @@ -0,0 +1,804 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "id": "bec049ad", + "metadata": { + "nbgrader": { + "grade": false, + "grade_id": "cell-6892cebeacb58715", + "locked": true, + "schema_version": 3, + "solution": false, + "task": false + }, + "slideshow": { + "slide_type": "slide" + } + }, + "source": [ + "# UE5 Fundamentals of Algorithms\n", + "## Lecture 3: Lists, search, sort\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" + ] + }, + { + "cell_type": "markdown", + "id": "6341504d", + "metadata": { + "slideshow": { + "slide_type": "skip" + } + }, + "source": [ + "---\n", + "TODO\n", + "- \n", + "- tp-pythonneries.pdf\n", + "Static and dynamic arrays\n", + "Singly linked lists\n", + "Doubly linked lists\n", + "Circular linked lists" + ] + }, + { + "cell_type": "markdown", + "id": "fbbc2f0d", + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, + "source": [ + "## Outline\n", + "- Definition and examples of lists\n", + "- Manipulate\n", + "- Search\n", + "- Sort\n", + "- Iterate\n", + "- Filter/Map" + ] + }, + { + "cell_type": "markdown", + "id": "ab21085a", + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, + "source": [ + "## What is a list?\n", + "\n", + "> A **list** is a linear data structure \n", + "\n", + "- A sequence of elements\n", + "- Each element has a position (index)\n", + "- The order of the elements is important\n", + "- The elements can be of any type\n", + "\n", + "Examples of lists:" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "4fcb6bdb", + "metadata": {}, + "outputs": [], + "source": [ + "numbers_list = [1, 2, 3, 4, 5]\n", + "strings_list = [\"apple\", \"banana\", \"cherry\", \"date\"]\n", + "mixed_list = [1, \"apple\", 3.14, True]\n", + "nested_list = [[1, 2, 3], [\"a\", \"b\", \"c\"], [True, False]]" + ] + }, + { + "cell_type": "markdown", + "id": "bb445f5c", + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, + "source": [ + "### List operations\n", + "\n", + "- **Access** an element at a given position\n", + "- **Insert** an element at a given position\n", + "- **Remove** an element at a given position\n", + "- **Search** an element\n", + "- **Sort** the list\n", + "- **Reverse** the list" + ] + }, + { + "cell_type": "markdown", + "id": "cc05f88e", + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, + "source": [ + "## Access\n", + "\n", + "> Return a value" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "33da6137", + "metadata": {}, + "outputs": [], + "source": [ + "L = [1, 2, 3]\n", + "\n", + "for val in tab:\n", + " print(val)" + ] + }, + { + "cell_type": "markdown", + "id": "990e937d", + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, + "source": [ + "### Example: is a list ordered?" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "05a3d562", + "metadata": {}, + "outputs": [], + "source": [ + "def estordonnee(liste):\n", + "\n", + " for i in range(len(liste) - 1):\n", + " if liste[i + 1] < liste[i]:\n", + " return False\n", + " return True\n", + "\n", + "print(estordonnee([1,2,3,4]))\n", + "print(estordonnee([1,2,3,4,1]))" + ] + }, + { + "cell_type": "markdown", + "id": "3e822b32", + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, + "source": [ + "## Insert\n", + "\n", + "> Add elements in the list (regardless the index)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "5aad3402", + "metadata": {}, + "outputs": [], + "source": [ + "from time import time\n", + "\n", + "def compute_average(n):\n", + " data = []\n", + " start = time()\n", + " for k in range(n):\n", + " data.append(None)\n", + " end = time()\n", + " return (end - start) / n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "37c3b4a7", + "metadata": {}, + "outputs": [], + "source": [ + "compute_average(20)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "9c4be228", + "metadata": { + "slideshow": { + "slide_type": "-" + } + }, + "outputs": [], + "source": [ + "my_list = [1, 2, 3, 4, 5]\n", + "insert_elements = [99, 100]\n", + "my_list = my_list[:2] + insert_elements + my_list[2:]\n", + "print(my_list)" + ] + }, + { + "cell_type": "markdown", + "id": "5d95ee75", + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, + "source": [ + "# Search\n", + "\n", + "> Given a list of elements, find the position of a given element\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "8a5dd42f", + "metadata": { + "nbgrader": { + "grade": false, + "grade_id": "cell-387c098b188d4707", + "locked": false, + "schema_version": 3, + "solution": true, + "task": false + } + }, + "outputs": [], + "source": [ + "def search_element_in_list(element, list):\n", + " for i in list:\n", + " if i == element:\n", + " return True\n", + " return False" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "a3e4ed1f", + "metadata": { + "nbgrader": { + "grade": true, + "grade_id": "cell-d5f44386312e81c0", + "locked": true, + "points": 1, + "schema_version": 3, + "solution": false, + "task": false + } + }, + "outputs": [], + "source": [ + "L = [1, 2, 3, 4, 5]\n", + "element_to_find = 3\n", + "\n", + "try:\n", + " index = L.index(element_to_find)\n", + " print(f\"{element_to_find} found at index {index}.\")\n", + "except ValueError:\n", + " print(f\"{element_to_find} is not in the list.\")" + ] + }, + { + "cell_type": "markdown", + "id": "52399db0", + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, + "source": [ + "### Example: Binary search (pseudo code)\n", + "\n", + "- **Input**: A sorted list (array) and a target value to find.\n", + "- **Initialization**:\n", + " - Set a pointer `left` to the beginning of the list (index 0).\n", + " - Set a pointer `right` to the end of the list (index equal to the length of the list minus one).\n", + "- **Search**:\n", + " - While `left` is less than or equal to `right`:\n", + " - Calculate the middle index as `mid` by adding `left` and `right` and then dividing by 2.\n", + " - Check if the element at index `mid` in the list is equal to the target value:\n", + " - If it is, you've found the target, so return `mid`.\n", + " - If the element at index `mid` is less than the target:\n", + " - Update `left` to `mid + 1` to search in the right half of the list.\n", + " - If the element at index `mid` is greater than the target:\n", + " - Update `right` to `mid - 1` to search in the left half of the list.\n", + "- **Result**:\n", + " - If you've gone through the entire loop and haven't found the target, return -1 to indicate that the target is not in the list." + ] + }, + { + "cell_type": "code", + "execution_count": 22, + "id": "0d5eeb2c", + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, + "outputs": [], + "source": [ + "### Example: Binary search (pseudo code)" + ] + }, + { + "cell_type": "code", + "execution_count": 23, + "id": "1197437b", + "metadata": { + "slideshow": { + "slide_type": "-" + } + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Element 5 found at index 4.\n" + ] + } + ], + "source": [ + "def binary_search(arr, target):\n", + " left, right = 0, len(arr) - 1\n", + "\n", + " while left <= right:\n", + " mid = (left + right) // 2 # Calculate the middle index\n", + "\n", + " if arr[mid] == target:\n", + " return mid # Element found, return its index\n", + " elif arr[mid] < target:\n", + " left = mid + 1 # Search the right half\n", + " else:\n", + " right = mid - 1 # Search the left half\n", + "\n", + " return -1 # Element not found\n", + "\n", + "# Example usage:\n", + "ordered_list = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]\n", + "target_element = 5\n", + "result = binary_search(ordered_list, target_element)\n", + "\n", + "if result != -1:\n", + " print(f\"Element {target_element} found at index {result}.\")\n", + "else:\n", + " print(f\"Element {target_element} not found in the list.\")" + ] + }, + { + "cell_type": "markdown", + "id": "08843d8f", + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, + "source": [ + "# Sort\n", + "\n", + "> Given a list of elements, sort the elements according to a given order\n", + "\n", + "- **Ascending** order\n", + "- **Descending** order\n", + "- **Alphabetical** order\n", + "- **Reverse** order\n", + "- **Custom** order\n", + "\n", + "NB: Sort is more complex and will be studied later on." + ] + }, + { + "cell_type": "markdown", + "id": "879f8d7c", + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, + "source": [ + "### All the ways to sort a list " + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "dead2e0b", + "metadata": {}, + "outputs": [], + "source": [ + "my_list = [3, 1, 4, 1, 5, 9, 2, 6, 5, 3, 5]\n", + "sorted_list = sorted(my_list)\n", + "print(sorted_list)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "01e4d112", + "metadata": {}, + "outputs": [], + "source": [ + "numbers = [3, 1, 4, 1, 5, 9, 2, 6, 5, 3, 5]\n", + "sorted_numbers = sorted(numbers)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "e2c9277a", + "metadata": {}, + "outputs": [], + "source": [ + "numbers = [3, 1, 4, 1, 5, 9, 2, 6, 5, 3, 5]\n", + "numbers.sort(reverse=True)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "26d6dad8", + "metadata": {}, + "outputs": [], + "source": [ + "numbers = [3, 1, 4, 1, 5, 9, 2, 6, 5, 3, 5]\n", + "numbers.sort()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "34975051", + "metadata": {}, + "outputs": [], + "source": [ + "words = ['apple', 'banana', 'cherry', 'date']\n", + "sorted_words = sorted(words, key=len)" + ] + }, + { + "cell_type": "markdown", + "id": "ee60b8ff", + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, + "source": [ + "## Enumerators\n", + "\n", + "> Enables to turn a list into a list of index + value\n" + ] + }, + { + "cell_type": "code", + "execution_count": 6, + "id": "c1bdb416", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "0 1\n", + "1 2\n", + "2 3\n", + "0 1 A\n", + "1 2 B\n", + "2 3 C\n" + ] + } + ], + "source": [ + "a = [1, 2, 3]\n", + "b = [\"A\", \"B\", \"C\"]\n", + "\n", + "for index, value in enumerate(L):\n", + " print(index, value)\n", + " \n", + "for i, (x, y) in enumerate(zip(a, b)):\n", + " print(i, x, y)" + ] + }, + { + "cell_type": "code", + "execution_count": 7, + "id": "15eebc0d", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "1\n", + "2\n", + "3\n" + ] + } + ], + "source": [ + "iterable = [1, 2, 3]\n", + "iterator = iter(iterable)\n", + "\n", + "try:\n", + " while True:\n", + " item = next(iterator)\n", + " print(item)\n", + "except StopIteration:\n", + " pass" + ] + }, + { + "cell_type": "markdown", + "id": "e97201fc", + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, + "source": [ + "## Iterators" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "bc13a581", + "metadata": {}, + "outputs": [], + "source": [ + "iterable = [1, 2, 3, 4, 5]\n", + "iterator = iter(iterable)\n", + "\n", + "try:\n", + " while True:\n", + " item = next(iterator)\n", + " print(item)\n", + "except StopIteration:\n", + " pass" + ] + }, + { + "cell_type": "markdown", + "id": "8297afc9", + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, + "source": [ + "## Generators" + ] + }, + { + "cell_type": "markdown", + "id": "269c01b9", + "metadata": {}, + "source": [ + "Using generators" + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "id": "289eb2ba", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "1\n", + "2\n", + "3\n" + ] + } + ], + "source": [ + "def my_iterator():\n", + " data = [1, 2, 3]\n", + " for item in data:\n", + " yield item\n", + "\n", + "for item in my_iterator():\n", + " print(item)" + ] + }, + { + "cell_type": "markdown", + "id": "0a882d1d", + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, + "source": [ + "## Linked list\n", + "\n", + "> A **_linked_ list** is a sequence of values (or objects) called *nodes* that are connected to each other in order to facilitate their storage and retrieval.\n", + "\n", + "\n", + "- The first node is called the head, the last node is the tail, and it points to `null`.\n", + "\n", + "- This structure allows for a flexible approach to manipulating objects: increasing their number, order, etc.\n", + "\n", + "- Especially allows for **dynamic memory allocation**, whereas an array needs to allocate all the space before being filled.\n", + "\n", + "- On the other hand, it requires linear search time (unlike arrays), and can be problematic for implementing a stack.\n" + ] + }, + { + "cell_type": "code", + "execution_count": 19, + "id": "f248b881", + "metadata": {}, + "outputs": [], + "source": [ + "## Linked list (cont.)" + ] + }, + { + "cell_type": "code", + "execution_count": 18, + "id": "53534019", + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "1 -> 2 -> 3 -> None\n" + ] + } + ], + "source": [ + "# Initialize an empty linked list\n", + "linked_list = None\n", + "\n", + "# Function to append data to the linked list\n", + "def append(data):\n", + " global linked_list\n", + " if linked_list is None:\n", + " linked_list = {\"data\": data, \"next\": None}\n", + " else:\n", + " current = linked_list\n", + " while current[\"next\"]:\n", + " current = current[\"next\"]\n", + " current[\"next\"] = {\"data\": data, \"next\": None}\n", + "\n", + "# Function to traverse and print the linked list\n", + "def traverse():\n", + " current = linked_list\n", + " while current:\n", + " print(current[\"data\"], end=\" -> \")\n", + " current = current[\"next\"]\n", + " print(\"None\")\n", + "\n", + "# Append some data to the linked list\n", + "append(1)\n", + "append(2)\n", + "append(3)\n", + "\n", + "# Print the linked list\n", + "traverse()\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "5c865215", + "metadata": {}, + "outputs": [], + "source": [] + }, + { + "cell_type": "markdown", + "id": "28564ab2", + "metadata": {}, + "source": [ + "## Filter\n", + "\n" + ] + }, + { + "cell_type": "code", + "execution_count": 9, + "id": "3012f2e3", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "[6, 7, 8, 9]" + ] + }, + "execution_count": 9, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "x = range(10)\n", + "list(x)\n", + "list(filter(lambda x : x > 5, x))" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "5c0860da", + "metadata": {}, + "outputs": [], + "source": [ + "## Map" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "435094a4", + "metadata": {}, + "outputs": [], + "source": [ + "list(map(lambda x : x * x, x))" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "5575cf08", + "metadata": {}, + "outputs": [], + "source": [] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "fb30b1ce", + "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 +} diff --git a/README.md b/README.md index 31fb64acfed0d101c17ad8b7ffa17ec7d9126d6e..822085d8e2c4665262f1ce85bd5dd7e7dad2fc5f 100644 --- a/README.md +++ b/README.md @@ -13,33 +13,45 @@ Instructor: [Romain Vuillemot](romain.vuillemot@ec-lyon.fr) ## Outline -### Lecture 1 - **Data structures and complexity** | [notebook](01-introduction.ipynb) | [slides](01-introduction-slides.pdf) +### Lecture 1 - **Data structures and complexity** | [notebook](01-introduction.ipynb) | [slides](01-introduction-slides.pdf) | [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) -📖 [Think Python](pdf/thinkpython2.pdf) chapter 5 (Conditionals and recursion) and [Real Python](https://realpython.com/python-recursion/). +📖 [Think Python](pdf/thinkpython2.pdf) chapter 5 (Conditionals and recursion) and Real Python [recursion](https://realpython.com/python-recursion/). -### Lecture 3 - **Lists, search, sort** +### 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) -📖 [Think Python](pdf/thinkpython2.pdf) chapter 11 (lists), chapter 12 (tuples), [Python for Everybody](pdf/pythonlearn.pdf) chapter 8 (lists) and [Real Python](https://realpython.com/python-list/). +📖 [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/). -📝 Assignment 1 - Analyzing a Simple Dataset +--- -### Lecture 4 - **Divide and conquer and greedy algorithms** +📝 Assignment 1 - Analyzing a simple dataset -### Lecture 5 - **Dynamic programming** +--- - 📝Assignment 2 - Solving a problem with dynamic programming +### Lecture 4 - **Programming strategies** + +📖 [Divide & conquer](https://en.wikibooks.org/wiki/Algorithms/Divide_and_Conquer), [dynamic programing](https://en.wikibooks.org/wiki/Algorithms/Dynamic_Programming) and [greedy algorithms](https://en.wikibooks.org/wiki/Algorithms/Greedy_Algorithms) + +### Lecture 5 - **Trees** + +📖 [Problem Solving with Algorithms](pdf/problemsolving.pdf) chapter 6 (trees and tree algorithms) + +--- + +📝Assignment 2 - Solving a problem with dynamic programming + +--- Next topics: -1. **Advanced sorting** +1. **Stacks and queues** -2. **Hashing** +2. **Advanced data structures** -3. **Trees** +3. **Hashing** 4. **Trees and their representation** @@ -47,13 +59,16 @@ Next topics: 6. **Binary and n-trees** -7. **Graphs** +7. **Graphs** -8. **Graphs algorithms** +8. **Graphs algorithms** -9. **Graphs shortest path algorithm** +9. **Graphs shortest path algorithm** -## Books +## Books and ressources - [Think Python](pdf/thinkpython2.pdf), 2nd edition, by Allen B. Downey -- [Python for Everybody](pdf/pythonlearn.pdf), by Charles Severance \ No newline at end of file +- [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 +- 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/pdf/Dsa.pdf b/pdf/Dsa.pdf new file mode 100644 index 0000000000000000000000000000000000000000..abe92653999f42e44c1388f7216d6d943112d103 Binary files /dev/null and b/pdf/Dsa.pdf differ diff --git a/pdf/Python_Algorithms_Data_Structures.pdf b/pdf/Python_Algorithms_Data_Structures.pdf new file mode 100644 index 0000000000000000000000000000000000000000..60ca2094c0549d3d321498938108940e2ebb9313 Binary files /dev/null and b/pdf/Python_Algorithms_Data_Structures.pdf differ diff --git a/pdf/problemsolving.pdf b/pdf/problemsolving.pdf new file mode 100644 index 0000000000000000000000000000000000000000..e3bddf21a98610071a3de443c3906166446de234 Binary files /dev/null and b/pdf/problemsolving.pdf differ