Skip to content

Commit 68fa7d5

Browse files
authored
book-store: refactor for speed (exercism#1602)
Faster solution to reduce Travis build times
1 parent 8170ca7 commit 68fa7d5

1 file changed

Lines changed: 49 additions & 34 deletions

File tree

exercises/book-store/example.py

Lines changed: 49 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -1,34 +1,49 @@
1-
from collections import Counter
2-
BOOK_PRICE = 800
3-
4-
5-
def _group_price(size):
6-
discounts = [0, .05, .1, .2, .25]
7-
if not (0 < size <= 5):
8-
raise ValueError('size must be in 1..' + len(discounts))
9-
return BOOK_PRICE * size * (1 - discounts[size - 1])
10-
11-
12-
def calculate_total(books, price_so_far=0.):
13-
if not books:
14-
return price_so_far
15-
16-
reordered_books = []
17-
groups = []
18-
for value, count in Counter(books).most_common():
19-
reordered_books = reordered_books + [value] * count
20-
groups.append(value)
21-
min_price = float('inf')
22-
23-
for i in range(len(groups)):
24-
25-
remaining_books = reordered_books[:]
26-
27-
for v in groups[:i + 1]:
28-
remaining_books.remove(v)
29-
30-
price = calculate_total(remaining_books,
31-
price_so_far + _group_price(i + 1))
32-
min_price = min(min_price, price)
33-
34-
return min_price
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 groupCost(g):
8+
return len(g) * discount[len(g)]
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(groupCost, self.groups)) * BASE_COST
17+
18+
def dup(self):
19+
return Grouping(list(map(set, self.groups)))
20+
21+
def add_to_valid(self, b):
22+
"""Returns all possible groupings from current grouping adding book b
23+
"""
24+
other = self.dup()
25+
other.groups.sort(key=lambda g: len(g))
26+
results = []
27+
for i, g in enumerate(other.groups):
28+
if b not in g:
29+
o2 = other.dup()
30+
o2.groups[i].add(b)
31+
results.append(o2)
32+
if not results:
33+
other.groups.append(set([b]))
34+
return [other]
35+
return results
36+
37+
def __lt__(self, other):
38+
return self.total() < other.total()
39+
40+
41+
def step(rs, b):
42+
return [g for r in rs for g in r.add_to_valid(b)]
43+
44+
45+
def calculate_total(books):
46+
if len(books) == 0:
47+
return 0
48+
start = Grouping([{books[0]}])
49+
return round(min(reduce(step, books[1:], [start])).total())

0 commit comments

Comments
 (0)