Greedy-Algorithms: Knapsack small code cleanup

This commit is contained in:
2025-10-05 22:26:44 -04:00
parent aaa1fed779
commit 842ea1d43a

View File

@@ -9,10 +9,10 @@ Honor Code and Acknowledgments:
""" """
from dataclasses import dataclass from dataclasses import dataclass
from typing import override from typing import Self, override
# I don't like tuples # I don't like tuples, dataclasses ftw
@dataclass(frozen=True) @dataclass(frozen=True)
class KnapsackItem: class KnapsackItem:
name: str name: str
@@ -20,42 +20,42 @@ class KnapsackItem:
weight: float weight: float
@property @property
def value_per(self) -> float: def value_ratio(self) -> float:
return self.value / self.weight return self.value / self.weight
@override @override
def __str__(self) -> str: def __str__(self) -> str:
return f"{self.name}({self.value:.2f}, {self.weight:.2f})" return f"{self.name}({self.value:.2f}, {self.weight:.2f})"
@staticmethod @classmethod
def from_str(string: str) -> "KnapsackItem": def parse(cls, string: str) -> Self:
values: list[str] = string.split() values: list[str] = string.strip().split()
name, value, weight = values[0], float(values[1]), float(values[2]) name, value, weight = values[0], float(values[1]), float(values[2])
return KnapsackItem(name, value, weight) return cls(name, value, weight)
def knapsack( def knapsack(
capacity: int, items: list[KnapsackItem] capacity: int, items: list[KnapsackItem]
) -> tuple[list[KnapsackItem], float]: ) -> tuple[list[KnapsackItem], float]:
cur_capacity: float = capacity
sorted_items: list[KnapsackItem] = sorted(items, key=lambda i: -i.value_per) current_capacity: float = float(capacity)
sorted_items: list[KnapsackItem] = sorted(items, key=lambda i: -i.value_ratio)
total_value: float = 0.0 total_value: float = 0.0
fractional_items: list[KnapsackItem] = [] fractional_items: list[KnapsackItem] = []
for item in sorted_items: for item in sorted_items:
if abs(cur_capacity) < 1e-8: if abs(current_capacity) < 1e-8:
break break
if cur_capacity < item.weight: name, value, weight = item.name, item.value, item.weight
value: float = item.value_per * cur_capacity if current_capacity < weight:
total_value += value value = item.value_ratio * current_capacity
fractional_items.append(KnapsackItem(item.name, value, cur_capacity)) weight = current_capacity
cur_capacity = 0
else: fractional_items.append(KnapsackItem(name, value, weight))
total_value += item.value total_value += value
fractional_items.append(KnapsackItem(item.name, item.value, item.weight)) current_capacity -= weight
cur_capacity -= item.weight
return fractional_items, total_value return fractional_items, total_value
@@ -66,7 +66,7 @@ def main():
capacity: int = int(input()) capacity: int = int(input())
n: int = int(input()) n: int = int(input())
items: list[KnapsackItem] = [KnapsackItem.from_str(input()) for _ in range(0, n)] items: list[KnapsackItem] = [KnapsackItem.parse(input()) for _ in range(0, n)]
fractional_items, total_value = knapsack(capacity, items) fractional_items, total_value = knapsack(capacity, items)