diff --git a/Greedy-Algorithms/cs412_knapsack_fractional.py b/Greedy-Algorithms/cs412_knapsack_fractional.py index 33907d6..5983460 100644 --- a/Greedy-Algorithms/cs412_knapsack_fractional.py +++ b/Greedy-Algorithms/cs412_knapsack_fractional.py @@ -8,12 +8,70 @@ Honor Code and Acknowledgments: Comments here on your code and submission. """ +from dataclasses import dataclass +from typing import override + + +# I don't like tuples +@dataclass(frozen=True) +class KnapsackItem: + name: str + value: float + weight: float + + @property + def value_per(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() + name, value, weight = values[0], float(values[1]), float(values[2]) + return KnapsackItem(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) + + total_value: float = 0.0 + fractional_items: list[KnapsackItem] = [] + + for item in sorted_items: + if abs(cur_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 + + return fractional_items, total_value + # All modules for CS 412 must include a main method that allows it # to imported and invoked from other python scripts def main(): - # your code here - pass + capacity: int = int(input()) + n: int = int(input()) + + items: list[KnapsackItem] = [KnapsackItem.from_str(input()) for _ in range(0, n)] + + fractional_items, total_value = knapsack(capacity, items) + + print(" ".join(map(str, fractional_items))) + print(total_value) if __name__ == "__main__":