|
|
@@ -4,47 +4,47 @@ import java.util.stream.Collectors;
|
|
4
|
4
|
|
|
5
|
5
|
class BookStore {
|
|
6
|
6
|
|
|
7
|
|
- private static final int BOOK_PRICE = 8, MAX_GROUP_SIZE = 5;
|
|
|
7
|
+ private static final int BOOK_PRICE = 8, MAX_GROUP_SIZE = 5;
|
|
8
|
8
|
|
|
9
|
|
- private static double[] DISCOUNT_TIERS = {0, 5, 10, 20, 25};
|
|
|
9
|
+ private static double[] DISCOUNT_TIERS = {0, 5, 10, 20, 25};
|
|
10
|
10
|
|
|
11
|
|
- double calculateBasketCost(final List<Integer> books) {
|
|
12
|
|
- return calculateBasketCost(books, 0);
|
|
13
|
|
- }
|
|
14
|
|
-
|
|
15
|
|
- private double calculateBasketCost(final List<Integer> books, final double priceSoFar) {
|
|
16
|
|
- if (books.size() == 0) {
|
|
17
|
|
- return priceSoFar;
|
|
|
11
|
+ double calculateBasketCost(final List<Integer> books) {
|
|
|
12
|
+ return calculateBasketCost(books, 0);
|
|
18
|
13
|
}
|
|
19
|
14
|
|
|
20
|
|
- List<Integer> availableBookNumbers = books.stream()
|
|
21
|
|
- .distinct()
|
|
22
|
|
- .collect(Collectors.toList());
|
|
|
15
|
+ private double calculateBasketCost(final List<Integer> books, final double priceSoFar) {
|
|
|
16
|
+ if (books.size() == 0) {
|
|
|
17
|
+ return priceSoFar;
|
|
|
18
|
+ }
|
|
23
|
19
|
|
|
24
|
|
- double minPrice = Double.MAX_VALUE;
|
|
|
20
|
+ List<Integer> availableBookNumbers = books.stream()
|
|
|
21
|
+ .distinct()
|
|
|
22
|
+ .collect(Collectors.toList());
|
|
25
|
23
|
|
|
26
|
|
- for (int i = 0; i < availableBookNumbers.size(); i++) {
|
|
27
|
|
- List<Integer> newGroupBooks = new ArrayList<>(availableBookNumbers.subList(0, i + 1));
|
|
28
|
|
- List<Integer> remainingBooks = new ArrayList<>(books);
|
|
|
24
|
+ double minPrice = Double.MAX_VALUE;
|
|
29
|
25
|
|
|
30
|
|
- for (final Integer newGroupBook : newGroupBooks) {
|
|
31
|
|
- //noinspection UseBulkOperation - we want to remove _one_ of each book number, not _all_ of each book number.
|
|
32
|
|
- remainingBooks.remove(newGroupBook);
|
|
33
|
|
- }
|
|
|
26
|
+ for (int i = 0; i < availableBookNumbers.size(); i++) {
|
|
|
27
|
+ List<Integer> newGroupBooks = new ArrayList<>(availableBookNumbers.subList(0, i + 1));
|
|
|
28
|
+ List<Integer> remainingBooks = new ArrayList<>(books);
|
|
34
|
29
|
|
|
35
|
|
- double price = calculateBasketCost(remainingBooks, priceSoFar + costOfGroupSize(newGroupBooks.size()));
|
|
36
|
|
- minPrice = Math.min(minPrice, price);
|
|
37
|
|
- }
|
|
|
30
|
+ for (final Integer newGroupBook : newGroupBooks) {
|
|
|
31
|
+ //noinspection UseBulkOperation - we want to remove _one_ of each book number, not _all_ of each book number.
|
|
|
32
|
+ remainingBooks.remove(newGroupBook);
|
|
|
33
|
+ }
|
|
38
|
34
|
|
|
39
|
|
- return minPrice;
|
|
40
|
|
- }
|
|
|
35
|
+ double price = calculateBasketCost(remainingBooks, priceSoFar + costOfGroupSize(newGroupBooks.size()));
|
|
|
36
|
+ minPrice = Math.min(minPrice, price);
|
|
|
37
|
+ }
|
|
41
|
38
|
|
|
42
|
|
- private double costOfGroupSize(int groupSize) {
|
|
43
|
|
- if (groupSize < 1 || groupSize > MAX_GROUP_SIZE) {
|
|
44
|
|
- throw new IllegalStateException("Invalid group size : " + groupSize);
|
|
|
39
|
+ return minPrice;
|
|
45
|
40
|
}
|
|
46
|
41
|
|
|
47
|
|
- return BOOK_PRICE * groupSize * (100 - DISCOUNT_TIERS[groupSize - 1]) / 100;
|
|
48
|
|
- }
|
|
|
42
|
+ private double costOfGroupSize(int groupSize) {
|
|
|
43
|
+ if (groupSize < 1 || groupSize > MAX_GROUP_SIZE) {
|
|
|
44
|
+ throw new IllegalStateException("Invalid group size : " + groupSize);
|
|
|
45
|
+ }
|
|
|
46
|
+
|
|
|
47
|
+ return BOOK_PRICE * groupSize * (100 - DISCOUNT_TIERS[groupSize - 1]) / 100;
|
|
|
48
|
+ }
|
|
49
|
49
|
|
|
50
|
50
|
}
|