Sunday Times Teaser 3214 – Squaring the Square
by Peter Good
Published Friday April 26 2024 (link)
Clark took a sheet of A4 paper (8.27 × 11.69 inches) and cut out a large square with dimensions a whole number of inches. He cut this into an odd number of smaller squares, each with dimensions a whole number of inches. These were of several different sizes and there was a different number of squares of each size; in fact, the number of different sizes was the largest possible, given the above.
It turns out that there is more than one way that the above dissection can be made, but Clark chose the method that gave the smallest number of smaller squares.
How many smaller squares were there?
10 Comments
Leave one →
My thanks to Frits for analysing my rectangle packing code and discovering a major improvement when duplicate rectangles are being packed. In short, if we have several squares of the same size, each level of recursion will fit the square in every possible position but, although we will have fitted the squares in a different order, the end result will be the same. In effect we have fitted a permutation of these squares when we only need to fit them once. Also, if the first square cannot be fitted in any position, we don’t need to consider duplicate squares since they won’t fit either. Hence for each recursion level we only need to consider one square of each different size.
Here is a download link for jiigsaw.py.
I reused some of my code for Teaser 3069.
A new version:
– allowing for at least three different sizes (instead of four)
– no dummy border anymore
– not placing the largest square in the top left corner (without proof)
– attempting to increase min_sizes as soon as possible
– not trying to fit 1×1 squares into the grid
– skipping variations where larger squares (as of 2×2) are one position of an edge
– alternate searching (between up and down)
Reading Brian’s comment “In short, if an attempt to fit a rectangle at a particular point fails, we can then skip the checking of all its duplicates since they will also fail. This results in an impressive speed improvement.” I realized I could do the same by adding two lines of code at line 38:
The output looks OK but I’m in a slight rush as traveling tomorrow so haven’t been able to thoroughly verify.
I don’t understand how these two lines get the desired speedup; just that they do. Any ideas Brian or Frits?
Hi John,
Without this addition, your loop will fit the current sized square
in all positions in the grid where it fits before moving to the next
recursion level. When we proceed to this next level, it there
are still more of this sized square, it will again be fitted in all
remaining positions, and so on until all of this size of squares
have been fitted.
But, while all the squares have been fitted in different recursion
levels, the end result will be the same! In effect we have fitted
all permutations of these squares when we only needed to fit
them once.
The fix avoids this by only fitting a duplicated square in the first
grid position found in each recursion level.
My earlier explanation was incomplete in not covering this.
See my description just before this check.
When trying different larger squares than 8×8 I noticed my program was getting very slow. The recursion I used isn’t efficient if the list contains many pieces of the same size.
With the new recursion (similar to Brian’s and Jim’s set up) the internal run time now is 4ms.
Here is a more elegant solution to the speed problem. Instead of starting the search from (0, 0) at each recursion, we start from where the search ended in the previous level if the square size of the current level and the previous level are the same. If they are different the search starts from (0, 0).
There are also some changes to avoid having to restore the modified grid by copying it and modifying the copy and by transmitting a new recomposed tuple of square sizes.