first commit

This commit is contained in:
2023-10-09 11:15:06 +02:00
commit e1ab376e72
56 changed files with 5734 additions and 0 deletions

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,250 @@
#!/usr/bin/env python
# coding: utf-8
# In[33]:
# Data
amounts = [12.35, 12.35*2, 12.35*3, 12.35*4, 12.35*5, 12.35*6, 12.35*7, 12.35*8, 12.35*9, 12.35*10]
coin_list = [
[0.2, 0.1, 0.05],
[1, 0.2, 0.1, 0.05],
[2, 1, 0.2, 0.1, 0.05],
[5, 2, 1, 0.2, 0.1, 0.05],
[5, 2, 1, 0.5, 0.2, 0.1, 0.05],
[5, 2, 1, 0.5, 0.2, 0.1, 0.05, 0.02],
[5, 2, 1, 0.5, 0.2, 0.1, 0.05, 0.02, 0.01]
]
import time
import matplotlib.pyplot as plt
# In[34]:
# Greedy
def greedy_make_change(amount, coins):
i = 0
change = []
while amount > 0 and len(coins) > i:
# print(str(round(amount//coins[i])) + " Coins of " + str(coins[i]) + "€")
for j in range(round(amount//coins[i])):
change.append(coins[i])
amount = round(amount%coins[i], 2)
i = i+1
if amount > 0:
print(f"Cannot make exact change for {amount:.2f}")
return change
# In[35]:
# Iterative
# Function to count occurrences of items in a list
def count_occurrences(array):
counts = {}
for item in array:
if item in counts:
counts[item] += 1 # If the item is already in the dictionary, increment its count
else:
counts[item] = 1 # If the item is not in the dictionary, add it with a count of 1
return counts
# Function to calculate all combinations of coins to make a specific amount
def calculate_change_combinations(amount, coins):
# Convert euro amounts to cents for calculations
amount_cents = int(amount * 100)
coin_values_cents = [int(coin * 100) for coin in coins]
# Initialize a list to store combinations and their counts
combinations = []
stack = [(0, [], 0)] # (current amount in cents, current combination, current coin index)
while stack:
current_amount, current_combination, current_coin_index = stack.pop()
# If the current combination sums up to the target amount, add it to the list
if current_amount == amount_cents:
combinations.append(current_combination)
# If the current amount is less than the target amount and there are more coins to consider
elif current_amount < amount_cents and current_coin_index < len(coin_values_cents):
coin = coin_values_cents[current_coin_index]
max_count = (amount_cents - current_amount) // coin # Maximum count of the current coin
# Try adding different counts of the current coin to explore possibilities
for count in range(max_count + 1):
new_amount = current_amount + count * coin
new_combination = current_combination + [coins[current_coin_index]] * count
# Push the new state onto the stack for further exploration
stack.append((new_amount, new_combination, current_coin_index + 1))
# Print the total number of combinations
# print(f"Total number of combinations: {len(combinations)}")
return combinations
# In[36]:
# Recursive
def make_change_recursive(amount, coins, start, current_change, result):
if amount == 0:
result.append(current_change[:])
return
for i in range(start, len(coins)):
coin_cents = round(coins[i] * 100)
if amount >= coin_cents:
current_change.append(coins[i])
make_change_recursive(amount - coin_cents, coins, i, current_change, result)
current_change.pop()
return result
# In[50]:
greedy_times_coin_list = []
greedy_labels_coin_list = []
coins_list_copy = coin_list.copy()
for coins in coins_list_copy:
start = time.perf_counter()
greedy_make_change(amounts[0], coins)
end = time.perf_counter()
greedy_times_coin_list.append(end - start)
greedy_labels_coin_list.append(str(len(coins)))
greedy_times_amount_list = []
greedy_labels_amount_list = []
# Plot a graph
plt.figure(figsize=(10, 6))
# NO BAR
plt.plot(greedy_labels_coin_list[1:], greedy_times_coin_list[1:], marker='o', linestyle='solid')
plt.xlabel('Coins')
plt.ylabel('Time (s)')
plt.title('Greedy Algorithm using different coins to make change for 12.35€')
plt.show()
for amount in amounts:
start = time.perf_counter()
greedy_make_change(amount, coin_list[-1])
end = time.perf_counter()
greedy_times_amount_list.append(end - start)
greedy_labels_amount_list.append(str(amount))
# NO BAR
plt.plot(greedy_labels_amount_list[1:], greedy_times_amount_list[1:], marker='o', linestyle='solid')
plt.xlabel('Amount')
plt.ylabel('Time (s)')
plt.title('Greedy Algorithm using 9 coins to make change for different amounts')
plt.show()
# In[47]:
iterative_times_coin_list = []
iterative_labels_coin_list = []
coins_list_copy = coin_list.copy()
for coins in coins_list_copy[:5]:
start = time.perf_counter()
calculate_change_combinations(amounts[0], coins)
end = time.perf_counter()
iterative_times_coin_list.append(end - start)
iterative_labels_coin_list.append(str(len(coins)))
# Plot a graph
plt.figure(figsize=(10, 6))
# NO BAR
plt.plot(iterative_labels_coin_list[1:], iterative_times_coin_list[1:], marker='o', linestyle='solid')
plt.xlabel('Coins')
plt.ylabel('Time (s)')
plt.title('Iterative Algorithm generating all the possibilities using different coins to make change for 12.35€')
plt.show()
# The complexity increase more when we add coins that are smaller. We can see that adding 0.02 and 0.01 have more impact than adding 2, and 5.
# In[46]:
recursive_times_coin_list = []
recursive_labels_coin_list = []
coins_list_copy = coin_list.copy()
for coins in coins_list_copy[:5]:
# print(coins)
start = time.perf_counter()
make_change_recursive(amounts[0]*100, coins, 0, [], [])
end = time.perf_counter()
recursive_times_coin_list.append(end - start)
recursive_labels_coin_list.append(str(len(coins)))
# Plot a graph
plt.figure(figsize=(10, 6))
# NO BAR
plt.plot(recursive_labels_coin_list[1:], recursive_times_coin_list[1:], marker='o', linestyle='solid')
plt.xlabel('Coins')
plt.ylabel('Time (s)')
plt.title('Recursive Algorithm generating all the possibilities using different coins to make change for 12.35€')
plt.show()
# Complexity seems polynomial or exponential, but it is not possible to test using this problem as it takes to much time to run on all the list of coins.
# In[45]:
# Export all results to json
import json
# Greedy
greedy_results = {
"greedy_times_coin_list": greedy_times_coin_list,
"greedy_labels_coin_list": greedy_labels_coin_list,
"greedy_times_amount_list": greedy_times_amount_list,
"greedy_labels_amount_list": greedy_labels_amount_list
}
with open('greedy_results.json', 'w') as fp:
json.dump(greedy_results, fp)
# Iterative
iterative_results = {
"iterative_times_coin_list": iterative_times_coin_list,
"iterative_labels_coin_list": iterative_labels_coin_list
}
with open('iterative_results.json', 'w') as fp:
json.dump(iterative_results, fp)
# Recursive
recursive_results = {
"recursive_times_coin_list": recursive_times_coin_list,
"recursive_labels_coin_list": recursive_labels_coin_list
}
with open('recursive_results.json', 'w') as fp:
json.dump(recursive_results, fp)

View File

@@ -0,0 +1,271 @@
```python
# Data
amounts = [12.35, 12.35*2, 12.35*3, 12.35*4, 12.35*5, 12.35*6, 12.35*7, 12.35*8, 12.35*9, 12.35*10]
coin_list = [
[0.2, 0.1, 0.05],
[1, 0.2, 0.1, 0.05],
[2, 1, 0.2, 0.1, 0.05],
[5, 2, 1, 0.2, 0.1, 0.05],
[5, 2, 1, 0.5, 0.2, 0.1, 0.05],
[5, 2, 1, 0.5, 0.2, 0.1, 0.05, 0.02],
[5, 2, 1, 0.5, 0.2, 0.1, 0.05, 0.02, 0.01]
]
import time
import matplotlib.pyplot as plt
```
```python
# Greedy
def greedy_make_change(amount, coins):
i = 0
change = []
while amount > 0 and len(coins) > i:
# print(str(round(amount//coins[i])) + " Coins of " + str(coins[i]) + "€")
for j in range(round(amount//coins[i])):
change.append(coins[i])
amount = round(amount%coins[i], 2)
i = i+1
if amount > 0:
print(f"Cannot make exact change for {amount:.2f}")
return change
```
```python
# Iterative
# Function to count occurrences of items in a list
def count_occurrences(array):
counts = {}
for item in array:
if item in counts:
counts[item] += 1 # If the item is already in the dictionary, increment its count
else:
counts[item] = 1 # If the item is not in the dictionary, add it with a count of 1
return counts
# Function to calculate all combinations of coins to make a specific amount
def calculate_change_combinations(amount, coins):
# Convert euro amounts to cents for calculations
amount_cents = int(amount * 100)
coin_values_cents = [int(coin * 100) for coin in coins]
# Initialize a list to store combinations and their counts
combinations = []
stack = [(0, [], 0)] # (current amount in cents, current combination, current coin index)
while stack:
current_amount, current_combination, current_coin_index = stack.pop()
# If the current combination sums up to the target amount, add it to the list
if current_amount == amount_cents:
combinations.append(current_combination)
# If the current amount is less than the target amount and there are more coins to consider
elif current_amount < amount_cents and current_coin_index < len(coin_values_cents):
coin = coin_values_cents[current_coin_index]
max_count = (amount_cents - current_amount) // coin # Maximum count of the current coin
# Try adding different counts of the current coin to explore possibilities
for count in range(max_count + 1):
new_amount = current_amount + count * coin
new_combination = current_combination + [coins[current_coin_index]] * count
# Push the new state onto the stack for further exploration
stack.append((new_amount, new_combination, current_coin_index + 1))
# Print the total number of combinations
# print(f"Total number of combinations: {len(combinations)}")
return combinations
```
```python
# Recursive
def make_change_recursive(amount, coins, start, current_change, result):
if amount == 0:
result.append(current_change[:])
return
for i in range(start, len(coins)):
coin_cents = round(coins[i] * 100)
if amount >= coin_cents:
current_change.append(coins[i])
make_change_recursive(amount - coin_cents, coins, i, current_change, result)
current_change.pop()
return result
```
```python
greedy_times_coin_list = []
greedy_labels_coin_list = []
coins_list_copy = coin_list.copy()
for coins in coins_list_copy:
start = time.perf_counter()
greedy_make_change(amounts[0], coins)
end = time.perf_counter()
greedy_times_coin_list.append(end - start)
greedy_labels_coin_list.append(str(len(coins)))
greedy_times_amount_list = []
greedy_labels_amount_list = []
# Plot a graph
plt.figure(figsize=(10, 6))
# NO BAR
plt.plot(greedy_labels_coin_list[1:], greedy_times_coin_list[1:], marker='o', linestyle='solid')
plt.xlabel('Coins')
plt.ylabel('Time (s)')
plt.title('Greedy Algorithm using different coins to make change for 12.35€')
plt.show()
for amount in amounts:
start = time.perf_counter()
greedy_make_change(amount, coin_list[-1])
end = time.perf_counter()
greedy_times_amount_list.append(end - start)
greedy_labels_amount_list.append(str(amount))
# NO BAR
plt.plot(greedy_labels_amount_list[1:], greedy_times_amount_list[1:], marker='o', linestyle='solid')
plt.xlabel('Amount')
plt.ylabel('Time (s)')
plt.title('Greedy Algorithm using 9 coins to make change for different amounts')
plt.show()
```
![png](output_4_0.png)
![png](output_4_1.png)
```python
iterative_times_coin_list = []
iterative_labels_coin_list = []
coins_list_copy = coin_list.copy()
for coins in coins_list_copy[:5]:
start = time.perf_counter()
calculate_change_combinations(amounts[0], coins)
end = time.perf_counter()
iterative_times_coin_list.append(end - start)
iterative_labels_coin_list.append(str(len(coins)))
# Plot a graph
plt.figure(figsize=(10, 6))
# NO BAR
plt.plot(iterative_labels_coin_list[1:], iterative_times_coin_list[1:], marker='o', linestyle='solid')
plt.xlabel('Coins')
plt.ylabel('Time (s)')
plt.title('Iterative Algorithm generating all the possibilities using different coins to make change for 12.35€')
plt.show()
```
![png](output_5_0.png)
The complexity increase more when we add coins that are smaller. We can see that adding 0.02 and 0.01 have more impact than adding 2, and 5.
```python
recursive_times_coin_list = []
recursive_labels_coin_list = []
coins_list_copy = coin_list.copy()
for coins in coins_list_copy[:5]:
# print(coins)
start = time.perf_counter()
make_change_recursive(amounts[0]*100, coins, 0, [], [])
end = time.perf_counter()
recursive_times_coin_list.append(end - start)
recursive_labels_coin_list.append(str(len(coins)))
# Plot a graph
plt.figure(figsize=(10, 6))
# NO BAR
plt.plot(recursive_labels_coin_list[1:], recursive_times_coin_list[1:], marker='o', linestyle='solid')
plt.xlabel('Coins')
plt.ylabel('Time (s)')
plt.title('Recursive Algorithm generating all the possibilities using different coins to make change for 12.35€')
plt.show()
```
[0.2, 0.1, 0.05]
[1, 0.2, 0.1, 0.05]
[2, 1, 0.2, 0.1, 0.05]
[5, 2, 1, 0.2, 0.1, 0.05]
[5, 2, 1, 0.5, 0.2, 0.1, 0.05]
![png](output_7_1.png)
Complexity seems polynomial or exponential, but it is not possible to test using this problem as it takes to much time to run on all the list of coins.
```python
# Export all results to json
import json
# Greedy
greedy_results = {
"greedy_times_coin_list": greedy_times_coin_list,
"greedy_labels_coin_list": greedy_labels_coin_list,
"greedy_times_amount_list": greedy_times_amount_list,
"greedy_labels_amount_list": greedy_labels_amount_list
}
with open('greedy_results.json', 'w') as fp:
json.dump(greedy_results, fp)
# Iterative
iterative_results = {
"iterative_times_coin_list": iterative_times_coin_list,
"iterative_labels_coin_list": iterative_labels_coin_list
}
with open('iterative_results.json', 'w') as fp:
json.dump(iterative_results, fp)
# Recursive
recursive_results = {
"recursive_times_coin_list": recursive_times_coin_list,
"recursive_labels_coin_list": recursive_labels_coin_list
}
with open('recursive_results.json', 'w') as fp:
json.dump(recursive_results, fp)
```

Binary file not shown.

After

Width:  |  Height:  |  Size: 30 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 43 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 29 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 30 KiB

View File

@@ -0,0 +1 @@
{"greedy_times_coin_list": [2.7266999495623168e-05, 4.290000106266234e-06, 4.249999619787559e-06, 4.71700059279101e-06, 5.1530005293898284e-06, 5.198000508244149e-06, 5.539999619941227e-06], "greedy_labels_coin_list": ["3", "4", "5", "6", "7", "8", "9"], "greedy_times_amount_list": [1.591299951542169e-05, 4.618999810190871e-06, 5.142000190971885e-06, 4.219999937049579e-06, 5.545999556488823e-06, 4.925000212097075e-06, 5.834999683429487e-06, 5.122999937157147e-06, 5.883000085304957e-06, 4.184000317764003e-06], "greedy_labels_amount_list": ["12.35", "24.7", "37.05", "49.4", "61.75", "74.1", "86.45", "98.8", "111.14999999999999", "123.5"]}

Binary file not shown.

After

Width:  |  Height:  |  Size: 30 KiB

View File

@@ -0,0 +1 @@
{"iterative_times_coin_list": [0.23977153500072745, 0.7593725659999109, 1.4812359939996895, 1.3827171279999675, 6.808871098000054], "iterative_labels_coin_list": ["3", "4", "5", "6", "7"]}

Binary file not shown.

After

Width:  |  Height:  |  Size: 29 KiB

View File

@@ -0,0 +1 @@
{"recursive_times_coin_list": [0.12517524299983052, 0.44915761500033113, 0.8362728540005264, 0.9114188160001504, 4.504991862000679], "recursive_labels_coin_list": ["3", "4", "5", "6", "7"]}

Binary file not shown.

After

Width:  |  Height:  |  Size: 30 KiB