grokking-algorithms/chapter11/knapsack.py

73 lines
1.8 KiB
Python
Raw Normal View History

2024-01-15 18:24:04 +00:00
import logging
from dataclasses import dataclass
from tabulate import tabulate
logging.basicConfig(
level=logging.DEBUG,
format="%(asctime)s %(levelname)s\n\r%(message)s",
datefmt="%H:%M:%S",
)
logger = logging.getLogger(__name__)
@dataclass
class Item:
name: str
value: int
weight: int
2024-01-15 18:28:16 +00:00
def dynamic(items, n):
2024-01-15 18:24:04 +00:00
# create table and zero fill it (required for calculations)
table = [[0 for _ in range(W + 1)] for _ in range(n + 1)]
2024-01-15 20:15:59 +00:00
# calculate all possible max values for items in knapsack
2024-01-15 18:24:04 +00:00
for i in range(1, n + 1):
for w in range(1, W + 1):
if items[i - 1].weight <= w:
table[i][w] = max(
items[i - 1].value + table[i - 1][w - items[i - 1].weight],
table[i - 1][w],
)
else:
table[i][w] = table[i - 1][w]
format_and_print(table)
return table[-1][-1]
def format_and_print(table):
# enumerate first row (headings) + label each row in column0
for i, row in enumerate(table):
if i == 0:
continue
row[0] = items[i - 1].name
2024-01-16 17:19:45 +00:00
table[0] = [None, *[i for i in range(1, W + 1)]]
2024-01-15 18:24:04 +00:00
# print tabularised 2D array
2024-01-15 20:25:37 +00:00
logger.info([item.name for item in items])
2024-01-15 18:24:04 +00:00
logger.info(tabulate(table, tablefmt="pretty"))
2024-01-15 20:25:37 +00:00
# Where items = Guitar + Stereo + Laptop
2024-01-15 18:24:04 +00:00
items = [Item("Guitar", 1500, 1), Item("Stereo", 3000, 4), Item("Laptop", 2000, 3)]
W = 4
2024-01-15 18:28:16 +00:00
greatest_value = dynamic(items, len(items))
2024-01-15 18:24:04 +00:00
2024-01-15 20:25:37 +00:00
print(f"Greatest value: {greatest_value}")
# Where items = Guitar + Stereo + Laptop + Iphone
items = [
Item("Guitar", 1500, 1),
Item("Stereo", 3000, 4),
Item("Laptop", 2000, 3),
Item("Iphone", 2000, 1),
]
W = 4
greatest_value_with_iphone = dynamic(items, len(items))
print(f"Greatest value: {greatest_value_with_iphone}")