2 * Library code to divide up a rectangle into a number of equally
3 * sized ominoes, in a random fashion.
5 * Could use this for generating solved grids of
6 * http://www.nikoli.co.jp/ja/puzzles/block_puzzle/
7 * or for generating the playfield for Jigsaw Sudoku.
11 * This code is restricted to simply connected solutions: that is,
12 * no single polyomino may completely surround another (not even
13 * with a corner visible to the outside world, in the sense that a
14 * 7-omino can `surround' a single square).
16 * It's tempting to think that this is a natural consequence of
17 * all the ominoes being the same size - after all, a division of
18 * anything into 7-ominoes must necessarily have all of them
19 * simply connected, because if one was not then the 1-square
20 * space in the middle could not be part of any 7-omino - but in
21 * fact, for sufficiently large k, it is perfectly possible for a
22 * k-omino to completely surround another k-omino. A simple
23 * example is this one with two 25-ominoes:
25 * +--+--+--+--+--+--+--+
27 * + +--+--+--+--+--+ +
37 * + +--+--+--+--+--+ +
39 * +--+--+--+--+--+--+--+
41 * I claim the smallest k which can manage this is 23. More
44 * If a k-omino P is completely surrounded by another k-omino Q,
45 * such that every edge of P borders on Q, then k >= 23.
49 * It's relatively simple to find the largest _rectangle_ a
50 * k-omino can enclose. So I'll construct my proof in two parts:
51 * firstly, show that no 22-omino or smaller can enclose a
52 * rectangle as large as itself, and secondly, show that no
53 * polyomino can enclose a larger non-rectangle than a rectangle.
55 * The first of those claims:
57 * To surround an m x n rectangle, a polyomino must have 2m
58 * squares along the two m-sides of the rectangle, 2n squares
59 * along the two n-sides, and must fill in at least three of the
60 * corners in order to be connected. Thus, 2(m+n)+3 <= k. We wish
61 * to find the largest value of mn subject to that constraint, and
62 * it's clear that this is achieved when m and n are as close to
63 * equal as possible. (If they aren't, WLOG suppose m < n; then
64 * (m+1)(n-1) = mn + n - m - 1 >= mn, with equality only when
67 * So the area of the largest rectangle which can be enclosed by a
68 * k-omino is given by floor(k'/2) * ceil(k'/2), where k' =
69 * (k-3)/2. This is a monotonic function in k, so there will be a
70 * unique point at which it goes from being smaller than k to
71 * being larger than k. That point is between 22 (maximum area 20)
72 * and 23 (maximum area 25).
76 * Suppose we have an inner polyomino P surrounded by an outer
77 * polyomino Q. I seek to show that if P is non-rectangular, then
78 * P is also non-maximal, in the sense that we can transform P and
79 * Q into a new pair of polyominoes in which P is larger and Q is
80 * at most the same size.
82 * Consider walking along the boundary of P in a clockwise
83 * direction. (We may assume, of course, that there is only _one_
84 * boundary of P, i.e. P has no hole in the middle. If it does
85 * have a hole in the middle, it's _trivially_ non-maximal because
86 * we can just fill the hole in!) Our walk will take us along many
87 * edges between squares; sometimes we might turn left, and
88 * certainly sometimes we will turn right. Always there will be a
89 * square of P on our right, and a square of Q on our left.
91 * The net angle through which we turn during the entire walk must
92 * add up to 360 degrees rightwards. So if there are no left
93 * turns, then we must turn right exactly four times, meaning we
94 * have described a rectangle. Hence, if P is _not_ rectangular,
95 * then there must have been a left turn at some point. A left
96 * turn must mean we walk along two edges of the same square of Q.
98 * Thus, there is some square X in Q which is adjacent to two
99 * diagonally separated squares in P. Let us call those two
100 * squares N and E; let us refer to the other two neighbours of X
101 * as S and W; let us refer to the other mutual neighbour of S and
102 * W as D; and let us refer to the other mutual neighbour of S and
103 * E as Y. In other words, we have named seven squares, arranged
110 * where N and E are in P, and X is in Q.
112 * Clearly at least one of W and S must be in Q (because otherwise
113 * X would not be connected to any other square in Q, and would
114 * hence have to be the whole of Q; and evidently if Q were a
115 * 1-omino it could not enclose _anything_). So we divide into
118 * If both W and S are in Q, then we take X out of Q and put it in
119 * P, which does not expose any edge of P. If this disconnects Q,
120 * then we can reconnect it by adding D to Q.
122 * If only one of W and S is in Q, then wlog let it be W. If S is
123 * in _P_, then we have a particularly easy case: we can simply
124 * take X out of Q and add it to P, and this cannot disconnect X
125 * since X was a leaf square of Q.
127 * Our remaining case is that W is in Q and S is in neither P nor
128 * Q. Again we take X out of Q and put it in P; we also add S to
129 * Q. This ensures we do not expose an edge of P, but we must now
130 * prove that S is adjacent to some other existing square of Q so
131 * that we haven't disconnected Q by adding it.
133 * To do this, we recall that we walked along the edge XE, and
134 * then turned left to walk along XN. So just before doing all
135 * that, we must have reached the corner XSE, and we must have
136 * done it by walking along one of the three edges meeting at that
137 * corner which are _not_ XE. It can't have been SY, since S would
138 * then have been on our left and it isn't in Q; and it can't have
139 * been XS, since S would then have been on our right and it isn't
140 * in P. So it must have been YE, in which case Y was on our left,
143 * So in all cases we have shown that we can take X out of Q and
144 * add it to P, and add at most one square to Q to restore the
145 * containment and connectedness properties. Hence, we can keep
146 * doing this until we run out of left turns and P becomes
151 * Anyway, that entire proof was a bit of a sidetrack. The point
152 * is, although constructions of this type are possible for
153 * sufficiently large k, divvy_rectangle() will never generate
154 * them. This could be considered a weakness for some purposes, in
155 * the sense that we can't generate all possible divisions.
156 * However, there are many divisions which we are highly unlikely
157 * to generate anyway, so in practice it probably isn't _too_ bad.
159 * If I wanted to fix this issue, I would have to make the rules
160 * more complicated for determining when a square can safely be
161 * _removed_ from a polyomino. Adding one becomes easier (a square
162 * may be added to a polyomino iff it is 4-adjacent to any square
163 * currently part of the polyomino, and the current test for loop
164 * formation may be dispensed with), but to determine which
165 * squares may be removed we must now resort to analysis of the
166 * overall structure of the polyomino rather than the simple local
167 * properties we can currently get away with measuring.
171 * Possible improvements which might cut the fail rate:
173 * - instead of picking one omino to extend in an iteration, try
174 * them all in succession (in a randomised order)
176 * - (for real rigour) instead of bfsing over ominoes, bfs over
177 * the space of possible _removed squares_. That way we aren't
178 * limited to randomly choosing a single square to remove from
179 * an omino and failing if that particular square doesn't
182 * However, I don't currently think it's necessary to do either of
183 * these, because the failure rate is already low enough to be
184 * easily tolerable, under all circumstances I've been able to
196 * Subroutine which implements a function used in computing both
197 * whether a square can safely be added to an omino, and whether
198 * it can safely be removed.
200 * We enumerate the eight squares 8-adjacent to this one, in
201 * cyclic order. We go round that loop and count the number of
202 * times we find a square owned by the target omino next to one
203 * not owned by it. We then return success iff that count is 2.
205 * When adding a square to an omino, this is precisely the
206 * criterion which tells us that adding the square won't leave a
207 * hole in the middle of the omino. (If it did, then things get
208 * more complicated; see above.)
210 * When removing a square from an omino, the _same_ criterion
211 * tells us that removing the square won't disconnect the omino.
212 * (This only works _because_ we've ensured the omino is simply
215 static int addremcommon(int w
, int h
, int x
, int y
, int *own
, int val
)
220 for (dir
= 0; dir
< 8; dir
++) {
221 int dx
= ((dir
& 3) == 2 ? 0 : dir
> 2 && dir
< 6 ? +1 : -1);
222 int dy
= ((dir
& 3) == 0 ? 0 : dir
< 4 ? -1 : +1);
223 int sx
= x
+dx
, sy
= y
+dy
;
225 if (sx
< 0 || sx
>= w
|| sy
< 0 || sy
>= h
)
226 neighbours
[dir
] = -1; /* outside the grid */
228 neighbours
[dir
] = own
[sy
*w
+sx
];
232 * To begin with, check 4-adjacency.
234 if (neighbours
[0] != val
&& neighbours
[2] != val
&&
235 neighbours
[4] != val
&& neighbours
[6] != val
)
240 for (dir
= 0; dir
< 8; dir
++) {
241 int next
= (dir
+ 1) & 7;
242 int gotthis
= (neighbours
[dir
] == val
);
243 int gotnext
= (neighbours
[next
] == val
);
245 if (gotthis
!= gotnext
)
253 * w and h are the dimensions of the rectangle.
255 * k is the size of the required ominoes. (So k must divide w*h,
258 * The returned result is a w*h-sized dsf.
260 * In both of the above suggested use cases, the user would
261 * probably want w==h==k, but that isn't a requirement.
263 static int *divvy_internal(int w
, int h
, int k
, random_state
*rs
)
265 int *order
, *queue
, *tmp
, *own
, *sizes
, *addable
, *removable
, *retdsf
;
267 int i
, j
, n
, x
, y
, qhead
, qtail
;
272 order
= snewn(wh
, int);
273 tmp
= snewn(wh
, int);
274 own
= snewn(wh
, int);
275 sizes
= snewn(n
, int);
276 queue
= snewn(n
, int);
277 addable
= snewn(wh
*4, int);
278 removable
= snewn(wh
, int);
281 * Permute the grid squares into a random order, which will be
282 * used for iterating over the grid whenever we need to search
283 * for something. This prevents directional bias and arranges
284 * for the answer to be non-deterministic.
286 for (i
= 0; i
< wh
; i
++)
288 shuffle(order
, wh
, sizeof(*order
), rs
);
291 * Begin by choosing a starting square at random for each
294 for (i
= 0; i
< wh
; i
++) {
297 for (i
= 0; i
< n
; i
++) {
303 * Now repeatedly pick a random omino which isn't already at
304 * the target size, and find a way to expand it by one. This
305 * may involve stealing a square from another omino, in which
306 * case we then re-expand that omino, forming a chain of
307 * square-stealing which terminates in an as yet unclaimed
308 * square. Hence every successful iteration around this loop
309 * causes the number of unclaimed squares to drop by one, and
310 * so the process is bounded in duration.
314 #ifdef DIVVY_DIAGNOSTICS
317 printf("Top of loop. Current grid:\n");
318 for (y
= 0; y
< h
; y
++) {
319 for (x
= 0; x
< w
; x
++)
320 printf("%3d", own
[y
*w
+x
]);
327 * Go over the grid and figure out which squares can
328 * safely be added to, or removed from, each omino. We
329 * don't take account of other ominoes in this process, so
330 * we will often end up knowing that a square can be
331 * poached from one omino by another.
333 * For each square, there may be up to four ominoes to
334 * which it can be added (those to which it is
337 for (y
= 0; y
< h
; y
++) {
338 for (x
= 0; x
< w
; x
++) {
344 removable
[yx
] = FALSE
; /* can't remove if not owned! */
345 } else if (sizes
[curr
] == 1) {
346 removable
[yx
] = TRUE
; /* can always remove a singleton */
349 * See if this square can be removed from its
350 * omino without disconnecting it.
352 removable
[yx
] = addremcommon(w
, h
, x
, y
, own
, curr
);
355 for (dir
= 0; dir
< 4; dir
++) {
356 int dx
= (dir
== 0 ? -1 : dir
== 1 ? +1 : 0);
357 int dy
= (dir
== 2 ? -1 : dir
== 3 ? +1 : 0);
358 int sx
= x
+ dx
, sy
= y
+ dy
;
361 addable
[yx
*4+dir
] = -1;
363 if (sx
< 0 || sx
>= w
|| sy
< 0 || sy
>= h
)
364 continue; /* no omino here! */
366 continue; /* also no omino here */
367 if (own
[syx
] == own
[yx
])
368 continue; /* we already got one */
369 if (!addremcommon(w
, h
, x
, y
, own
, own
[syx
]))
370 continue; /* would non-simply connect the omino */
372 addable
[yx
*4+dir
] = own
[syx
];
377 for (i
= j
= 0; i
< n
; i
++)
381 break; /* all ominoes are complete! */
382 j
= tmp
[random_upto(rs
, j
)];
383 #ifdef DIVVY_DIAGNOSTICS
384 printf("Trying to extend %d\n", j
);
388 * So we're trying to expand omino j. We breadth-first
389 * search out from j across the space of ominoes.
391 * For bfs purposes, we use two elements of tmp per omino:
392 * tmp[2*i+0] tells us which omino we got to i from, and
393 * tmp[2*i+1] numbers the grid square that omino stole
396 * This requires that wh (the size of tmp) is at least 2n,
397 * i.e. k is at least 2. There would have been nothing to
398 * stop a user calling this function with k=1, but if they
399 * did then we wouldn't have got to _here_ in the code -
400 * we would have noticed above that all ominoes were
401 * already at their target sizes, and terminated :-)
404 for (i
= 0; i
< n
; i
++)
405 tmp
[2*i
] = tmp
[2*i
+1] = -1;
408 tmp
[2*j
] = tmp
[2*j
+1] = -2; /* special value: `starting point' */
410 while (qhead
< qtail
) {
416 * We wish to expand omino j. However, we might have
417 * got here by omino j having a square stolen from it,
418 * so first of all we must temporarily mark that
419 * square as not belonging to j, so that our adjacency
420 * calculations don't assume j _does_ belong to us.
424 assert(own
[tmpsq
] == j
);
429 * OK. Now begin by seeing if we can find any
430 * unclaimed square into which we can expand omino j.
431 * If we find one, the entire bfs terminates.
433 for (i
= 0; i
< wh
; i
++) {
436 if (own
[order
[i
]] != -1)
437 continue; /* this square is claimed */
440 * Special case: if our current omino was size 1
441 * and then had a square stolen from it, it's now
442 * size zero, which means it's valid to `expand'
443 * it into _any_ unclaimed square.
445 if (sizes
[j
] == 1 && tmpsq
>= 0)
449 * Failing that, we must do the full test for
452 for (dir
= 0; dir
< 4; dir
++)
453 if (addable
[order
[i
]*4+dir
] == j
) {
455 * We know this square is addable to this
456 * omino with the grid in the state it had
457 * at the top of the loop. However, we
458 * must now check that it's _still_
459 * addable to this omino when the omino is
460 * missing a square. To do this it's only
461 * necessary to re-check addremcommon.
463 if (!addremcommon(w
, h
, order
[i
]%w
, order
[i
]/w
,
469 continue; /* we can't add this square to j */
471 break; /* got one! */
477 * Restore the temporarily removed square _before_
478 * we start shifting ownerships about.
484 * We are done. We can add square i to omino j,
485 * and then backtrack along the trail in tmp
486 * moving squares between ominoes, ending up
487 * expanding our starting omino by one.
489 #ifdef DIVVY_DIAGNOSTICS
490 printf("(%d,%d)", i
%w
, i
/w
);
494 #ifdef DIVVY_DIAGNOSTICS
501 #ifdef DIVVY_DIAGNOSTICS
502 printf("; (%d,%d)", i
%w
, i
/w
);
505 #ifdef DIVVY_DIAGNOSTICS
510 * Increment the size of the starting omino.
515 * Terminate the bfs loop.
521 * If we get here, we haven't been able to expand
522 * omino j into an unclaimed square. So now we begin
523 * to investigate expanding it into squares which are
524 * claimed by ominoes the bfs has not yet visited.
526 for (i
= 0; i
< wh
; i
++) {
530 if (nj
< 0 || tmp
[2*nj
] != -1)
531 continue; /* unclaimed, or owned by wrong omino */
532 if (!removable
[order
[i
]])
533 continue; /* its omino won't let it go */
535 for (dir
= 0; dir
< 4; dir
++)
536 if (addable
[order
[i
]*4+dir
] == j
) {
538 * As above, re-check addremcommon.
540 if (!addremcommon(w
, h
, order
[i
]%w
, order
[i
]/w
,
545 * We have found a square we can use to
546 * expand omino j, at the expense of the
547 * as-yet unvisited omino nj. So add this
553 tmp
[2*nj
+1] = order
[i
];
556 * Now terminate the loop over dir, to
557 * ensure we don't accidentally add the
558 * same omino twice to the queue.
565 * Restore the temporarily removed square.
571 * Advance the queue head.
576 if (qhead
== qtail
) {
578 * We have finished the bfs and not found any way to
579 * expand omino j. Panic, and return failure.
581 * FIXME: or should we loop over all ominoes before we
584 #ifdef DIVVY_DIAGNOSTICS
592 #ifdef DIVVY_DIAGNOSTICS
595 printf("SUCCESS! Final grid:\n");
596 for (y
= 0; y
< h
; y
++) {
597 for (x
= 0; x
< w
; x
++)
598 printf("%3d", own
[y
*w
+x
]);
605 * Construct the output dsf.
607 for (i
= 0; i
< wh
; i
++) {
608 assert(own
[i
] >= 0 && own
[i
] < n
);
611 retdsf
= snew_dsf(wh
);
612 for (i
= 0; i
< wh
; i
++) {
613 dsf_merge(retdsf
, i
, tmp
[own
[i
]]);
617 * Construct the output dsf a different way, to verify that
618 * the ominoes really are k-ominoes and we haven't
619 * accidentally split one into two disconnected pieces.
622 for (y
= 0; y
< h
; y
++)
623 for (x
= 0; x
+1 < w
; x
++)
624 if (own
[y
*w
+x
] == own
[y
*w
+(x
+1)])
625 dsf_merge(tmp
, y
*w
+x
, y
*w
+(x
+1));
626 for (x
= 0; x
< w
; x
++)
627 for (y
= 0; y
+1 < h
; y
++)
628 if (own
[y
*w
+x
] == own
[(y
+1)*w
+x
])
629 dsf_merge(tmp
, y
*w
+x
, (y
+1)*w
+x
);
630 for (i
= 0; i
< wh
; i
++) {
631 j
= dsf_canonify(retdsf
, i
);
632 assert(dsf_canonify(tmp
, j
) == dsf_canonify(tmp
, i
));
638 * Free our temporary working space.
655 static int fail_counter
= 0;
658 int *divvy_rectangle(int w
, int h
, int k
, random_state
*rs
)
663 ret
= divvy_internal(w
, h
, k
, rs
);
678 * gcc -g -O0 -DTESTMODE -I.. -o divvy divvy.c ../random.c ../malloc.c ../dsf.c ../misc.c ../nullfe.c
682 * gcc -g -O0 -DDIVVY_DIAGNOSTICS -DTESTMODE -I.. -o divvy divvy.c ../random.c ../malloc.c ../dsf.c ../misc.c ../nullfe.c
685 int main(int argc
, char **argv
)
689 int w
= 9, h
= 4, k
= 6, tries
= 100;
692 rs
= random_new("123456", 6);
701 tries
= atoi(argv
[4]);
703 for (i
= 0; i
< tries
; i
++) {
706 dsf
= divvy_rectangle(w
, h
, k
, rs
);
709 for (y
= 0; y
<= 2*h
; y
++) {
710 for (x
= 0; x
<= 2*w
; x
++) {
711 int miny
= y
/2 - 1, maxy
= y
/2;
712 int minx
= x
/2 - 1, maxx
= x
/2;
713 int classes
[4], tx
, ty
;
714 for (ty
= 0; ty
< 2; ty
++)
715 for (tx
= 0; tx
< 2; tx
++) {
716 int cx
= minx
+tx
, cy
= miny
+ty
;
717 if (cx
< 0 || cx
>= w
|| cy
< 0 || cy
>= h
)
718 classes
[ty
*2+tx
] = -1;
720 classes
[ty
*2+tx
] = dsf_canonify(dsf
, cy
*w
+cx
);
722 switch (y
%2 * 2 + x
%2) {
725 * Cases for the corner:
727 * - if all four surrounding squares belong
728 * to the same omino, we print a space.
730 * - if the top two are the same and the
731 * bottom two are the same, we print a
734 * - if the left two are the same and the
735 * right two are the same, we print a
738 * - otherwise, we print a cross.
740 if (classes
[0] == classes
[1] &&
741 classes
[1] == classes
[2] &&
742 classes
[2] == classes
[3])
744 else if (classes
[0] == classes
[1] &&
745 classes
[2] == classes
[3])
747 else if (classes
[0] == classes
[2] &&
748 classes
[1] == classes
[3])
753 case 1: /* horiz edge */
754 if (classes
[1] == classes
[3])
759 case 2: /* vert edge */
760 if (classes
[2] == classes
[3])
765 case 3: /* square centre */
776 printf("%d retries needed for %d successes\n", fail_counter
, tries
);