Skip to content

Commit c6245b3

Browse files
authored
book-store: Add new exercise (exercism#465)
1 parent d5b1a3a commit c6245b3

4 files changed

Lines changed: 109 additions & 0 deletions

File tree

config.json

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -416,6 +416,12 @@
416416
"topics": [
417417
]
418418
},
419+
{
420+
"slug": "book-store",
421+
"difficulty": 1,
422+
"topics": [
423+
]
424+
},
419425
{
420426
"slug": "linked-list",
421427
"difficulty": 1,

exercises/book-store/book_store.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
def calculate_total():
2+
pass
Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
import unittest
2+
3+
from book_store import calculate_total
4+
5+
6+
# test cases adapted from `x-common//canonical-data.json` @ version: 1.0.0
7+
8+
class BookStoreTests(unittest.TestCase):
9+
def test_only_a_single_book(self):
10+
self.assertAlmostEqual(calculate_total([1]), 8.00,
11+
places=2)
12+
13+
def test_two_of_the_same_book(self):
14+
self.assertAlmostEqual(calculate_total([2, 2]), 16.00,
15+
places=2)
16+
17+
def test_empty_basket(self):
18+
self.assertAlmostEqual(calculate_total([]), 0.00,
19+
places=2)
20+
21+
def test_two_different_books(self):
22+
self.assertAlmostEqual(calculate_total([1, 2]), 15.20,
23+
places=2)
24+
25+
def test_three_different_books(self):
26+
self.assertAlmostEqual(calculate_total([1, 2, 3]), 21.60,
27+
places=2)
28+
29+
def test_four_different_books(self):
30+
self.assertAlmostEqual(calculate_total([1, 2, 3, 4]), 25.60,
31+
places=2)
32+
33+
def test_five_different_books(self):
34+
self.assertAlmostEqual(
35+
calculate_total([1, 2, 3, 4, 5]), 30.00,
36+
places=2)
37+
38+
def test_two_groups_of_4_is_cheaper_than_group_of_5_plus_group_of_3(self):
39+
self.assertAlmostEqual(
40+
calculate_total([1, 1, 2, 2, 3, 3, 4, 5]), 51.20,
41+
places=2)
42+
43+
def test_group_of_4_plus_group_of_2_is_cheaper_than_2_groups_of_3(self):
44+
self.assertAlmostEqual(
45+
calculate_total([1, 1, 2, 2, 3, 4]), 40.80,
46+
places=2)
47+
48+
def test_two_each_of_first_4_books_and_1_copy_each_of_rest(self):
49+
self.assertAlmostEqual(
50+
calculate_total([1, 1, 2, 2, 3, 3, 4, 4, 5]), 55.60,
51+
places=2)
52+
53+
def test_two_copies_of_each_book(self):
54+
self.assertAlmostEqual(
55+
calculate_total([1, 1, 2, 2, 3, 3, 4, 4, 5, 5]), 60.00,
56+
places=2)
57+
58+
def test_three_copies_of_first_book_and_2_each_of_remaining(self):
59+
self.assertAlmostEqual(
60+
calculate_total([1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 1]),
61+
68.00,
62+
places=2)
63+
64+
def test_three_each_of_first_2_books_and_2_each_of_remaining_books(self):
65+
self.assertAlmostEqual(
66+
calculate_total([1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 1, 2]),
67+
75.20,
68+
places=2)
69+
70+
71+
if __name__ == '__main__':
72+
unittest.main()

exercises/book-store/example.py

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
BOOK_PRICE = 8
2+
3+
4+
def _group_price(size):
5+
discounts = [0, .05, .1, .2, .25]
6+
if not (0 < size <= 5):
7+
raise ValueError('size must be in 1..' + len(discounts))
8+
return 8 * size * (1 - discounts[size - 1])
9+
10+
11+
def calculate_total(books, price_so_far=0.):
12+
if not books:
13+
return price_so_far
14+
15+
groups = list(set(books))
16+
min_price = float('inf')
17+
18+
for i in range(len(groups)):
19+
20+
remaining_books = books[:]
21+
22+
for v in groups[:i + 1]:
23+
remaining_books.remove(v)
24+
25+
price = calculate_total(remaining_books,
26+
price_so_far + _group_price(i + 1))
27+
min_price = min(min_price, price)
28+
29+
return min_price

0 commit comments

Comments
 (0)