Skip to content

Commit 14e4aed

Browse files
authored
[book-store] Simplify example.py (#2175)
The existing example.py is quite complex and not particulary efficient, even for quite small lists of books. This example.py is much simpler, but could be made considerably more efficient through a bit of a caching and some sensible short-circuit returns. These are left to the student to figure out, however.
1 parent e5dbf17 commit 14e4aed

File tree

1 file changed

+25
-50
lines changed

1 file changed

+25
-50
lines changed

exercises/book-store/example.py

Lines changed: 25 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -1,51 +1,26 @@
1-
from functools import reduce
2-
3-
BASE_COST = 800
4-
discount = [1.0, 1.0, 0.95, 0.9, 0.8, 0.75]
5-
6-
7-
def group_cost(group):
8-
return len(group) * discount[len(group)]
9-
10-
11-
class Grouping:
12-
def __init__(self, groups=None):
13-
self.groups = [set()] if groups is None else groups
14-
15-
def total(self):
16-
return sum(map(group_cost, self.groups)) * BASE_COST
17-
18-
def dup(self):
19-
return Grouping(list(map(set, self.groups)))
20-
21-
def add_to_valid(self, book):
22-
"""Returns all possible groupings from the
23-
current grouping adding book
24-
"""
25-
other = self.dup()
26-
other.groups.sort(key=lambda g: len(g))
27-
results = []
28-
for index, group in enumerate(other.groups):
29-
if book not in group:
30-
other2 = other.dup()
31-
other2.groups[index].add(book)
32-
results.append(other2)
33-
if not results:
34-
other.groups.append(set([book]))
35-
return [other]
36-
return results
37-
38-
def __lt__(self, other):
39-
return self.total() < other.total()
40-
41-
42-
def step(basket, book):
43-
return [group for groupings in basket
44-
for group in groupings.add_to_valid(book)]
45-
46-
47-
def total(basket):
48-
if len(basket) == 0:
1+
from collections import Counter
2+
3+
PER_BOOK = 800.00
4+
PER_GROUP = {
5+
1: 1 * PER_BOOK * 1.00,
6+
2: 2 * PER_BOOK * 0.95,
7+
3: 3 * PER_BOOK * 0.90,
8+
4: 4 * PER_BOOK * 0.80,
9+
5: 5 * PER_BOOK * 0.75,
10+
}
11+
12+
13+
def _total(books):
14+
volumes = Counter(books)
15+
price = len(books) * PER_BOOK
16+
for size in range(len(volumes), 1, -1):
17+
group = volumes - Counter(k for k, _ in volumes.most_common(size))
18+
group_books = sorted(group.elements())
19+
price = min(price, PER_GROUP[size] + _total(group_books))
20+
return price
21+
22+
23+
def total(books):
24+
if not books:
4925
return 0
50-
start = Grouping([{basket[0]}])
51-
return round(min(reduce(step, basket[1:], [start])).total())
26+
return _total(sorted(books))

0 commit comments

Comments
 (0)