|
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: |
49 | 25 | 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