1 // Solve a Dominosa puzzle.
16 if (!scanf("%d\n", &n
)) die("input error");
17 uint32_t rcount
= n
+ 1, ccount
= n
+ 2;
18 int board
[rcount
][ccount
];
19 inta_t list
[rcount
][ccount
];
21 for(int i
= 0; i
< rcount
; i
++) {
23 for(int j
= 0; j
< ccount
; j
++) {
24 inta_init(list
[i
][j
]);
26 if (c
== EOF
|| c
== '\n') die("input error");
41 board
[i
][j
] = encode(c
);
44 if (c
!= '\n') die("input error");
47 // n is useless as the highest number on a domino. Reuse it as
48 // the total number of dominoes.
49 n
= rcount
* ccount
/ 2;
51 for(int i
= 0; i
< n
; i
++) inta_init(tally
[i
]);
53 int geti(int a
, int b
) {
54 // Return canonical numbering for a given domino.
56 return a
* (a
+ 1) / 2 + b
;
60 for(int i
= 0; i
< rcount
; i
++) {
61 for(int j
= 0; j
< ccount
; j
++) {
64 // Horizontal tiling constraint.
65 inta_append(list
[i
][j
], v
);
66 inta_append(list
[i
][j
+ 1], v
);
69 if (a
< b
) c
= a
, a
= b
, b
= c
;
70 // One domino per board constraint.
71 inta_append(tally
[geti(a
, b
)], v
);
76 // Vertical tiling constraint.
77 inta_append(list
[i
][j
], v
);
78 inta_append(list
[i
+ 1][j
], v
);
81 if (a
< b
) c
= a
, a
= b
, b
= c
;
82 // One domino per board constraint.
83 inta_append(tally
[geti(a
, b
)], v
);
90 int todo
= rcount
- 1;
91 for(int i
= 0; i
< rcount
; i
++) {
92 for(int j
= 0; j
< ccount
; j
++) {
93 zdd_contains_exactly_1(inta_raw(list
[i
][j
]), inta_count(list
[i
][j
]));
94 if (j
) zdd_intersection();
104 while(todo
--) zdd_intersection();
106 int compar(const void *a
, const void *b
) {
107 return inta_count((const inta_ptr
) a
) > inta_count((const inta_ptr
) b
);
109 qsort(tally
, n
, sizeof(inta_t
), compar
);
110 for(int i
= 0; i
< n
; i
++) {
111 //printf("%d/%d\n", i + 1, n);
112 zdd_contains_exactly_1(inta_raw(tally
[i
]), inta_count(tally
[i
]));
116 // Print lexicographically largest solution, assuming it exists.
117 char pic
[2 * rcount
+ 1][2 * ccount
+ 1];
118 for(int i
= 0; i
< rcount
; i
++) {
119 for(int j
= 0; j
< ccount
; j
++) {
120 pic
[2 * i
][2 * j
] = board
[i
][j
] + '0';
121 pic
[2 * i
][2 * j
+ 1] = '|';
122 pic
[2 * i
+ 1][2 * j
] = '-';
123 pic
[2 * i
+ 1][2 * j
+ 1] = '+';
125 pic
[2 * i
][2 * ccount
] = pic
[2 * i
+ 1][2 * ccount
] = '\0';
129 int i
= zdd_v(v
) / (rcount
+ ccount
);
130 int j
= zdd_v(v
) % (rcount
+ ccount
);
132 pic
[2 * i
- 1][2 * (ccount
- 1)] = ' ';
133 } else if (rcount
- 1 == i
) {
134 pic
[2 * i
][2 * j
- 1] = ' ';
139 pic
[2 * i
+ 1][j
- 2] = ' ';
144 for(int i
= 0; i
< 2 * rcount
; i
++) {