Enigmatic Code

Programming Enigma Puzzles

Tantalizer 484: Blockwork

From New Scientist #1035, 20th January 1977 [link]

Someone gave my small son a bag of 1in cubes for Christmas and he was soon busy stacking them. First he built a rectangular wall one brick thick. Then he used the rest of the bricks to build another rectangular block, using 140 bricks more than the other. Then he got bored.

But I didn’t, as I spotted an intriguing fact. The sum of the lengths of the twelve edges on each construction was the same. So were the total surface areas of the two constructions (including the faces standing on the carpet). All the six dimensions involved were different.

How many bricks had he been given?

[tantalizer484]

One response to “Tantalizer 484: Blockwork”

1. Jim Randell 21 April 2017 at 8:15 am

Suppose the first block constructed has dimensions (a, b, 1) and the second block has dimensions (x, y, z), then from the information given we have the following equations:

[1] “The second block uses 140 bricks more than the first”

xyz = ab + 140

[2] “The sum of the lengths of the edges was the same for both blocks”

x + y + z = a + b + 1

[3] “The total surface area of the two blocks is the same”

xy + xz + yz = ab + a + b

By expanding (x – 1)(y – 1)(z – 1) we get:

(x – 1)(y – 1)(z – 1) = (xyz) – (xy + xz + yz) + (x + y + z) – 1

And we can substitute the bracketed expressions on the RHS with equations [1], [2], [3] to get:

(x – 1)(y – 1)(z – 1) = (ab + 140) – (ab + a + b) + (a + b + 1) – 1

which simplifies to give:

(x – 1)(y – 1)(z – 1) = 140

So we can consider factors of 140, to find x, y, z, and then find corresponding values for a, b.

The only solution is (x, y, z) = (15, 6, 3) and (a, b, c) = (13, 10, 1).

So the first block consists of 130 bricks, and the second of 270 bricks, giving 400 bricks in total, which will fit nicely into a 20″×20″ tray.

This Python 3 program finds the solution in 50ms.

```from enigma import irange, divisor_pairs, printf

# generate k-tuples of different divisors of n
def divisor_tuples(n, k, s=()):
if k == 1:
if not(s) or n > s[-1]:
yield s + (n,)
else:
for (a, b) in divisor_pairs(n):
if not(s) or a > s[-1]:
yield from divisor_tuples(b, k - 1, s + (a,))

# find x1 > y1 > z1 > 0, where x1 * y1 * z1 = 140
for (z1, y1, x1) in divisor_tuples(140, 3):

# calculate the dimensions of the second block
(x, y, z) = (x1 + 1, y1 + 1, z1 + 1)

# the volumes of the blocks, and the total volume v
v2 = x * y * z
v1 = v2 - 140
v = v1 + v2

# find a > b > 1, where a * b = v1
for (b, a) in divisor_tuples(v1, 2):

# check the perimeter and surface area constraints
if not(x + y + z == a + b + 1): continue
if not(x * y + x * z + y * z == a * b + a + b): continue

# check the dimensions are all different
if len(set((x, y, z, a, b, 1))) != 6: continue

printf("v={v} [v1={v1}: ({a}, {b}, 1), v2={v2}: ({x}, {y}, {z})]")
```

Solution: There were 400 bricks in total.

Note that the divisor_tuples(n, k) function generates tuples of different divisors, to make it a more general analogue of divisor_pairs(n) the tests need to be modified to return tuples containing repeated divisors.