Skip to content

Commit 78af0c4

Browse files
debnath003pre-commit-ci[bot]cclauss
authored
Create fractional_cover_problem.py (TheAlgorithms#9973)
* Create fractional_cover_problem.py * Update fractional_cover_problem.py * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * Update fractional_cover_problem.py * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * Update fractional_cover_problem.py * Update fractional_cover_problem.py * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * Update fractional_cover_problem.py * Update fractional_cover_problem.py * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * Update fractional_cover_problem.py * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * Lose __eq__() * Update fractional_cover_problem.py * Define Item property ratio --------- Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> Co-authored-by: Christian Clauss <[email protected]>
1 parent 678e0aa commit 78af0c4

File tree

1 file changed

+102
-0
lines changed

1 file changed

+102
-0
lines changed
+102
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,102 @@
1+
# https://en.wikipedia.org/wiki/Set_cover_problem
2+
3+
from dataclasses import dataclass
4+
from operator import attrgetter
5+
6+
7+
@dataclass
8+
class Item:
9+
weight: int
10+
value: int
11+
12+
@property
13+
def ratio(self) -> float:
14+
"""
15+
Return the value-to-weight ratio for the item.
16+
17+
Returns:
18+
float: The value-to-weight ratio for the item.
19+
20+
Examples:
21+
>>> Item(10, 65).ratio
22+
6.5
23+
24+
>>> Item(20, 100).ratio
25+
5.0
26+
27+
>>> Item(30, 120).ratio
28+
4.0
29+
"""
30+
return self.value / self.weight
31+
32+
33+
def fractional_cover(items: list[Item], capacity: int) -> float:
34+
"""
35+
Solve the Fractional Cover Problem.
36+
37+
Args:
38+
items: A list of items, where each item has weight and value attributes.
39+
capacity: The maximum weight capacity of the knapsack.
40+
41+
Returns:
42+
The maximum value that can be obtained by selecting fractions of items to cover
43+
the knapsack's capacity.
44+
45+
Raises:
46+
ValueError: If capacity is negative.
47+
48+
Examples:
49+
>>> fractional_cover((Item(10, 60), Item(20, 100), Item(30, 120)), capacity=50)
50+
240.0
51+
52+
>>> fractional_cover([Item(20, 100), Item(30, 120), Item(10, 60)], capacity=25)
53+
135.0
54+
55+
>>> fractional_cover([Item(10, 60), Item(20, 100), Item(30, 120)], capacity=60)
56+
280.0
57+
58+
>>> fractional_cover(items=[Item(5, 30), Item(10, 60), Item(15, 90)], capacity=30)
59+
180.0
60+
61+
>>> fractional_cover(items=[], capacity=50)
62+
0.0
63+
64+
>>> fractional_cover(items=[Item(10, 60)], capacity=5)
65+
30.0
66+
67+
>>> fractional_cover(items=[Item(10, 60)], capacity=1)
68+
6.0
69+
70+
>>> fractional_cover(items=[Item(10, 60)], capacity=0)
71+
0.0
72+
73+
>>> fractional_cover(items=[Item(10, 60)], capacity=-1)
74+
Traceback (most recent call last):
75+
...
76+
ValueError: Capacity cannot be negative
77+
"""
78+
if capacity < 0:
79+
raise ValueError("Capacity cannot be negative")
80+
81+
total_value = 0.0
82+
remaining_capacity = capacity
83+
84+
# Sort the items by their value-to-weight ratio in descending order
85+
for item in sorted(items, key=attrgetter("ratio"), reverse=True):
86+
if remaining_capacity == 0:
87+
break
88+
89+
weight_taken = min(item.weight, remaining_capacity)
90+
total_value += weight_taken * item.ratio
91+
remaining_capacity -= weight_taken
92+
93+
return total_value
94+
95+
96+
if __name__ == "__main__":
97+
import doctest
98+
99+
if result := doctest.testmod().failed:
100+
print(f"{result} test(s) failed")
101+
else:
102+
print("All tests passed")

0 commit comments

Comments
 (0)