1 // Solve a Slither Link puzzle.
15 if (!scanf("%d\n", &max
)) die("input error");
17 for(int i
= 0; i
< max
; i
++) {
19 for(int j
= 0; j
< max
; j
++) {
21 if (c
== EOF
|| c
== '\n') die("input error");
27 board
[i
][j
] = c
- '0';
34 if (c
!= '\n') die("input error");
37 // The size of a puzzle is the squares, but we really care about the edges
38 // between their corners. If there are n^2 squares, then there are (n + 1)^2
42 // Label nodes and edges of grid graph. For example, when max = 3 we have
47 int rtab
[max
* max
+ 1], ctab
[max
* max
+ 1];
55 if (j
== max
- 1) break;
66 zdd_set_vmax(max
* (max
- 1) * 2);
67 // Arcs go from u to v.
68 int au
[zdd_vmax() + 1], av
[zdd_vmax() + 1];
70 for(v
= 1; v
<= max
* max
; v
++) {
71 if (ctab
[v
] != max
- 1) {
73 av
[i
] = vtab
[rtab
[v
]][ctab
[v
] + 1];
76 if (rtab
[v
] != max
- 1) {
78 av
[i
] = vtab
[rtab
[v
] + 1][ctab
[v
]];
84 int done
= 0, todo
= -1;
85 for(int i
= 0; i
< max
- 1; i
++) for(int j
= 0; j
< max
- 1; j
++) {
90 // Top left corner should have two outedges: one right, one down.
91 while(au
[e
] != vtab
[i
][j
]) e
++;
94 EXPECT(au
[e
+ 1] == vtab
[i
][j
]);
95 // One more from the top right corner going down.
96 while(au
[e
] != vtab
[i
][j
+ 1]) e
++;
97 if (av
[e
] != vtab
[i
+ 1][j
+ 1]) e
++;
99 // One more from the bottom left corner going right.
100 while(au
[e
] != vtab
[i
+ 1][j
]) e
++;
102 zdd_contains_exactly_n(n
, a
, 4);
113 while (done
< todo
) {
118 uint32_t p
= zdd_root();
119 uint32_t clue_size
= zdd_last_node();
120 // Construct ZDD of all simple loops constrained by the clues.
121 memo_t node_tab
[zdd_vmax() + 1];
122 for(uint16_t v
= 1; v
<= zdd_vmax(); v
++) memo_init(node_tab
[v
]);
124 uint32_t unique(uint16_t v
, uint32_t lo
, uint32_t hi
) {
125 // Create or return existing node representing !v ? lo : hi.
126 uint32_t key
[2] = { lo
, hi
};
128 int just_created
= memo_it_insert_u(&it
, node_tab
[v
], (void *) key
, 8);
131 memo_it_put(it
, (void *) (r
= zdd_abs_node(v
, lo
, hi
)));
132 if (!(r
<< 15)) printf("node #%x\n", r
);
135 return (uint32_t) memo_it_data(it
);
138 // Similar to the routine in cycle_test.c, but at the same time we respect
139 // the clues. The node p in the clue ZDD therefore is part of the state.
140 memo_t cache
[clue_size
+ 1];
141 for(int i
= 0; i
<= clue_size
; i
++) memo_init(cache
[i
]);
142 uint32_t recurse(uint32_t p
, char *state
, int start
, int count
) {
143 if (p
<= 1) return p
;
145 char newstate
[max
+ 1];
148 uint32_t memoize(uint32_t n
) {
149 if (it
) return (uint32_t) memo_it_put(it
, (void *) n
);
152 // state == NULL is a special case that we use during the first call.
154 for(int j
= au
[e
]; j
<= av
[e
]; j
++) {
155 newstate
[j
- au
[e
]] = j
- au
[e
] + 1;
157 newcount
= av
[e
] - au
[e
] + 1;
159 // The crit-bit tree uses NULL to terminate keys, so we must
160 // do a sort of variable-length encoding.
161 int hack
= start
, hacki
= 0;
163 while(hack
& ~0x7f) {
164 state
[count
+ hacki
] |= 0x80;
167 state
[count
+ hacki
] = hack
;
169 state
[count
+ ++hacki
] = 0;
170 int just_created
= memo_it_insert(&it
, cache
[p
], state
);
171 if (!just_created
&& p
<= 29) return (uint32_t) memo_it_data(it
);
172 // Examine part of state that cannot be affected by future choices,
173 // including whether we include the current edge.
174 // Return false node if it's impossible to continue, otherwise
175 // remove them from the state and continue.
176 int j
= au
[e
] - start
;
178 // Future choices cannot change any dangling edges.
179 for (int i
= 0; i
< j
; i
++) {
180 int otherend
= state
[i
];
181 if (otherend
- 1 != i
) {
182 // Vertex start + i is dangling, and we can no longer connect it
189 for (int i
= 0; i
< j
; i
++) {
190 int otherend
= state
[i
];
191 if (otherend
!= -1 && otherend
- 1 != i
) {
192 // Vertex start + i is dangling, and we can no longer connect it
197 // Copy over the part of the state that is still relevant.
200 newstate
[newcount
++] = n
< 0 ? -1 : n
+ start
- au
[e
];
203 // Add vertices that now matter to our state.
206 newstate
[newcount
++] = j
++ - au
[e
] + 1;
208 // By now newcount == av[e] - au[e].
211 // If we've come to the last edge...
212 if (e
== zdd_vmax()) {
213 if (newstate
[0] == 1) {
214 // ...we have the empty graph:
215 if (zdd_lo(p
)) return memoize(1);
217 // ...or must need the last edge to finish the
218 // loop: we want !V ? FALSE : TRUE. (An elementary family.)
219 return memoize(unique(e
, 0, 1));
223 // First, the case where we don't pick the current edge.
224 // If the clues force us to leave every other element out then we cannot
225 // complete a loop (since we have not completed a loop yet). Similarly
226 // we must use the current edge, we cannot complete a loop. Otherwise
228 uint32_t lo
= 1 >= zdd_lo(p
) ? 0 :
229 recurse(zdd_lo(p
), newstate
, au
[e
], newcount
);
231 // Before we recurse the other case, we must check a couple of things.
232 // Let's initially assume we are done if we pick the current edge!
234 // Examine the other ends of au[e] and av[e], conveniently located at
235 // the ends of newstate[].
237 int v
= newstate
[newcount
- 1];
238 if (u
== -1 || v
== -1) {
239 // At least one of the endpoints of the current edge is already busy.
241 } else if (u
+ au
[e
] - 1 == av
[e
]) {
242 // We have a closed a loop. We're good as long as nothing is dangling...
243 for (int i
= 1; i
< newcount
- 1; i
++) {
244 if (newstate
[i
] != -1 && newstate
[i
] != i
+ 1) {
245 // Dangling link starting at i + au[e] - 1.
250 // ...and the clues allow us to pick no higher edges.
252 uint32_t q
= zdd_hi(p
);
253 while(q
> 1) q
= zdd_lo(q
);
256 } else if (1 == zdd_hi(p
)) {
257 // The clues allow no future edges, so we cannot complete our loop.
260 // Recurse the case when we do pick the current edge. Modify the
261 // state accordingly for the call.
263 newstate
[newcount
- 1] = -1;
266 hi
= recurse(zdd_hi(p
), newstate
, au
[e
], newcount
);
268 // Compress HI -> FALSE nodes.
269 if (!hi
) return memoize(lo
);
270 return memoize(unique(e
, lo
, hi
));
273 zdd_set_root(recurse(p
, NULL
, 0, 0));
274 for(int i
= 0; i
<= clue_size
; i
++) memo_clear(cache
[i
]);
275 for(uint16_t v
= 1; v
<= zdd_vmax(); v
++) memo_clear(node_tab
[v
]);
278 void printsol(int *v
, int vcount
) {
279 char pic
[2 * max
][2 * max
];
280 for(int i
= 0; i
< max
; i
++) {
281 for(int j
= 0; j
< max
; j
++) {
282 pic
[2 * i
][2 * j
] = '.';
283 pic
[2 * i
][2 * j
+ 1] = ' ';
284 pic
[2 * i
+ 1][2 * j
] = ' ';
285 pic
[2 * i
+ 1][2 * j
+ 1] = ' ';
287 pic
[2 * i
][2 * max
- 1] = '\0';
288 pic
[2 * i
+ 1][2 * max
- 1] = '\0';
290 for(int i
= 0; i
< max
- 1; i
++) {
291 for(int j
= 0; j
< max
- 1; j
++) {
292 if (board
[i
][j
] != -1) {
293 pic
[2 * i
+ 1][2 * j
+ 1] = '0' + board
[i
][j
];
298 for(int i
= 0; i
< vcount
; i
++) {
300 int r
= rtab
[au
[e
]] + rtab
[av
[e
]];
301 int c
= ctab
[au
[e
]] + ctab
[av
[e
]];
302 pic
[r
][c
] = r
& 1 ? '|' : '-';
305 /* Plain ASCII output:
306 for(int i = 0; i < 2 * max; i++) puts(pic[i]);
309 for(int i
= 0; i
< 2 * max
- 1; i
++) {
310 for(int j
= 0; j
< 2 * max
; j
++) {
313 int filled(int x
, int y
) {
314 if (x
>= 0 && x
< 2 * max
- 1 && y
>= 0 && y
< 2 * max
- 1 &&
315 pic
[x
][y
] != ' ') return 1;
318 if (filled(i
- 1, j
)) n
+= 1;
319 if (filled(i
, j
- 1)) n
+= 2;
320 if (filled(i
+ 1, j
)) n
+= 4;
321 if (filled(i
, j
+ 1)) n
+= 8;
370 zdd_forall(printsol
);