Brain-Teaser 460: [Crates of Boppo]
From The Sunday Times, 22nd March 1970 [link]
Boppo is made up in 1 lb cans at 8s, 2 lb cans at 15s and 4 lb cans at 27s. The contents of crates vary, but every crate contains 60 cans of mixed three sizes with a total value of £45.
The foreman himself had packed two such crates. He told new worker Rob, “Just go along and nail down those two open crates in the shed, Rob. The lorry’s waiting.”
Rob found the two crates standing beside the weighing platform, and for no particular reason he weighed them. One was heavier than the other. “Huh! Calls ‘isself a foreman” he said, as he removed some cans from the heavier crate. “That’s it. Both the same now. Lucky I weighed ’em”. So he nailed them down and the lorry went off with them.
He met the foreman. “You made a mistake with those crates, chum”, he said, “but it’s OK now. Here’s three spare cans.”
“!!” said the foreman.
What were the weights of the two crates the foreman had packed?
This puzzle was originally published with no title.
[teaser460]
Jim Randell 11:19 am on 5 March 2019 Permalink |
Before decimalisation £1 was the same as 20 shillings, so each crate has a monetary value of 900 shillings.
I solved this using a similar approach to Enigma 486 (and borrowed some of the code too).
This Python 3 program runs in 108ms.
from enigma import (defaultdict, irange, subsets, printf) # express total <t> using denominations <ds>, min quantity 1 def express(t, ds, s=[]): if not ds: if t == 0: yield s else: (d, *ds) = ds for i in irange(1, t // d): yield from express(t - d * i, ds, s + [i]) # the weights and costs of the cans weights = (1, 2, 4) costs = (8, 15, 27) # find ways to split the cost of a crate into cans crates = defaultdict(list) for ns in express(900, costs): # but each crate has 60 cans if not (sum(ns) == 60): continue # calculate the total weight of the crate t = sum(n * w for (n, w) in zip(ns, weights)) printf("[{ns} -> weight = {t}]") crates[t].append(ns) # possible weights of 3 cans to be removed w3s = defaultdict(list) for rs in subsets(weights, size=3, select='R'): w3s[sum(rs)].append(rs) # find two crates with weights that differ by 3 cans for (w1, w2) in subsets(sorted(crates.keys()), size=2): for rs in w3s[w2 - w1]: # check there are enough cans in the w2 crate if not any(all(not (r > n) for (r, n) in zip(rs, ns)) for ns in crates[w2]): continue # output solution printf("{w2} lb -> {w1} lb by removing {rs} x {weights} lb cans")Solution: The crates the foreman had packed weighed 122 lb and 126 lb.
Rob reduced the weight of the 126 lb crate to 122 lb by removing 2× 1 lb cans and 1× 2 lb can.
There are only 3 ways to pack the crates so they have 60 cans and are worth 900 shillings (900s) (where the is at least 1 of each type of can included):
If we don’t require that all three weights of can are represented in the crate then we can make a crate with 60× 2 lb cans, which weighs 120 lb, and gives rise to multiple solutions.
LikeLike
GeoffR 7:42 am on 6 March 2019 Permalink |
The only 3 ways to pack a crate are found in my MiniZinc programme as 122 lb, 124 lb and 126 lb
The only way of removing 3 cans to make the crates equal is to remove 3 cans ( 2 of 1lb and 1 of 2lb = 4lb) to reduce the crate weighing 126 ilb to 122 lb.
Therefore, the foreman had packed 122 lb and 126 lb into the two crates.
LikeLike