Skip to content
Snippets Groups Projects
Commit afb43d01 authored by Romain Vuillemot's avatar Romain Vuillemot
Browse files

lab 6

parent e9bfc010
No related branches found
No related tags found
No related merge requests found
%% Cell type:markdown id:2a3fec41 tags:
NAME:
%% Cell type:markdown id:a701f259-d48a-43a8-aa7d-6f77c3896e5e tags:
# UE5 Fundamentals of Algorithms
# Lab 6: Programming strategies: Dynamic programming
%% Cell type:markdown id:6c24ca95-9c26-427c-ac1c-0a5f185140e9 tags:
---
%% Cell type:markdown id:cd8663e3-c5a5-41ec-b888-49bac1e82ef4 tags:
<details style="border: 1px">
<summary> How to use those notebooks</summary>
For each of the following questions:
- In the `# YOUR CODE HERE` cell, remove `raise NotImplementedError()` to write your code
- Write an example of use of your code or make sure the given examples and tests pass
- Add extra tests in the `#Tests` cell
</details>
%% Cell type:markdown id:d2673591-dbe2-45f2-b24d-f21ae1186770 tags:
## Exercise 1: Fibonacci
Write the Fibonacci sequence $T(n) = T(n-1) + T(n-2)$ using dynamic programming, in particular the _memoization_ mechanism.
%% Cell type:code id:a0ca630b-5a69-4e32-8e89-91afaec02c3e tags:
``` python
def fibonacci(n, memo = {}):
# YOUR CODE HERE
raise NotImplementedError()
```
%% Cell type:code id:c7baa400-bd44-4e35-a3cc-1d44e1711af5 tags:
``` python
# Example of use
fibonacci(10)
```
%% Cell type:code id:3b629a14-7c08-49e1-8cce-8ad320066eec tags:
``` python
# Tests
assert fibonacci(10) == 55
```
%% Cell type:markdown id:a45c7015-d59b-4ab3-96f7-d5eaf26273fc tags:
## Exercise 2: Knapsack
Propose a dynamic programming solution for the knapsack problem (as defined in the previous lab). Here is the general case (where the weights availability is 1, which means there can be any duplicate in the solution):
$
dp[i][w] =
\begin{cases}
0 & \text{if } i = 0 \text{ or } w = 0 \\
dp[i-1][w] & \text{if } w_i > w \\
\max(dp[i-1][w], w_i + dp[i-1][w - w_i]) & \text{otherwise}
\end{cases}$
Your algorithm should return the weight the solution managed to reach, and the list of weights.
%% Cell type:code id:e77956b0-b286-4347-858d-81468f6a8017 tags:
``` python
def dynamic_knapsack(W, wt):
# YOUR CODE HERE
raise NotImplementedError()
```
%% Cell type:code id:d92f7880-6a1d-4b43-a37e-71ae9d92bb6d tags:
``` python
# Example of use
weights = [2, 3, 4, 5]
max_weight = 5
dynamic_knapsack(max_weight, weights)
```
%% Cell type:markdown id:d27f1afa-da6d-45dd-81c9-c99a8cdf1855 tags:
Compare to the greedy version which solution is given below:
%% Cell type:code id:3c67509f-a10d-4452-9637-1592d6a3aea1 tags:
``` python
def greedy_knapsack(W, w):
w.sort(reverse=True)
n = len(w)
remaining_items = list(range(n))
total_weight = 0
knapsack = []
while remaining_items and total_weight < W:
best_weight = float('inf')
best_item = None
for i in remaining_items:
if w[i] < best_weight:
best_weight = w[i]
best_item = i
if best_item is not None:
weight = w[best_item]
knapsack.append(weight)
total_weight += weight
remaining_items.remove(best_item)
return total_weight, knapsack
```
%% Cell type:code id:a12fc960-a59e-410d-976e-9c65f822cedc tags:
``` python
assert greedy_knapsack(5, [2, 3, 4, 5]) == (5, [2, 3])
```
%% Cell type:markdown id:de7cf7d9-6a75-49e4-a143-84c43174d68e tags:
## Exercise 3: Longest increasing subsequence
Given an array of integers, write a function to find the length of the longest increasing subsequence. For intance, given the sequence `[10, 9, 2, 5, 3, 7, 101, 18]` the result is `[2, 3, 7, 101]` (size `4`). Note that the increasing numbers are not necessarily immediately consecutive.
%% Cell type:markdown id:341924a7-5e56-4ead-8fb0-921cb7edf935 tags:
Write a dynamic programming approach by following those steps:
1. Create a `dp` array of size \(n\), where \(dp[i]\) represents the length of the longest incresing sequence ending at index \(i\)
2. Initialize all values in `dp` to 1, since the longest incresing sequence at each index is at least the element itself
3. For each pair of indices \(i\) and \(j\) where \(j < i\):
- If \(nums[j] < nums[i]\), update \(dp[i] = max(dp[i], dp[j] + 1)\)
4. The length of the longest increasing sequence is the maximum value in the `dp` array
%% Cell type:code id:e09b072d-78f3-4ce1-9203-c85cf0e464ae tags:
``` python
def longest_dynprog(L):
# YOUR CODE HERE
raise NotImplementedError()
```
%% Cell type:code id:8d29b1e7-d541-4363-94cf-e928944d019f tags:
``` python
L = [10, 9, 2, 5, 3, 7, 101, 18]
assert longest_dynprog(L) == 4
```
%% Cell type:markdown id:358e492b-9a9b-499f-a49b-6a90c530b0fa tags:
Finally, you may implement a more efficient solution using binary search like explained [in this book](https://cp-algorithms.com/sequences/longest_increasing_subsequence.html).
First write a binary search function:
%% Cell type:code id:64570eb7-a5e6-4282-9b41-730227337658 tags:
``` python
def binary_search(sub, target):
# YOUR CODE HERE
raise NotImplementedError()
```
%% Cell type:code id:dcd76d9f-2f4d-40fb-8ca6-0ce3acc40070 tags:
``` python
assert binary_search([1, 2, 3], 2) == [1, 2, 3].index(2)
```
%% Cell type:markdown id:4165d800-4a37-4d8c-99f0-f55f995c747f tags:
Now write a function that uses the above binary search function to return the longest sequence:
%% Cell type:code id:418a8882-8d04-4ef6-9718-307a4056d800 tags:
``` python
def longest_binary(L):
# YOUR CODE HERE
raise NotImplementedError()
```
%% Cell type:code id:b6b27c2b-5758-496c-975b-a732e71d1791 tags:
``` python
L = [10, 9, 2, 5, 3, 7, 101, 18]
assert longest_binary(nums) == 4
```
%% Cell type:markdown id:46eedf29-dac1-4373-9f2c-98275cd749b2 tags:
## Exercise 4: Find a target sum
You are given a list of integers `L` and a target sum `t`. You need to return the number of different ways you can assign a + or - sign to each number in the list such that the sum equals target.
```
L = [1, 1, 1, 1, 1]
t = 3
```
There are 5 possible solutions (`[1, 1, -1, 1, 1]`, etc).
%% Cell type:markdown id:89555ffc-d9b1-4386-a278-4a583dca2bdc tags:
Generate a brute force approach like in the previous lab by using the `product` method.
%% Cell type:code id:7f98f9bb-d1c5-46c7-9ce8-6ccee5087e69 tags:
``` python
from itertools import product
def find_target_brut(L, target):
# YOUR CODE HERE
raise NotImplementedError()
```
%% Cell type:code id:efd683c1-1be1-4bf3-a424-f59cbfdd1160 tags:
``` python
L = [1, 1, 1, 1, 1]
t = 3
assert find_target_brut([1, 1, 1, 1, 1], t) == 5
```
%% Cell type:markdown id:ee303057-a1c2-47cd-a9b3-8f11747e1b3e tags:
Now write a dynamic programming solution by following the instructions below:
Before proceeding, check for two conditions that would make it impossible to achieve the target:
1. If the total sum \( s \) is less than the target, it's impossible to form a subset equal to the target
2. If \( s - target \) is odd, you cannot split the array into two subsets with integer sums that have the required difference
Next, initialize a dynamic programming (dp) array of size \( n + 1 \) with all values set to zero, except for `dp[0]`, which is set to 1. This means there is one way to achieve a sum of zero (by choosing no number).
Then, iterate through each number \( v \) in `L`. For each number, iterate backward through the dp array from \( n \) down to \( v \) to avoid recomputing values that rely on the current index. This ensures that we don't count the same combination more than once.
Update the dp array by adding the number of ways to achieve a sum of \( j \) without including the current number \( v \) (i.e., `dp[j - v]`). This accumulates the number of ways to form a sum of \( j \) by either including or excluding the current number \( v \).
%% Cell type:code id:49c42188-c753-46dc-a8c7-8de377b9014b tags:
``` python
def find_target_dynprog(L, target):
# YOUR CODE HERE
raise NotImplementedError()
```
%% Cell type:code id:c1585467-2783-460c-b6ac-0cf2252112b8 tags:
``` python
# Example usage
find_target_dynprog([1, 1, 1, 1, 1], t) # 5
```
%% Cell type:code id:d60099d5-335d-494b-bb8a-3cbada63bf94 tags:
``` python
# Tests
L = [1, 1, 1, 1, 1]
t = 3
assert find_target_dynprog([1, 1, 1, 1, 1], t) == 5
```
%% Cell type:code id:500075c4-8084-41c3-aa1d-b98a7137c1e3 tags:
``` python
```
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment