diff --git a/Greedy-Algorithms/cs412_knapsack_fractional.py b/Greedy-Algorithms/cs412_knapsack_fractional.py index 5983460..90a66eb 100644 --- a/Greedy-Algorithms/cs412_knapsack_fractional.py +++ b/Greedy-Algorithms/cs412_knapsack_fractional.py @@ -9,10 +9,10 @@ Honor Code and Acknowledgments: """ 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) class KnapsackItem: name: str @@ -20,42 +20,42 @@ class KnapsackItem: weight: float @property - def value_per(self) -> float: + def value_ratio(self) -> float: return self.value / self.weight @override def __str__(self) -> str: return f"{self.name}({self.value:.2f}, {self.weight:.2f})" - @staticmethod - def from_str(string: str) -> "KnapsackItem": - values: list[str] = string.split() + @classmethod + def parse(cls, string: str) -> Self: + values: list[str] = string.strip().split() name, value, weight = values[0], float(values[1]), float(values[2]) - return KnapsackItem(name, value, weight) + return cls(name, value, weight) def knapsack( capacity: int, items: list[KnapsackItem] ) -> 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 fractional_items: list[KnapsackItem] = [] for item in sorted_items: - if abs(cur_capacity) < 1e-8: + if abs(current_capacity) < 1e-8: break - if cur_capacity < item.weight: - value: float = item.value_per * cur_capacity - total_value += value - fractional_items.append(KnapsackItem(item.name, value, cur_capacity)) - cur_capacity = 0 - else: - total_value += item.value - fractional_items.append(KnapsackItem(item.name, item.value, item.weight)) - cur_capacity -= item.weight + name, value, weight = item.name, item.value, item.weight + if current_capacity < weight: + value = item.value_ratio * current_capacity + weight = current_capacity + + fractional_items.append(KnapsackItem(name, value, weight)) + total_value += value + current_capacity -= weight return fractional_items, total_value @@ -66,7 +66,7 @@ def main(): capacity: 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)