Skip to content

Commit

Permalink
Sync book-store (#850)
Browse files Browse the repository at this point in the history
  • Loading branch information
tomasnorre authored Dec 8, 2024
1 parent cb9d5b1 commit 0af034f
Show file tree
Hide file tree
Showing 5 changed files with 193 additions and 115 deletions.
39 changes: 16 additions & 23 deletions exercises/practice/book-store/.docs/instructions.md
Original file line number Diff line number Diff line change
@@ -1,27 +1,20 @@
# Instructions

To try and encourage more sales of different books from a popular 5 book
series, a bookshop has decided to offer discounts on multiple book purchases.
To try and encourage more sales of different books from a popular 5 book series, a bookshop has decided to offer discounts on multiple book purchases.

One copy of any of the five books costs $8.

If, however, you buy two different books, you get a 5%
discount on those two books.
If, however, you buy two different books, you get a 5% discount on those two books.

If you buy 3 different books, you get a 10% discount.

If you buy 4 different books, you get a 20% discount.

If you buy all 5, you get a 25% discount.

Note: that if you buy four books, of which 3 are
different titles, you get a 10% discount on the 3 that
form part of a set, but the fourth book still costs $8.
Note that if you buy four books, of which 3 are different titles, you get a 10% discount on the 3 that form part of a set, but the fourth book still costs $8.

Your mission is to write a piece of code to calculate the
price of any conceivable shopping basket (containing only
books of the same series), giving as big a discount as
possible.
Your mission is to write code to calculate the price of any conceivable shopping basket (containing only books of the same series), giving as big a discount as possible.

For example, how much does this basket of books cost?

Expand All @@ -33,36 +26,36 @@ For example, how much does this basket of books cost?

One way of grouping these 8 books is:

- 1 group of 5 --> 25% discount (1st,2nd,3rd,4th,5th)
- +1 group of 3 --> 10% discount (1st,2nd,3rd)
- 1 group of 5 (1st, 2nd,3rd, 4th, 5th)
- 1 group of 3 (1st, 2nd, 3rd)

This would give a total of:

- 5 books at a 25% discount
- +3 books at a 10% discount
- 3 books at a 10% discount

Resulting in:

- 5 x (8 - 2.00) == 5 x 6.00 == $30.00
- +3 x (8 - 0.80) == 3 x 7.20 == $21.60
- 5 × (100% - 25%) × $8 = 5 × $6.00 = $30.00, plus
- 3 × (100% - 10%) × $8 = 3 × $7.20 = $21.60

For a total of $51.60
Which equals $51.60.

However, a different way to group these 8 books is:

- 1 group of 4 books --> 20% discount (1st,2nd,3rd,4th)
- +1 group of 4 books --> 20% discount (1st,2nd,3rd,5th)
- 1 group of 4 books (1st, 2nd, 3rd, 4th)
- 1 group of 4 books (1st, 2nd, 3rd, 5th)

This would give a total of:

- 4 books at a 20% discount
- +4 books at a 20% discount
- 4 books at a 20% discount

Resulting in:

- 4 x (8 - 1.60) == 4 x 6.40 == $25.60
- +4 x (8 - 1.60) == 4 x 6.40 == $25.60
- 4 × (100% - 20%) × $8 = 4 × $6.40 = $25.60, plus
- 4 × (100% - 20%) × $8 = 4 × $6.40 = $25.60

For a total of $51.20
Which equals $51.20.

And $51.20 is the price with the biggest discount.
82 changes: 31 additions & 51 deletions exercises/practice/book-store/.meta/example.php
Original file line number Diff line number Diff line change
@@ -1,62 +1,42 @@
<?php

/*
* By adding type hints and enabling strict type checking, code can become
* easier to read, self-documenting and reduce the number of potential bugs.
* By default, type declarations are non-strict, which means they will attempt
* to change the original type to match the type specified by the
* type-declaration.
*
* In other words, if you pass a string to a function requiring a float,
* it will attempt to convert the string value to a float.
*
* To enable strict mode, a single declare directive must be placed at the top
* of the file.
* This means that the strictness of typing is configured on a per-file basis.
* This directive not only affects the type declarations of parameters, but also
* a function's return type.
*
* For more info review the Concept on strict type checking in the PHP track
* <link>.
*
* To disable strict typing, comment out the directive below.
*/

declare(strict_types=1);

function total($items)
function total(array $items): int
{
return calculate($items, 0);
}
$groups = array_fill(1, 5, 0); // Groups of books
$sets = array_fill(1, 5, 0); // Sets by size

function calculate($items, $total)
{
if (empty($items)) {
return $total;
// Group the basket
foreach ($items as $bookId) {
$groups[$bookId]++;
}

$group = array_unique($items);
$totalMin = INF;

for ($i = count($group); $i > 0; $i--) {
$itemsToRemove = array_flip(array_slice($group, 0, $i));
$itemsRemaining = array_filter($items, function ($x) use (&$itemsToRemove) {
if (array_key_exists($x, $itemsToRemove)) {
unset($itemsToRemove[$x]);
return false;
// Arrange groups into counts by set size
while (array_sum($groups) > 0) {
$setSize = 0;
foreach ($groups as $key => $count) {
if ($count > 0) {
$setSize++;
$groups[$key]--;
}
return true;
});
$totalCurrent = calculate($itemsRemaining, $total + totalForGroup($i));
$totalMin = min([$totalMin, $totalCurrent]);
}
if ($setSize > 0) {
$sets[$setSize]++;
}
}

return $totalMin;
}
// Replace each 3set+5set with two 4sets
while ($sets[3] > 0 && $sets[5] > 0) {
$sets[3]--;
$sets[5]--;
$sets[4] += 2;
}

function totalForGroup($count)
{
$discount = [0, 0, 0.05, 0.1, 0.2, 0.25];
$price = 8;
return $price * $count * (1 - $discount[$count]);
// Calculate the total cost
$cost = 800 * $sets[1] +
(800 * 2 * 0.95) * $sets[2] +
(800 * 3 * 0.9) * $sets[3] +
(800 * 4 * 0.8) * $sets[4] +
(800 * 5 * 0.75) * $sets[5];

return (int)$cost;
}
28 changes: 22 additions & 6 deletions exercises/practice/book-store/.meta/tests.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,13 @@
# This is an auto-generated file. Regular comments will be removed when this
# file is regenerated. Regenerating will not touch any manually added keys,
# so comments can be added in a "comment" key.
# This is an auto-generated file.
#
# Regenerating this file via `configlet sync` will:
# - Recreate every `description` key/value pair
# - Recreate every `reimplements` key/value pair, where they exist in problem-specifications
# - Remove any `include = true` key/value pair (an omitted `include` key implies inclusion)
# - Preserve any other key/value pair
#
# As user-added comments (using the # character) will be removed when this file
# is regenerated, comments can be added via a `comment` key.

[17146bd5-2e80-4557-ab4c-05632b6b0d01]
description = "Only a single book"
Expand Down Expand Up @@ -33,16 +40,25 @@ description = "Two groups of four is cheaper than groups of five and three"
description = "Group of four plus group of two is cheaper than two groups of three"

[68ea9b78-10ad-420e-a766-836a501d3633]
description = "Two each of first 4 books and 1 copy each of rest"
description = "Two each of first four books and one copy each of rest"

[c0a779d5-a40c-47ae-9828-a340e936b866]
description = "Two copies of each book"

[18fd86fe-08f1-4b68-969b-392b8af20513]
description = "Three copies of first book and 2 each of remaining"
description = "Three copies of first book and two each of remaining"

[0b19a24d-e4cf-4ec8-9db2-8899a41af0da]
description = "Three each of first 2 books and 2 each of remaining books"
description = "Three each of first two books and two each of remaining books"

[bb376344-4fb2-49ab-ab85-e38d8354a58d]
description = "Four groups of four are cheaper than two groups each of five and three"

[5260ddde-2703-4915-b45a-e54dbbac4303]
description = "Check that groups of four are created properly even when there are more groups of three than groups of five"

[b0478278-c551-4747-b0fc-7e0be3158b1f]
description = "One group of one and four is cheaper than one group of two and three"

[cf868453-6484-4ae1-9dfc-f8ee85bbde01]
description = "One group of one and two plus three groups of four is cheaper than one group of each size"
5 changes: 4 additions & 1 deletion exercises/practice/book-store/BookStore.php
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,10 @@

declare(strict_types=1);

function total(array $items): float
/**
* Note: we expect the total in cents (1$ = 100 cents).
*/
function total(array $items): int
{
throw new \BadFunctionCallException("Implement the total function");
}
Loading

0 comments on commit 0af034f

Please sign in to comment.