From abc40d69d5232cf294906b34713af2343492a694 Mon Sep 17 00:00:00 2001 From: Romain Vuillemot <romain.vuillemot@gmail.com> Date: Wed, 23 Oct 2024 18:13:18 +0200 Subject: [PATCH] Solution lab 2 --- labs-solutions/02-recursion-exercises.ipynb | 1325 +++++++++++++++++++ 1 file changed, 1325 insertions(+) create mode 100644 labs-solutions/02-recursion-exercises.ipynb diff --git a/labs-solutions/02-recursion-exercises.ipynb b/labs-solutions/02-recursion-exercises.ipynb new file mode 100644 index 0000000..bd31821 --- /dev/null +++ b/labs-solutions/02-recursion-exercises.ipynb @@ -0,0 +1,1325 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "id": "a4e4fad3", + "metadata": { + "slideshow": { + "slide_type": "slide" + } + }, + "source": [ + "# UE5 Fundamentals of Algorithms\n", + "# Lab 2: Recursion" + ] + }, + { + "cell_type": "markdown", + "id": "a8adef9b", + "metadata": { + "slideshow": { + "slide_type": "skip" + } + }, + "source": [ + "---" + ] + }, + { + "cell_type": "markdown", + "id": "eee7125e-cd0b-4aff-ac6d-fba530b13050", + "metadata": { + "tags": [] + }, + "source": [ + "For each of the following questions:\n", + "- In the `# YOUR CODE HERE` cell, remove `raise NotImplementedError()` to write your code\n", + "- Write an example of use of your code or make sure the given examples and tests pass\n", + "- Add extra tests in the `#Tests` cell\n", + "\n", + "Recall on recursion:\n", + "\n", + "- Find a base case to stop the recursion\n", + "- Fin a decomposition of the problem to reach it\n", + "- Don't reach the Python recursion limits or infinite loops\n", + "\n", + "To compare iterative and recursive functions you may use the following time comparison functions:" + ] + }, + { + "cell_type": "code", + "execution_count": 11, + "id": "f6c23281-9c3d-488a-acb9-069964faff4b", + "metadata": { + "tags": [] + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Elapsed time: 1.0082 seconds\n" + ] + } + ], + "source": [ + "import time\n", + "t1 = time.time()\n", + "# YOUR CODE\n", + "time.sleep(1)\n", + "dt = time.time() - t1\n", + "print(f\"Elapsed time: {dt:.4f} seconds\")" + ] + }, + { + "cell_type": "markdown", + "id": "568202fd", + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, + "source": [ + "### Example: 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": 16, + "id": "431fe8c1-91d1-40f3-a7a4-f4a3770a4a01", + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "def find_maximum_iterative(L): \n", + " if len(L) == 0:\n", + " raise ValueError(\"the list is empty\")\n", + "\n", + " max_val = L[0]\n", + " for num in L:\n", + " if num > max_val:\n", + " max_val = num\n", + " return max_val" + ] + }, + { + "cell_type": "code", + "execution_count": 17, + "id": "f6baae3c-3660-4add-ab4b-48016cba3030", + "metadata": { + "tags": [] + }, + "outputs": [ + { + "data": { + "text/plain": [ + "9" + ] + }, + "execution_count": 17, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "# Example of use\n", + "find_maximum_iterative([1, 3, 5, 7, 9]) # 9" + ] + }, + { + "cell_type": "code", + "execution_count": 18, + "id": "e68b3e9a-418f-4950-9f27-18bb0fe90794", + "metadata": { + "nbgrader": { + "grade": true, + "grade_id": "correct_find_maximum_iterative", + "locked": true, + "points": 1, + "schema_version": 3, + "solution": false, + "task": false + }, + "tags": [] + }, + "outputs": [], + "source": [ + "# Tests\n", + "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": "772184f4-6af4-4996-9bb1-da46c31891f8", + "metadata": {}, + "source": [ + "To test exceptions you can use the following code:" + ] + }, + { + "cell_type": "code", + "execution_count": 19, + "id": "a4201264-48f2-44f3-817b-a008500aed0c", + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "try:\n", + " find_maximum_iterative([])\n", + "except ValueError:\n", + " assert True" + ] + }, + { + "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 to find the max value in a list of integers. You may use the `max()` function for the recursive call but not as a unique solution. Compare with the iterative version from the example." + ] + }, + { + "cell_type": "code", + "execution_count": 22, + "id": "07668fd8", + "metadata": { + "nbgrader": { + "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", + " ### BEGIN SOLUTION\n", + " if len(L) == 1:\n", + " return L[0]\n", + " else:\n", + " return max(L[0], find_maximum_recursive(L[1:]))\n", + " ### END SOLUTION" + ] + }, + { + "cell_type": "code", + "execution_count": 31, + "id": "f9784710-4b2b-434c-bc47-da46fa410749", + "metadata": { + "tags": [] + }, + "outputs": [ + { + "data": { + "text/plain": [ + "9" + ] + }, + "execution_count": 31, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "# Example of use\n", + "find_maximum_recursive([1, 3, 5, 7, 9]) # 9" + ] + }, + { + "cell_type": "code", + "execution_count": 32, + "id": "9b0161f8-0539-4e5e-921c-1886e61c0783", + "metadata": { + "nbgrader": { + "grade": true, + "grade_id": "correct_find_maximum_recursive", + "locked": true, + "points": 1, + "schema_version": 3, + "solution": false, + "task": false + }, + "tags": [] + }, + "outputs": [], + "source": [ + "# Tests\n", + "assert find_maximum_iterative([-10, -5, -8, -2, -7]) == find_maximum_recursive([-10, -5, -8, -2, -7])" + ] + }, + { + "cell_type": "markdown", + "id": "25ba2ca3-b4f6-4f1a-8b95-b3e1394ee834", + "metadata": {}, + "source": [ + "Hints: find don't use `for` or `sort`." + ] + }, + { + "cell_type": "markdown", + "id": "005efd41-baa1-4505-b80e-3644d61ea094", + "metadata": {}, + "source": [ + "### Exercise 2: Sum of digits\n", + "\n", + "Write a recursive function that calculates the sum of the digits so that given a positive integer (e.g. `123` of type `int`), it return the sum of digits it contains (e.g. for `123` it returns `6`)." + ] + }, + { + "cell_type": "code", + "execution_count": 18, + "id": "de424156-0b9b-41d0-8e38-ce335f35cec0", + "metadata": { + "nbgrader": { + "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", + " ### BEGIN SOLUTION\n", + " if n < 10:\n", + " return n\n", + " else:\n", + " return n % 10 + sum_of_digits(n // 10)\n", + " ### END SOLUTION" + ] + }, + { + "cell_type": "code", + "execution_count": 19, + "id": "cec0caca-cb2c-4e4d-b004-27b3cf2ff611", + "metadata": { + "tags": [] + }, + "outputs": [ + { + "data": { + "text/plain": [ + "1" + ] + }, + "execution_count": 19, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "# Example of use\n", + "sum_of_digits(10) # 1" + ] + }, + { + "cell_type": "code", + "execution_count": 20, + "id": "bf276ca2-48ed-4e87-80f2-776f54b7062b", + "metadata": { + "nbgrader": { + "grade": true, + "grade_id": "correct_sum_of_digits", + "locked": true, + "points": 1, + "schema_version": 3, + "solution": false, + "task": false + }, + "tags": [] + }, + "outputs": [], + "source": [ + "# Tests\n", + "assert sum_of_digits(10) == sum_of_digits(100000)\n", + "assert sum_of_digits(0) == 0\n", + "assert sum_of_digits(123) == 6\n", + "assert sum_of_digits(56) == 11" + ] + }, + { + "cell_type": "markdown", + "id": "e2de630a-f9bd-4d45-959b-430e34cc9044", + "metadata": { + "tags": [] + }, + "source": [ + "### Exercise 3: Calculate the n-th power value\n", + "\n", + "Calculate the n-th power of a number using a recursive function." + ] + }, + { + "cell_type": "code", + "execution_count": 39, + "id": "abca03a0-7bcd-4ee6-b109-ff2f2da52bb6", + "metadata": { + "nbgrader": { + "grade": false, + "grade_id": "power", + "locked": false, + "schema_version": 3, + "solution": true, + "task": false + }, + "tags": [] + }, + "outputs": [], + "source": [ + "def power(base, exponent):\n", + " ### BEGIN SOLUTION\n", + " if exponent == 0:\n", + " return 1\n", + " else:\n", + " return base * power(base, exponent - 1)\n", + " ### END SOLUTION" + ] + }, + { + "cell_type": "code", + "execution_count": 52, + "id": "abddd3b1-f75f-4cb6-a09e-54eed489c5b0", + "metadata": { + "tags": [] + }, + "outputs": [ + { + "data": { + "text/plain": [ + "1024" + ] + }, + "execution_count": 52, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "# Example of use\n", + "power(2, 10) # 1024" + ] + }, + { + "cell_type": "code", + "execution_count": 38, + "id": "8a6605fe-4f6f-45de-84a3-7601e2e2e6f6", + "metadata": { + "nbgrader": { + "grade": true, + "grade_id": "correct_power", + "locked": true, + "points": 1, + "schema_version": 3, + "solution": false, + "task": false + }, + "tags": [] + }, + "outputs": [], + "source": [ + "# Tests\n", + "assert power(2, 10) == 1024\n", + "assert power(2, 0) == 1\n", + "assert power(5, 3) == 125\n", + "assert power(1, 0) == 1 ** 0" + ] + }, + { + "cell_type": "markdown", + "id": "715100d3-fc21-49b9-a66d-b5243b4a279d", + "metadata": { + "tags": [] + }, + "source": [ + "### Exercise 4: Reverse a string\n", + "\n", + "Write a recursive function that takes a string s as input and returns the reversed version of the string." + ] + }, + { + "cell_type": "code", + "execution_count": 22, + "id": "ddc9826a-0863-4777-a08d-81b66652b5a5", + "metadata": { + "nbgrader": { + "grade": false, + "grade_id": "reverse_string", + "locked": false, + "schema_version": 3, + "solution": true, + "task": false + }, + "tags": [] + }, + "outputs": [], + "source": [ + "def reverse_string(s):\n", + " ### BEGIN SOLUTION\n", + " if len(s) == 0 or len(s) == 1:\n", + " return s\n", + " else:\n", + " return reverse_string(s[1:]) + s[0]\n", + " ### END SOLUTION" + ] + }, + { + "cell_type": "code", + "execution_count": 23, + "id": "13acad7e-d03c-4ea6-ad86-baf02e0910eb", + "metadata": { + "tags": [] + }, + "outputs": [ + { + "data": { + "text/plain": [ + "'niamoR'" + ] + }, + "execution_count": 23, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "# Example of use\n", + "reverse_string(\"Romain\") # niamoR" + ] + }, + { + "cell_type": "code", + "execution_count": 24, + "id": "453c8e04-6cd9-4581-a206-dd479b6115cd", + "metadata": { + "nbgrader": { + "grade": true, + "grade_id": "correct_reverse_string", + "locked": true, + "points": 1, + "schema_version": 3, + "solution": false, + "task": false + }, + "tags": [] + }, + "outputs": [], + "source": [ + "# Tests\n", + "assert reverse_string(\"\") == \"\"\n", + "assert reverse_string(\"AA\") == \"AA\"\n", + "assert reverse_string(\"ABC\") == \"CBA\"" + ] + }, + { + "cell_type": "markdown", + "id": "c1587148-f816-4af2-8f3a-6d8a8480d54d", + "metadata": { + "tags": [] + }, + "source": [ + "Write another version in an iterative way and compare with the recursive one." + ] + }, + { + "cell_type": "code", + "execution_count": 25, + "id": "159b6d78-03ae-4cf8-8545-e822b7160b32", + "metadata": { + "nbgrader": { + "grade": false, + "grade_id": "cell-ead02fa889911e42", + "locked": false, + "schema_version": 3, + "solution": true, + "task": false + }, + "tags": [] + }, + "outputs": [], + "source": [ + "def iterative_reverse_string(s):\n", + " ### BEGIN SOLUTION\n", + " reversed_str = \"\"\n", + " for char in s:\n", + " reversed_str = char + reversed_str\n", + " return reversed_str\n", + " ### END SOLUTION" + ] + }, + { + "cell_type": "code", + "execution_count": 26, + "id": "0dcdbd99-5f57-4d1c-bc31-8f8afc617d0e", + "metadata": { + "tags": [] + }, + "outputs": [ + { + "data": { + "text/plain": [ + "'niamoR'" + ] + }, + "execution_count": 26, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "iterative_reverse_string(\"Romain\")" + ] + }, + { + "cell_type": "code", + "execution_count": 48, + "id": "43e10b0c", + "metadata": {}, + "outputs": [], + "source": [ + "# Tests\n", + "assert iterative_reverse_string(\"Romain\") == reverse_string(\"Romain\")" + ] + }, + { + "cell_type": "markdown", + "id": "5ab8f3c9-ddee-45ab-a013-fdd67d9853e0", + "metadata": {}, + "source": [ + "### Exercise 5: Convert an interative suite into a recursive tail function\n", + "\n", + "Convert an iterative function into a recursive tail function (a function where the last operation is the recursive call)." + ] + }, + { + "cell_type": "code", + "execution_count": 54, + "id": "219add7f", + "metadata": { + "slideshow": { + "slide_type": "subslide" + }, + "tags": [] + }, + "outputs": [], + "source": [ + "# iterative function\n", + "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": 55, + "id": "0787df24-8234-4286-b910-5f9e456dd279", + "metadata": { + "tags": [] + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "The result is 15\n" + ] + } + ], + "source": [ + "# Example of use\n", + "print(\"The result is {}\".format(sequence(3)))" + ] + }, + { + "cell_type": "code", + "execution_count": 56, + "id": "9c17cf1b-6d05-4589-af2b-c05cfcc33202", + "metadata": { + "nbgrader": { + "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", + " ### BEGIN SOLUTION\n", + " if n == 0:\n", + " return 1\n", + " return 2 * sequence_recursive_tail(n - 1) + 1\n", + " ### END SOLUTION" + ] + }, + { + "cell_type": "code", + "execution_count": 57, + "id": "43507c43-de61-414d-b389-c0a771ad9e0c", + "metadata": { + "tags": [] + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "The result is still 15\n" + ] + } + ], + "source": [ + "# Example of use\n", + "print(\"The result is still {}\".format(sequence_recursive_tail(3)))" + ] + }, + { + "cell_type": "code", + "execution_count": 59, + "id": "dd923b7c-0cab-4678-8dc3-aad2ab9b25f9", + "metadata": { + "nbgrader": { + "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": [ + "# Tests\n", + "assert sequence_recursive_tail(3) == sequence(3) == 15" + ] + }, + { + "cell_type": "markdown", + "id": "3c28b36a", + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, + "source": [ + "### Exercise 6: Check if a word is a palindrom\n", + "\n", + "Write a function that takes a string as input and returns `True` if the word is a palindrome (i.e., it reads the same forwards and backwards), and `False` otherwise." + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "id": "51bb3d08", + "metadata": { + "nbgrader": { + "grade": false, + "grade_id": "annagram_rec", + "locked": false, + "schema_version": 3, + "solution": true, + "task": false + }, + "tags": [] + }, + "outputs": [], + "source": [ + "def palindrom_rec(word):\n", + " ### BEGIN SOLUTION\n", + " if len(word) < 2: \n", + " return True\n", + " return (word[0] == word[-1]) and palindrom_rec(word[1:len(word)-1])\n", + " ### END SOLUTION" + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "id": "0c279628-9b96-4687-8e20-a954ab646e0f", + "metadata": { + "tags": [] + }, + "outputs": [ + { + "data": { + "text/plain": [ + "True" + ] + }, + "execution_count": 3, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "# Example of use\n", + "palindrom_rec(\"laval\")" + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "id": "cf6fa61a-7c6f-4a32-96c2-b9fd50deacc6", + "metadata": { + "nbgrader": { + "grade": true, + "grade_id": "correct_annagram_rec", + "locked": true, + "points": 1, + "schema_version": 3, + "solution": false, + "task": false + }, + "tags": [] + }, + "outputs": [], + "source": [ + "# Tests\n", + "assert palindrom_rec(\"\")\n", + "assert palindrom_rec(\"AA\")\n", + "assert not palindrom_rec(\"ABC\")\n", + "assert palindrom_rec(\"ABA\")\n", + "assert palindrom_rec(\"LAVAL\")\n", + "assert palindrom_rec(\"toto\") == False" + ] + }, + { + "cell_type": "markdown", + "id": "798c2875-7940-488a-8458-ad08f6a71c70", + "metadata": {}, + "source": [ + "### Exercise 7: Calculate GCD\n", + "\n", + "Given two positive integers, write a recursive function to calculate their Greatest Common Divisor (GCD). The GCD of two integers is the largest integer that divides both numbers without leaving a remainder. Compare with the following iterative function:" + ] + }, + { + "cell_type": "code", + "execution_count": 66, + "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": 67, + "id": "bf6e1a76", + "metadata": { + "nbgrader": { + "grade": false, + "grade_id": "recursive_gcd", + "locked": false, + "schema_version": 3, + "solution": true, + "task": false + }, + "tags": [] + }, + "outputs": [], + "source": [ + "def recursive_gcd(a, b):\n", + " ### BEGIN SOLUTION\n", + " if b == 0:\n", + " return a\n", + " else:\n", + " return recursive_gcd(b, a % b)\n", + " ### END SOLUTION" + ] + }, + { + "cell_type": "code", + "execution_count": 68, + "id": "4f1feace", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "2" + ] + }, + "execution_count": 68, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "# Example of use\n", + "recursive_gcd(10, 2)" + ] + }, + { + "cell_type": "code", + "execution_count": 69, + "id": "e6ff1765-ff4b-49a5-80d3-684d2627e961", + "metadata": { + "nbgrader": { + "grade": true, + "grade_id": "correct_recursive_gcd", + "locked": true, + "points": 1, + "schema_version": 3, + "solution": false, + "task": false + }, + "tags": [] + }, + "outputs": [], + "source": [ + "# Tests\n", + "assert iterative_gcd(10, 2) == recursive_gcd(10, 2)" + ] + }, + { + "cell_type": "markdown", + "id": "d8b05edf-9536-4fc1-bfcc-ddbbeee426fc", + "metadata": {}, + "source": [ + "### Exercise 8: Check if a list is sorted\n", + "\n", + "Write a recursive function that takes a list of numbers as input and returns `True` if the list is sorted in non-decreasing order and `False` otherwise." + ] + }, + { + "cell_type": "code", + "execution_count": 71, + "id": "1661dfb5-88f2-411f-8fe2-63bbaa29ce72", + "metadata": { + "nbgrader": { + "grade": false, + "grade_id": "calculate_average_recursive", + "locked": false, + "schema_version": 3, + "solution": true, + "task": false + }, + "tags": [] + }, + "outputs": [], + "source": [ + "def is_sorted(L):\n", + " ### BEGIN SOLUTION\n", + " if len(L) <= 1:\n", + " return True\n", + " else:\n", + " return L[0] <= L[1] and is_sorted(L[1:])\n", + " ### END SOLUTION" + ] + }, + { + "cell_type": "code", + "execution_count": 72, + "id": "0c5c72c6-3237-4f98-ab96-50a1838b833f", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "True" + ] + }, + "execution_count": 72, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "is_sorted([1, 2, 3, 4, 5])" + ] + }, + { + "cell_type": "code", + "execution_count": 73, + "id": "9f18b6b7-d980-4a72-a2a8-3aa201003d21", + "metadata": { + "nbgrader": { + "grade": true, + "grade_id": "correct_calculate_average_recursive", + "locked": true, + "points": 1, + "schema_version": 3, + "solution": false, + "task": false + }, + "tags": [] + }, + "outputs": [], + "source": [ + "# Tests\n", + "assert is_sorted([2, 3])\n", + "assert is_sorted([])\n", + "assert is_sorted([3, 2]) == False" + ] + }, + { + "cell_type": "markdown", + "id": "79eef392-1d3d-46c0-aeee-ac805686e6f1", + "metadata": {}, + "source": [ + "### Exercise 9: Check for prime number\n", + "\n", + "Write a recursive function that checks if a given integer is a prime number. A prime number is a natural number greater than 1 that has no divisors other than 1 and itself." + ] + }, + { + "cell_type": "code", + "execution_count": 74, + "id": "ac374a08-11c9-47e6-ba11-419549911266", + "metadata": { + "nbgrader": { + "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", + " ### BEGIN SOLUTION\n", + " if n < 2:\n", + " return False\n", + " \n", + " if n == 2:\n", + " return True\n", + " \n", + " if n % divisor == 0:\n", + " return False\n", + " \n", + " if divisor * divisor > n:\n", + " return True\n", + " \n", + " return is_prime_recursive(n, divisor + 1)\n", + " ### END SOLUTION" + ] + }, + { + "cell_type": "code", + "execution_count": 75, + "id": "996fc91f", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "True" + ] + }, + "execution_count": 75, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "# Example of use\n", + "is_prime_recursive(3)" + ] + }, + { + "cell_type": "code", + "execution_count": 66, + "id": "5be1051c-3b60-4810-b855-6f8575ad6380", + "metadata": { + "nbgrader": { + "grade": true, + "grade_id": "correct_is_prime_recursive", + "locked": true, + "points": 1, + "schema_version": 3, + "solution": false, + "task": false + }, + "tags": [] + }, + "outputs": [], + "source": [ + "# Tests\n", + "assert is_prime_recursive(3) " + ] + }, + { + "cell_type": "markdown", + "id": "5423682d-c31f-4a8d-9a0f-6812de7b1ae3", + "metadata": {}, + "source": [ + "### Exercise 10: Count occurrences of an element in a list" + ] + }, + { + "cell_type": "code", + "execution_count": 79, + "id": "cfeb0ad0-ed82-499e-9af3-64923291a0e7", + "metadata": { + "nbgrader": { + "grade": false, + "grade_id": "count_occurrences", + "locked": false, + "schema_version": 3, + "solution": true, + "task": false + }, + "tags": [] + }, + "outputs": [], + "source": [ + "def count_occurrences(L, target, index=0):\n", + " ### BEGIN SOLUTION\n", + " if index == len(L):\n", + " return 0\n", + " \n", + " count = (1 if L[index] == target else 0)\n", + " \n", + " return count + count_occurrences(L, target, index + 1)\n", + " ### END SOLUTION" + ] + }, + { + "cell_type": "code", + "execution_count": 81, + "id": "49daec07-00b3-412e-ad44-5bafadbd9f36", + "metadata": { + "tags": [] + }, + "outputs": [ + { + "data": { + "text/plain": [ + "4" + ] + }, + "execution_count": 81, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "# Example of use\n", + "count_occurrences([1, 2, 3, 4, 2, 2, 5, 6, 2], 2)" + ] + }, + { + "cell_type": "code", + "execution_count": 68, + "id": "14a2eb85-1126-4506-93bb-4bf624d046b6", + "metadata": { + "nbgrader": { + "grade": true, + "grade_id": "correct_count_occurrences", + "locked": true, + "points": 1, + "schema_version": 3, + "solution": false, + "task": false + }, + "tags": [] + }, + "outputs": [], + "source": [ + "# Tests\n", + "assert count_occurrences([1, 2, 3, 4, 2, 2, 5, 6, 2], 2) == 4" + ] + }, + { + "cell_type": "markdown", + "id": "88255769-ea62-4910-a459-109cb03e94d2", + "metadata": {}, + "source": [ + "## Bonus" + ] + }, + { + "cell_type": "markdown", + "id": "e6bcb281-7f97-406a-ae20-729dddd518a3", + "metadata": { + "tags": [] + }, + "source": [ + "### Exercise 11: 2D Binary search\n", + "\n", + "We want to search for a target value in a 2D matrix where:\n", + "\n", + "- Each row is sorted in ascending order.\n", + "- The first element of each row is greater than the last element of the previous row.\n", + "\n", + "Implement a recursive function to solve this problem (hint: use a similar approach to binary search in a 1D array)." + ] + }, + { + "cell_type": "code", + "execution_count": 101, + "id": "e3e14407-2567-4531-bb8e-b35a6ba6d036", + "metadata": { + "nbgrader": { + "grade": false, + "grade_id": "cell-fba8f66061fb46f3", + "locked": false, + "schema_version": 3, + "solution": true, + "task": false + }, + "tags": [] + }, + "outputs": [], + "source": [ + "def binary_search_2D(matrix, target, left=0, right=None):\n", + " ### BEGIN SOLUTION\n", + " if right is None:\n", + " if not matrix or not matrix[0]:\n", + " return False\n", + " \n", + " rows = len(matrix)\n", + " cols = len(matrix[0])\n", + " right = rows * cols - 1\n", + "\n", + " if left > right: # base case\n", + " return False\n", + "\n", + " mid = (left + right) // 2\n", + " mid_value = matrix[mid // len(matrix[0])][mid % len(matrix[0])]\n", + "\n", + " if mid_value == target:\n", + " return True\n", + " elif mid_value < target:\n", + " return binary_search_2D(matrix, target, mid + 1, right) \n", + " else:\n", + " return binary_search_2D(matrix, target, left, mid - 1)\n", + " ### END SOLUTION" + ] + }, + { + "cell_type": "code", + "execution_count": 95, + "id": "291b699a-519c-41ba-9a7d-1cb055f78b40", + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "m = [\n", + " [1, 3, 5, 7],\n", + " [10, 11, 16, 20],\n", + " [23, 30, 34, 50],\n", + " [60, 70, 80, 90]\n", + "]" + ] + }, + { + "cell_type": "code", + "execution_count": 98, + "id": "6c7215d2-f99a-41d1-a931-3623ab094674", + "metadata": { + "tags": [] + }, + "outputs": [ + { + "data": { + "text/plain": [ + "True" + ] + }, + "execution_count": 98, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "# Example of use\n", + "binary_search_2D(m, 3) # True" + ] + }, + { + "cell_type": "code", + "execution_count": 100, + "id": "38f7f201-26d9-42c3-86dc-ef8712eb4167", + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "# Tests\n", + "assert binary_search_2D(m, 11) == True\n", + "assert binary_search_2D(m, 15) == False" + ] + }, + { + "cell_type": "markdown", + "id": "d30f78d3-7916-4464-952d-8db56bc4cdb8", + "metadata": { + "tags": [] + }, + "source": [ + "## Other exerices\n", + "\n", + "- Write a recursive version of the Ackerman function as defined [in this page](https://mathworld.wolfram.com/AckermannFunction.html) - [solution]( https://github.com/chkydebug/Ackerman-python/blob/main/Ackerman.py)\n", + "- Solve the [Tower of Hanoï problem](https://en.wikipedia.org/wiki/Tower_of_Hanoi) in a recursive way" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "53fb4e2e-a123-4145-94d0-0323c886e1bd", + "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 +} -- GitLab