~ubuntu-branches/ubuntu/saucy/sgt-puzzles/saucy

« back to all changes in this revision

Viewing changes to divvy.c

  • Committer: Bazaar Package Importer
  • Author(s): Ben Hutchings
  • Date: 2008-04-13 17:39:38 UTC
  • mto: (1.1.6 upstream) (3.1.2 lenny)
  • mto: This revision was merged to the branch mainline in revision 9.
  • Revision ID: james.westby@ubuntu.com-20080413173938-nnrvlls98m6ky6eq
ImportĀ upstreamĀ versionĀ 7983

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * Library code to divide up a rectangle into a number of equally
 
3
 * sized ominoes, in a random fashion.
 
4
 * 
 
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.
 
8
 */
 
9
 
 
10
/*
 
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).
 
15
 * 
 
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:
 
24
 * 
 
25
 *   +--+--+--+--+--+--+--+
 
26
 *   |                    |
 
27
 *   +  +--+--+--+--+--+  +
 
28
 *   |  |              |  |
 
29
 *   +  +              +  +
 
30
 *   |  |              |  |
 
31
 *   +  +              +  +--+
 
32
 *   |  |              |     |
 
33
 *   +  +              +  +--+
 
34
 *   |  |              |  |
 
35
 *   +  +              +  +
 
36
 *   |  |              |  |
 
37
 *   +  +--+--+--+--+--+  +
 
38
 *   |                    |
 
39
 *   +--+--+--+--+--+--+--+
 
40
 * 
 
41
 * I claim the smallest k which can manage this is 23. More
 
42
 * formally:
 
43
 * 
 
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.
 
46
 * 
 
47
 * Proof:
 
48
 * 
 
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.
 
54
 * 
 
55
 * The first of those claims:
 
56
 * 
 
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
 
65
 * m=n-1.)
 
66
 * 
 
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).
 
73
 * 
 
74
 * The second claim:
 
75
 * 
 
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.
 
81
 * 
 
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.
 
90
 * 
 
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.
 
97
 * 
 
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
 
104
 * thus:
 
105
 * 
 
106
 *     N
 
107
 *   W X E
 
108
 *   D S Y
 
109
 * 
 
110
 * where N and E are in P, and X is in Q.
 
111
 * 
 
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
 
116
 * cases:
 
117
 * 
 
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.
 
121
 * 
 
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.
 
126
 * 
 
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.
 
132
 * 
 
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,
 
141
 * and hence is in Q.
 
142
 * 
 
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
 
147
 * rectangular. []
 
148
 * 
 
149
 * ------------
 
150
 * 
 
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.
 
158
 * 
 
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.
 
168
 */
 
169
 
 
170
/*
 
171
 * Possible improvements which might cut the fail rate:
 
172
 * 
 
173
 *  - instead of picking one omino to extend in an iteration, try
 
174
 *    them all in succession (in a randomised order)
 
175
 * 
 
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
 
180
 *    happen to work.
 
181
 * 
 
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
 
185
 * think of.
 
186
 */
 
187
 
 
188
#include <assert.h>
 
189
#include <stdio.h>
 
190
#include <stdlib.h>
 
191
#include <stddef.h>
 
192
 
 
193
#include "puzzles.h"
 
194
 
 
195
/*
 
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.
 
199
 * 
 
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.
 
204
 * 
 
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.)
 
209
 * 
 
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
 
213
 * connected.)
 
214
 */
 
215
static int addremcommon(int w, int h, int x, int y, int *own, int val)
 
216
{
 
217
    int neighbours[8];
 
218
    int dir, count;
 
219
 
 
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;
 
224
 
 
225
        if (sx < 0 || sx >= w || sy < 0 || sy >= h)
 
226
            neighbours[dir] = -1;      /* outside the grid */
 
227
        else
 
228
            neighbours[dir] = own[sy*w+sx];
 
229
    }
 
230
 
 
231
    /*
 
232
     * To begin with, check 4-adjacency.
 
233
     */
 
234
    if (neighbours[0] != val && neighbours[2] != val &&
 
235
        neighbours[4] != val && neighbours[6] != val)
 
236
        return FALSE;
 
237
 
 
238
    count = 0;
 
239
 
 
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);
 
244
 
 
245
        if (gotthis != gotnext)
 
246
            count++;
 
247
    }
 
248
 
 
249
    return (count == 2);
 
250
}
 
251
 
 
252
/*
 
253
 * w and h are the dimensions of the rectangle.
 
254
 * 
 
255
 * k is the size of the required ominoes. (So k must divide w*h,
 
256
 * of course.)
 
257
 * 
 
258
 * The returned result is a w*h-sized dsf.
 
259
 * 
 
260
 * In both of the above suggested use cases, the user would
 
261
 * probably want w==h==k, but that isn't a requirement.
 
262
 */
 
263
static int *divvy_internal(int w, int h, int k, random_state *rs)
 
264
{
 
265
    int *order, *queue, *tmp, *own, *sizes, *addable, *removable, *retdsf;
 
266
    int wh = w*h;
 
267
    int i, j, n, x, y, qhead, qtail;
 
268
 
 
269
    n = wh / k;
 
270
    assert(wh == k*n);
 
271
 
 
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);
 
279
 
 
280
    /*
 
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.
 
285
     */
 
286
    for (i = 0; i < wh; i++)
 
287
        order[i] = i;
 
288
    shuffle(order, wh, sizeof(*order), rs);
 
289
 
 
290
    /*
 
291
     * Begin by choosing a starting square at random for each
 
292
     * omino.
 
293
     */
 
294
    for (i = 0; i < wh; i++) {
 
295
        own[i] = -1;
 
296
    }
 
297
    for (i = 0; i < n; i++) {
 
298
        own[order[i]] = i;
 
299
        sizes[i] = 1;
 
300
    }
 
301
 
 
302
    /*
 
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.
 
311
     */
 
312
    while (1) {
 
313
 
 
314
#ifdef DIVVY_DIAGNOSTICS
 
315
        {
 
316
            int x, y;
 
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]);
 
321
                printf("\n");
 
322
            }
 
323
        }
 
324
#endif
 
325
 
 
326
        /*
 
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.
 
332
         * 
 
333
         * For each square, there may be up to four ominoes to
 
334
         * which it can be added (those to which it is
 
335
         * 4-adjacent).
 
336
         */
 
337
        for (y = 0; y < h; y++) {
 
338
            for (x = 0; x < w; x++) {
 
339
                int yx = y*w+x;
 
340
                int curr = own[yx];
 
341
                int dir;
 
342
 
 
343
                if (curr < 0) {
 
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 */
 
347
                } else {
 
348
                    /*
 
349
                     * See if this square can be removed from its
 
350
                     * omino without disconnecting it.
 
351
                     */
 
352
                    removable[yx] = addremcommon(w, h, x, y, own, curr);
 
353
                }
 
354
 
 
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;
 
359
                    int syx = sy*w+sx;
 
360
 
 
361
                    addable[yx*4+dir] = -1;
 
362
 
 
363
                    if (sx < 0 || sx >= w || sy < 0 || sy >= h)
 
364
                        continue;      /* no omino here! */
 
365
                    if (own[syx] < 0)
 
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 */
 
371
                    
 
372
                    addable[yx*4+dir] = own[syx];
 
373
                }
 
374
            }
 
375
        }
 
376
 
 
377
        for (i = j = 0; i < n; i++)
 
378
            if (sizes[i] < k)
 
379
                tmp[j++] = i;
 
380
        if (j == 0)
 
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);
 
385
#endif
 
386
 
 
387
        /*
 
388
         * So we're trying to expand omino j. We breadth-first
 
389
         * search out from j across the space of ominoes.
 
390
         * 
 
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
 
394
         * from us.
 
395
         * 
 
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 :-)
 
402
         */
 
403
        assert(wh >= 2*n);
 
404
        for (i = 0; i < n; i++)
 
405
            tmp[2*i] = tmp[2*i+1] = -1;
 
406
        qhead = qtail = 0;
 
407
        queue[qtail++] = j;
 
408
        tmp[2*j] = tmp[2*j+1] = -2;    /* special value: `starting point' */
 
409
 
 
410
        while (qhead < qtail) {
 
411
            int tmpsq;
 
412
 
 
413
            j = queue[qhead];
 
414
 
 
415
            /*
 
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.
 
421
             */
 
422
            tmpsq = tmp[2*j+1];
 
423
            if (tmpsq >= 0) {
 
424
                assert(own[tmpsq] == j);
 
425
                own[tmpsq] = -3;
 
426
            }
 
427
 
 
428
            /*
 
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.
 
432
             */
 
433
            for (i = 0; i < wh; i++) {
 
434
                int dir;
 
435
 
 
436
                if (own[order[i]] != -1)
 
437
                    continue;          /* this square is claimed */
 
438
 
 
439
                /*
 
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.
 
444
                 */
 
445
                if (sizes[j] == 1 && tmpsq >= 0)
 
446
                    break;             /* got one */
 
447
 
 
448
                /*
 
449
                 * Failing that, we must do the full test for
 
450
                 * addability.
 
451
                 */
 
452
                for (dir = 0; dir < 4; dir++)
 
453
                    if (addable[order[i]*4+dir] == j) {
 
454
                        /*
 
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.
 
462
                         */
 
463
                        if (!addremcommon(w, h, order[i]%w, order[i]/w,
 
464
                                          own, j))
 
465
                            continue;
 
466
                        break;
 
467
                    }
 
468
                if (dir == 4)
 
469
                    continue;          /* we can't add this square to j */
 
470
 
 
471
                break;                 /* got one! */
 
472
            }
 
473
            if (i < wh) {
 
474
                i = order[i];
 
475
 
 
476
                /*
 
477
                 * Restore the temporarily removed square _before_
 
478
                 * we start shifting ownerships about.
 
479
                 */
 
480
                if (tmpsq >= 0)
 
481
                    own[tmpsq] = j;
 
482
 
 
483
                /*
 
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.
 
488
                 */
 
489
#ifdef DIVVY_DIAGNOSTICS
 
490
                printf("(%d,%d)", i%w, i/w);
 
491
#endif
 
492
                while (1) {
 
493
                    own[i] = j;
 
494
#ifdef DIVVY_DIAGNOSTICS
 
495
                    printf(" -> %d", j);
 
496
#endif
 
497
                    if (tmp[2*j] == -2)
 
498
                        break;
 
499
                    i = tmp[2*j+1];
 
500
                    j = tmp[2*j];
 
501
#ifdef DIVVY_DIAGNOSTICS
 
502
                    printf("; (%d,%d)", i%w, i/w);
 
503
#endif
 
504
                }
 
505
#ifdef DIVVY_DIAGNOSTICS
 
506
                printf("\n");
 
507
#endif
 
508
 
 
509
                /*
 
510
                 * Increment the size of the starting omino.
 
511
                 */
 
512
                sizes[j]++;
 
513
 
 
514
                /*
 
515
                 * Terminate the bfs loop.
 
516
                 */
 
517
                break;
 
518
            }
 
519
 
 
520
            /*
 
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.
 
525
             */
 
526
            for (i = 0; i < wh; i++) {
 
527
                int dir, nj;
 
528
 
 
529
                nj = own[order[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 */
 
534
 
 
535
                for (dir = 0; dir < 4; dir++)
 
536
                    if (addable[order[i]*4+dir] == j) {
 
537
                        /*
 
538
                         * As above, re-check addremcommon.
 
539
                         */
 
540
                        if (!addremcommon(w, h, order[i]%w, order[i]/w,
 
541
                                          own, j))
 
542
                            continue;
 
543
 
 
544
                        /*
 
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
 
548
                         * to the bfs queue.
 
549
                         */
 
550
                        assert(qtail < n);
 
551
                        queue[qtail++] = nj;
 
552
                        tmp[2*nj] = j;
 
553
                        tmp[2*nj+1] = order[i];
 
554
 
 
555
                        /*
 
556
                         * Now terminate the loop over dir, to
 
557
                         * ensure we don't accidentally add the
 
558
                         * same omino twice to the queue.
 
559
                         */
 
560
                        break;
 
561
                    }
 
562
            }
 
563
 
 
564
            /*
 
565
             * Restore the temporarily removed square.
 
566
             */
 
567
            if (tmpsq >= 0)
 
568
                own[tmpsq] = j;
 
569
 
 
570
            /*
 
571
             * Advance the queue head.
 
572
             */
 
573
            qhead++;
 
574
        }
 
575
 
 
576
        if (qhead == qtail) {
 
577
            /*
 
578
             * We have finished the bfs and not found any way to
 
579
             * expand omino j. Panic, and return failure.
 
580
             * 
 
581
             * FIXME: or should we loop over all ominoes before we
 
582
             * give up?
 
583
             */
 
584
#ifdef DIVVY_DIAGNOSTICS
 
585
            printf("FAIL!\n");
 
586
#endif
 
587
            retdsf = NULL;
 
588
            goto cleanup;
 
589
        }
 
590
    }
 
591
 
 
592
#ifdef DIVVY_DIAGNOSTICS
 
593
    {
 
594
        int x, y;
 
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]);
 
599
            printf("\n");
 
600
        }
 
601
    }
 
602
#endif
 
603
 
 
604
    /*
 
605
     * Construct the output dsf.
 
606
     */
 
607
    for (i = 0; i < wh; i++) {
 
608
        assert(own[i] >= 0 && own[i] < n);
 
609
        tmp[own[i]] = i;
 
610
    }
 
611
    retdsf = snew_dsf(wh);
 
612
    for (i = 0; i < wh; i++) {
 
613
        dsf_merge(retdsf, i, tmp[own[i]]);
 
614
    }
 
615
 
 
616
    /*
 
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.
 
620
     */
 
621
    dsf_init(tmp, wh);
 
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));
 
633
    }
 
634
 
 
635
    cleanup:
 
636
 
 
637
    /*
 
638
     * Free our temporary working space.
 
639
     */
 
640
    sfree(order);
 
641
    sfree(tmp);
 
642
    sfree(own);
 
643
    sfree(sizes);
 
644
    sfree(queue);
 
645
    sfree(addable);
 
646
    sfree(removable);
 
647
 
 
648
    /*
 
649
     * And we're done.
 
650
     */
 
651
    return retdsf;
 
652
}
 
653
 
 
654
#ifdef TESTMODE
 
655
static int fail_counter = 0;
 
656
#endif
 
657
 
 
658
int *divvy_rectangle(int w, int h, int k, random_state *rs)
 
659
{
 
660
    int *ret;
 
661
 
 
662
    do {
 
663
        ret = divvy_internal(w, h, k, rs);
 
664
 
 
665
#ifdef TESTMODE
 
666
        if (!ret)
 
667
            fail_counter++;
 
668
#endif
 
669
 
 
670
    } while (!ret);
 
671
 
 
672
    return ret;
 
673
}
 
674
 
 
675
#ifdef TESTMODE
 
676
 
 
677
/*
 
678
 * gcc -g -O0 -DTESTMODE -I.. -o divvy divvy.c ../random.c ../malloc.c ../dsf.c ../misc.c ../nullfe.c
 
679
 * 
 
680
 * or to debug
 
681
 * 
 
682
 * gcc -g -O0 -DDIVVY_DIAGNOSTICS -DTESTMODE -I.. -o divvy divvy.c ../random.c ../malloc.c ../dsf.c ../misc.c ../nullfe.c
 
683
 */
 
684
 
 
685
int main(int argc, char **argv)
 
686
{
 
687
    int *dsf;
 
688
    int i;
 
689
    int w = 9, h = 4, k = 6, tries = 100;
 
690
    random_state *rs;
 
691
 
 
692
    rs = random_new("123456", 6);
 
693
 
 
694
    if (argc > 1)
 
695
        w = atoi(argv[1]);
 
696
    if (argc > 2)
 
697
        h = atoi(argv[2]);
 
698
    if (argc > 3)
 
699
        k = atoi(argv[3]);
 
700
    if (argc > 4)
 
701
        tries = atoi(argv[4]);
 
702
 
 
703
    for (i = 0; i < tries; i++) {
 
704
        int x, y;
 
705
 
 
706
        dsf = divvy_rectangle(w, h, k, rs);
 
707
        assert(dsf);
 
708
 
 
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;
 
719
                        else
 
720
                            classes[ty*2+tx] = dsf_canonify(dsf, cy*w+cx);
 
721
                    }
 
722
                switch (y%2 * 2 + x%2) {
 
723
                  case 0:              /* corner */
 
724
                    /*
 
725
                     * Cases for the corner:
 
726
                     *
 
727
                     *  - if all four surrounding squares belong
 
728
                     *    to the same omino, we print a space.
 
729
                     *
 
730
                     *  - if the top two are the same and the
 
731
                     *    bottom two are the same, we print a
 
732
                     *    horizontal line.
 
733
                     *
 
734
                     *  - if the left two are the same and the
 
735
                     *    right two are the same, we print a
 
736
                     *    vertical line.
 
737
                     *
 
738
                     *  - otherwise, we print a cross.
 
739
                     */
 
740
                    if (classes[0] == classes[1] &&
 
741
                        classes[1] == classes[2] &&
 
742
                        classes[2] == classes[3])
 
743
                        printf(" ");
 
744
                    else if (classes[0] == classes[1] &&
 
745
                             classes[2] == classes[3])
 
746
                        printf("-");
 
747
                    else if (classes[0] == classes[2] &&
 
748
                             classes[1] == classes[3])
 
749
                        printf("|");
 
750
                    else
 
751
                        printf("+");
 
752
                    break;
 
753
                  case 1:              /* horiz edge */
 
754
                    if (classes[1] == classes[3])
 
755
                        printf("  ");
 
756
                    else
 
757
                        printf("--");
 
758
                    break;
 
759
                  case 2:              /* vert edge */
 
760
                    if (classes[2] == classes[3])
 
761
                        printf(" ");
 
762
                    else
 
763
                        printf("|");
 
764
                    break;
 
765
                  case 3:              /* square centre */
 
766
                    printf("  ");
 
767
                    break;
 
768
                }
 
769
            }
 
770
            printf("\n");
 
771
        }
 
772
        printf("\n");
 
773
        sfree(dsf);
 
774
    }
 
775
 
 
776
    printf("%d retries needed for %d successes\n", fail_counter, tries);
 
777
 
 
778
    return 0;
 
779
}
 
780
 
 
781
#endif