Orbiter 2022
Combinatorial Objects
pentomino_puzzle.cpp
Go to the documentation of this file.
1/*
2 * pentomino_puzzle.cpp
3 *
4 * Created on: Nov 9, 2019
5 * Author: anton
6 */
7
8
9
10
11#include "foundations.h"
12
13using namespace std;
14
15namespace orbiter {
16namespace layer1_foundations {
17namespace combinatorics {
18
19static void pentomino_puzzle_compute_image_function(data_structures::set_of_sets *S,
20 void *compute_image_data, int elt_idx,
21 int gen_idx, int &idx_of_image, int verbose_level);
22static int pentomino_puzzle_compare_func(void *vec, void *a, int b, void *data_for_compare);
23
24
25void pentomino_puzzle::main(int verbose_level)
26{
30
31
32
33 int nb_eqns;
34 int nb_vars;
35 int nb_eqn1;
36 int nb_eqn2;
37
38 nb_vars = var_start[NB_PIECES];
39 nb_eqn1 = 5 * 5;
40 nb_eqn2 = 0;
41 nb_eqns = nb_eqn1 + nb_eqn2;
42
43 cout << "nb_vars=" << nb_vars << endl;
44 cout << "nb_eqn1=" << nb_eqn1 << endl;
45 cout << "nb_eqn2=" << nb_eqn2 << endl;
46 cout << "nb_eqns=" << nb_eqns << endl;
47
49
51
52 D->open(nb_eqns, nb_vars);
54
56
57
58 int f_write_tree = FALSE;
59 const char *fname_tree = "";
60
61 D->solve_all_DLX_with_RHS(f_write_tree, fname_tree, verbose_level);
62 cout << "After solve, we found " << D->_resultanz << " solutions" << endl;
63
64 long int *Sol;
65 int nb_sol, sol_length = 5;
66
67 D->get_solutions(Sol, nb_sol, verbose_level);
68
69
71 int l;
72
74 L->init_basic_constant_size(nb_vars,
75 nb_sol, sol_length, 0 /* verbose_level */);
76
77 for (l = 0; l < nb_sol; l++) {
78 Lint_vec_copy(Sol + l * sol_length, L->Sets[l], sol_length);
79 }
80
81 L->sort_all(0);
82
83 L->sort_big(0 /*verbose_level */);
84
85 {
86
87 string fname;
88
89 fname.assign("solutions.csv");
90
91 L->save_csv(fname, TRUE /* f_make_heading */, verbose_level);
92 }
93
94 cout << "Solution 8:" << endl;
95 decode_assembly(L->Sets[8]);
96 cout << endl;
97
98 cout << "Solution 10:" << endl;
99 decode_assembly(L->Sets[10]);
100 cout << endl;
101
102 cout << "Solution 90:" << endl;
103 decode_assembly(L->Sets[90]);
104 cout << endl;
105
106 cout << "Solution 94:" << endl;
107 decode_assembly(L->Sets[94]);
108 cout << endl;
109
110 cout << "Solution 163:" << endl;
111 decode_assembly(L->Sets[163]);
112 cout << endl;
113
114
115
116
117
118 {
119 const char *fname = "pentomino_all.tex";
120 ofstream fp(fname);
122
123 La.head_easy(fp);
124
125 fp << "\\noindent" << endl;
126 for (l = 0; l < nb_sol; l++) {
127
128
129 cout << "Solution " << l << " : ";
130 #if 1
131 Lint_vec_print(cout, L->Sets[l], sol_length);
132 cout << "\\\\" << endl;
133 #endif
134
135 draw_it(fp, L->Sets[l]);
136 cout << "\\\\" << endl;
137
138 #if 0
139 for (u = 0; u < sol_length; u++) {
140 j = Sol[l * sol_length + u];
141 decode_piece(j, h, r, t);
142 cout << "j=" << j << " h=" << h << " r=" << r << " t=" << t << endl;
143 }
144 #endif
145
146 }
147 La.foot(fp);
148 }
149
150 int i;
151 int nb_orbits;
152 int *orbit;
153 int *orbit_inv;
154 int *orbit_first;
155 int *orbit_len;
156
157 L->compute_orbits(nb_orbits, orbit, orbit_inv, orbit_first, orbit_len,
158 pentomino_puzzle_compute_image_function,
159 this /* void *compute_image_data */,
160 2 /* nb_gens */,
161 verbose_level + 2);
162
163 cout << "We found " << nb_orbits << " orbits \\\\" << endl;
164
165 int o, f, p;
166
167 {
168 const char *fname = "pentomino_orbits.tex";
169 ofstream fp(fname);
171
172 La.head_easy(fp);
173
174 fp << "\\noindent" << endl;
175 for (o = 0; o < nb_orbits; o++) {
176 f = orbit_first[o];
177 i = orbit[f];
178 #if 1
179 cout << "Representative of orbit " << o << " is solution " << i << " : ";
180 Lint_vec_print(cout, L->Sets[i], sol_length);
181 cout << "\\\\" << endl;
182 #endif
183
184 draw_it(fp, L->Sets[i]);
185 cout << "\\\\" << endl;
186
187 if (((o + 1) % 35) == 0) {
188 cout << endl << "\\clearpage" << endl << endl << "\\noindent" << endl;
189 }
190
191 }
192 La.foot(fp);
193 }
194
195 int nb_orbits_without_I;
196 int *orbits_without_I;
197
198 nb_orbits_without_I = 0;
199 orbits_without_I = NEW_int(nb_orbits);
200 for (o = 0; o < nb_orbits; o++) {
201 f = orbit_first[o];
202 i = orbit[f];
203 if (does_it_contain_an_I(L->Sets[i])) {
204 continue;
205 }
206 if (has_interlocking_Ls(L->Sets[i])) {
207 continue;
208 }
209 if (has_interlocking_Lprime(L->Sets[i])) {
210 continue;
211 }
212 if (has_interlocking_Ps(L->Sets[i])) {
213 continue;
214 }
215 if (has_interlocking_Pprime(L->Sets[i])) {
216 continue;
217 }
218 orbits_without_I[nb_orbits_without_I++] = o;
219 }
220
221 cout << "We found " << nb_orbits_without_I << " orbits without I and with no interlocking L's and P's\\\\" << endl;
222
223
224
225 {
226 const char *fname = "pentomino_orbits_reduced.tex";
227 ofstream fp(fname);
229
230
231 La.head_easy(fp);
232
233 fp << "\\noindent" << endl;
234 for (p = 0; p < nb_orbits_without_I; p++) {
235 o = orbits_without_I[p];
236 f = orbit_first[o];
237 i = orbit[f];
238
239#if 1
240 cout << p << " / " << nb_orbits_without_I << " Representative of orbit " << o << " is solution " << i << " : ";
241 Lint_vec_print(cout, L->Sets[i], sol_length);
242 cout << "\\\\" << endl;
243#endif
244
245 draw_it(fp, L->Sets[i]);
246 cout << "\\\\" << endl;
247
248 if (((o + 1) % 35) == 0) {
249 cout << endl << "\\clearpage" << endl << endl << "\\noindent" << endl;
250 }
251 }
252 La.foot(fp);
253 }
254
255#if 0
256
257 cout << "Orbits with interlocking Ps:\\\\" << endl;
258 int cnt = 0;
259 for (p = 0; p < nb_orbits_without_I; p++) {
260 o = orbits_without_I[p];
261 f = orbit_first[o];
262 i = orbit[f];
263
264 if (has_interlocking_Ps(L->Sets[i])) {
265 cout << "With interlocking P's, orbit " << o << " without I is solution " << i << " : ";
266 int_vec_print(cout, L->Sets[i], sol_length);
267 cout << "\\\\" << endl;
268
269 draw_it(L->Sets[i]);
270 cout << "\\\\" << endl;
271
272 cnt++;
273 }
274 }
275#endif
276 FREE_OBJECT(D);
277
278}
279
280
282{
283 int i, j, a;
284 int L[5];
285 int nb_L = 0;
286
287 for (i = 0; i < 5; i++) {
288 a = set[i];
289 if (a >= var_start[6] && a < var_start[6 + 1]) {
290 L[nb_L++] = a;
291 }
292 }
293 if (nb_L <= 1) {
294 return FALSE;
295 }
296 for (i = 0; i < nb_L; i++) {
297 for (j = i + 1; j < nb_L; j++) {
298 if (test_if_interlocking_Ps(L[i], L[j])) {
299 return TRUE;
300 }
301 }
302 }
303 return FALSE;
304}
305
307{
308 int i, j, a;
309 int L[5];
310 int nb_L = 0;
311
312 for (i = 0; i < 5; i++) {
313 a = set[i];
314 if (a >= var_start[15] && a < var_start[15 + 1]) {
315 L[nb_L++] = a;
316 }
317 }
318 if (nb_L <= 1) {
319 return FALSE;
320 }
321 for (i = 0; i < nb_L; i++) {
322 for (j = i + 1; j < nb_L; j++) {
323 if (test_if_interlocking_Ps(L[i], L[j])) {
324 return TRUE;
325 }
326 }
327 }
328 return FALSE;
329}
330
332{
333 int i, j, a;
334 int L[5];
335 int nb_L = 0;
336
337 for (i = 0; i < 5; i++) {
338 a = set[i];
339 if (a >= var_start[4] && a < var_start[4 + 1]) {
340 L[nb_L++] = a;
341 }
342 }
343 if (nb_L <= 1) {
344 return FALSE;
345 }
346 for (i = 0; i < nb_L; i++) {
347 for (j = i + 1; j < nb_L; j++) {
348 if (test_if_interlocking_Ls(L[i], L[j])) {
349 return TRUE;
350 }
351 }
352 }
353 return FALSE;
354}
355
357{
358 int i, j, a;
359 int L[5];
360 int nb_L = 0;
361
362 for (i = 0; i < 5; i++) {
363 a = set[i];
364 if (a >= var_start[13] && a < var_start[13 + 1]) {
365 L[nb_L++] = a;
366 }
367 }
368 if (nb_L <= 1) {
369 return FALSE;
370 }
371 for (i = 0; i < nb_L; i++) {
372 for (j = i + 1; j < nb_L; j++) {
373 if (test_if_interlocking_Ls(L[i], L[j])) {
374 return TRUE;
375 }
376 }
377 }
378 return FALSE;
379}
380
382{
383 int h1 = 0, r1 = 0, t1 = 0, tt1, x1, y1, rr1;
384 int h2 = 0, r2 = 0, t2 = 0, tt2, x2, y2, rr2;
385
386 decode_piece(a1, h1, r1, t1);
387 tt1 = T[h1][t1];
388 x1 = tt1 % 5;
389 y1 = tt1 / 5;
390 rr1 = R[h1][r1];
391 decode_piece(a2, h2, r2, t2);
392 tt2 = T[h2][t2];
393 x2 = tt2 % 5;
394 y2 = tt2 / 5;
395 rr2 = R[h2][r2];
396
397 if (((rr1 + 2) % 4) != rr2) {
398 return FALSE;
399 }
400 if (y1 != 0) {
401 return FALSE;
402 }
403 if (y2 != 0) {
404 return FALSE;
405 }
406 if (x1 + x2 != 3) {
407 return FALSE;
408 }
409 return TRUE;
410}
411
413{
414 int h1 = 0, r1 = 0, t1 = 0, tt1, x1, y1, rr1;
415 int h2 = 0, r2 = 0, t2 = 0, tt2, x2, y2, rr2;
416
417 decode_piece(a1, h1, r1, t1);
418 tt1 = T[h1][t1];
419 x1 = tt1 % 5;
420 y1 = tt1 / 5;
421 rr1 = R[h1][r1];
422 decode_piece(a2, h2, r2, t2);
423 tt2 = T[h2][t2];
424 x2 = tt2 % 5;
425 y2 = tt2 / 5;
426 rr2 = R[h2][r2];
427
428 if (((rr1 + 2) % 4) != rr2) {
429 return FALSE;
430 }
431 if (y1 != 1) {
432 return FALSE;
433 }
434 if (y2 != 1) {
435 return FALSE;
436 }
437 if (x1 + x2 != 3) {
438 return FALSE;
439 }
440 return TRUE;
441}
442
444{
445 int i, a, cnt = 0;
446
447 for (i = 0; i < 5; i++) {
448 a = set[i];
449 if (a >= var_start[t] && a < var_start[t + 1]) {
450 cnt++;
451 }
452 }
453 return cnt;
454}
455
457{
458 int i, a;
459
460 for (i = 0; i < 5; i++) {
461 a = set[i];
462 if (a >= var_start[3] && a < var_start[4]) {
463 return TRUE;
464 }
465 }
466 return FALSE;
467}
468
470// input set[5]
471{
472 int i, h = 0, r = 0, t = 0, tt, x, y, rr;
473
474 cout << "Set ";
475 Lint_vec_print(cout, set, 5);
476 cout << endl;
477
478 for (i = 0; i < 5; i++) {
479 decode_piece(set[i], h, r, t);
480 tt = T[h][t];
481 x = tt % 5;
482 y = tt / 5;
483 rr = R[h][r];
484 cout << "h=" << h << " r=" << r << " t=" << t
485 << " tt=" << tt
486 << " x=" << x << " y=" << y << " rr=" << rr << endl;
487 }
488}
489
490void pentomino_puzzle::decode_piece(int j, int &h, int &r, int &t)
491// h is the kind of piece
492// r is the rotation index
493// t is the translation index
494// to get the actual rotation rr and translation tt, use
495// rr = R[h][r] and tt = T[h][t].
496// To get the x and y shift from tt, use:
497// x = tt % 5;
498// y = tt / 5;
499
500{
501 int j0;
502
503 for (h = 0; h < NB_PIECES; h++) {
504 j0 = var_start[h + 1];
505 if (j0 > j) {
506 j -= var_start[h];
507 t = j % T_length[h];
508 j -= t;
509 r = j / T_length[h];
510 break;
511 }
512 }
513}
514
515int pentomino_puzzle::code_piece(int h, int r, int t)
516{
517 int j;
518
519 j = var_start[h] + r * T_length[h] + t;
520 return j;
521}
522
523
524void pentomino_puzzle::draw_it(ostream &ost, long int *sol)
525{
526 int sol_length = 5;
527 int u, h = 0, r = 0, rr, t = 0, tt, tx, ty, s, a, b, x, y, j;
528 int *O1;
529
530 ost << "\\begin{tikzpicture}[x=1cm, y=1cm, semitransparent, scale=0.5]" << endl;
531 ost << "\\draw[step=1cm, line width=0.3mm, black!30!white] (0,0) grid (5cm,5cm);" << endl;
532 for (u = 0; u < sol_length; u++) {
533 j = sol[u];
534 decode_piece(j, h, r, t);
535 //cout << "% j=" << j << " h=" << h << " r=" << r << " t=" << t << endl;
536 tt = T[h][t];
537 tx = tt % 5;
538 ty = tt / 5;
539 rr = R[h][r];
540
541 O1 = NEW_int(O_length[h]);
542 for (s = 0; s < O_length[h]; s++) {
543 a = O[h][s];
544 a += tx;
545 a += 6 * ty;
546 b = Rotate6[rr * 36 + a];
547 O1[s] = b;
548 }
549 ost << "\\draw [very thick] ";
550 for (s = 0; s < O_length[h]; s++) {
551 a = O1[s];
552 x = a % 6;
553 y = 5 - a / 6;
554 ost << "(" << x << "," << y << ")";
555 if (s < O_length[h] - 1) {
556 ost << " -- ";
557 }
558 }
559 ost << ";" << endl;
560 FREE_int(O1);
561 }
562 ost << "\\end{tikzpicture}" << endl;
563}
564
566 int elt_idx,
567 int gen_idx, int &idx_of_image, int verbose_level)
568// implements a rotation by 90 degree:
569{
570 //int verbose_level = 0;
571 int f_v = (verbose_level >= 1);
572 int f_vv = (verbose_level >= 2);
573 long int *set1;
574 long int *set2;
575 int sz, i, a, b, h, r, t, idx;
577
578 set1 = S->Sets[elt_idx];
579 sz = S->Set_size[elt_idx];
580 set2 = NEW_lint(sz);
581
582
583 if (f_v) {
584 cout << "compute_image_function "
585 "computing image of solution " << elt_idx << " = ";
586 Lint_vec_print(cout, set1, sz);
587 cout << " under generator " << gen_idx << endl;
588 }
589
590 for (i = 0; i < sz; i++) {
591 a = set1[i];
592 decode_piece(a, h, r, t);
593 if (f_vv) {
594 cout << "a=" << a << " h=" << h << " r=" << r << " t=" << t << " -> ";
595 }
596 if (gen_idx == 0) {
597 turn_piece(h, r, t, verbose_level - 1);
598 }
599 else if (gen_idx == 1) {
600 flip_piece(h, r, t, verbose_level - 1);
601 }
602 else {
603 cout << "compute_image_function gen_idx unrecognized" << endl;
604 exit(1);
605 }
606 b = code_piece(h, r, t);
607 if (f_vv) {
608 cout << "b=" << b << " h=" << h
609 << " r=" << r << " t=" << t << endl;
610 }
611 set2[i] = b;
612 }
613 Sorting.lint_vec_heapsort(set2, sz);
614 if (!Sorting.vec_search_general(S,
615 pentomino_puzzle_compare_func,
616 this /* void *data_for_compare */,
617 S->nb_sets, set2, idx, 0 /*verbose_level*/)) {
618 cout << "compute_image_function cannot find image" << endl;
619 Lint_vec_print(cout, set2, sz);
620 cout << endl;
621 exit(1);
622 }
623 idx_of_image = idx;
624 if (f_v) {
625 cout << "compute_image_function image is ";
626 Lint_vec_print(cout, set2, sz);
627 cout << " which is solution " << idx_of_image << endl;
628 }
629 FREE_lint(set2);
630
631}
632
633void pentomino_puzzle::turn_piece(int &h, int &r, int &t, int verbose_level)
634{
635 int tx, ty, txx = 0, tyy = 0, tt;
637
638 tt = T[h][t];
639 tx = tt % 5;
640 ty = tt / 5;
641 txx = tx;
642 tyy = ty;
643 if (h == 0) { // X
644 txx = 2 - ty;
645 tyy = tx;
646 }
647 else if (h == 3 && r == 1) { // I
648 txx = 4 - tx;
649 tyy = ty;
650 }
651 else if (h == 12 && r == 1) { // Z
652 txx = 2 - tx;
653 tyy = 2 - ty;
654 }
655 else if (h == 17 && r == 1) { // Z'
656 txx = 2 - tx;
657 tyy = 2 - ty;
658 }
659 r++;
660 r %= R_length[h];
661 tt = tyy * 5 + txx;
662 if (!Sorting.int_vec_search_linear(T[h], T_length[h], tt, t)) {
663 cout << "turn_piece cannot find "
664 "tt=" << tt << " for h=" << h << endl;
665 exit(1);
666 }
667}
668
669void pentomino_puzzle::flip_piece(int &h, int &r, int &t, int verbose_level)
670{
671 //int verbose_level = 0;
672 int f_v = (verbose_level >= 1);
673 int tx, ty, txx = 0, tyy = 0, tt;
675
676 if (f_v) {
677 cout << "flip_piece" << endl;
678 }
679 tt = T[h][t];
680 tx = tt % 5;
681 ty = tt / 5;
682 txx = tx;
683 tyy = ty;
684 if (f_v) {
685 cout << "r=" << r << " tt=" << tt << " x=" << tx << " y=" << ty << endl;
686 }
687 if (h == 0) { // X
688 txx = 2 - tx;
689 tyy = ty;
690 }
691 else if (h == 3 && r == 0) { // I
692 txx = 4 - tx;
693 tyy = ty;
694 }
695 else if (h == 7 || h == 8) { // T or U
696 if (r == 1) {
697 r = 3;
698 }
699 else if (r == 3) {
700 r = 1;
701 }
702 txx = 2 - tx;
703 tyy = ty;
704 }
705 else if (h == 9 || h == 10) { // V or W
706 if (r == 0) {
707 r = 3;
708 }
709 else if (r == 1) {
710 r = 2;
711 }
712 else if (r == 2) {
713 r = 1;
714 }
715 else if (r == 3) {
716 r = 0;
717 }
718 txx = 2 - ty;
719 tyy = 2 - tx;
720 }
721 else if (h == 12 || h == 17) { // Z (12) or Z' (17)
722 if (h == 12) {
723 h = 17;
724 }
725 else {
726 h = 12;
727 }
728 if (r == 1) {
729 txx = tx;
730 tyy = 2 - ty;
731 }
732 else {
733 txx = 2 - tx;
734 tyy = ty;
735 }
736 }
737 else if (h == 11 || h == 16) { // Y (11) or Y' (16)
738 if (h == 11) {
739 h = 16;
740 }
741 else {
742 h = 11;
743 }
744 if (r == 1) {
745 r = 3;
746 }
747 else if (r == 3) {
748 r = 1;
749 }
750 txx = 3 - tx;
751 tyy = ty;
752 }
753 else if (h == 4 || h == 13) { // L (4) or L' (13)
754 if (h == 4) {
755 h = 13;
756 }
757 else {
758 h = 4;
759 }
760 if (r == 1) {
761 r = 3;
762 }
763 else if (r == 3) {
764 r = 1;
765 }
766 txx = 3 - tx;
767 tyy = ty;
768 }
769 else if (h == 5 || h == 14) { // N (5) or N' (14)
770 if (h == 5) {
771 h = 14;
772 }
773 else {
774 h = 5;
775 }
776 if (r == 1) {
777 r = 3;
778 }
779 else if (r == 3) {
780 r = 1;
781 }
782 txx = 3 - tx;
783 tyy = ty;
784 }
785 else if (h == 6 || h == 15) { // P (6) or P' (15)
786 if (h == 6) {
787 h = 15;
788 }
789 else {
790 h = 6;
791 }
792 if (r == 1) {
793 r = 3;
794 }
795 else if (r == 3) {
796 r = 1;
797 }
798 txx = 3 - tx;
799 tyy = ty;
800 }
801 else if (h == 1 || h == 2) { // F (1) or F' (2)
802 if (h == 1) {
803 h = 2;
804 }
805 else {
806 h = 1;
807 }
808 if (r == 1) {
809 r = 3;
810 }
811 else if (r == 3) {
812 r = 1;
813 }
814 txx = 2 - tx;
815 tyy = ty;
816 }
817 tt = tyy * 5 + txx;
818 if (f_v) {
819 cout << "r=" << r << " x'=" << txx << " y'=" << tyy << " tt=" << tt << endl;
820 }
821 if (!Sorting.int_vec_search_linear(T[h], T_length[h], tt, t)) {
822 cout << "flip_piece cannot find tt=" << tt << " for h=" << h << endl;
823 exit(1);
824 }
825 if (f_v) {
826 cout << "h'=" << h << " r'=" << r << " t'=" << t << endl;
827 }
828 if (f_v) {
829 cout << "flip_piece done" << endl;
830 }
831}
832
833
835{
836 // pieces on a 5 x 5 grid:
837 int S1[] = {1,5,6,7,11,-1}; // X, Plus
838 int S2[] = {1,2,5,6,11,-1}; // F
839 int S3[] = {0,1,6,7,11,-1}; // F'
840 int S4[] = {0,5,10,15,20,-1}; // I
841 int S5[] = {0,5,10,15,16,-1}; // L
842 int S6[] = {1,6,10,11,15,-1}; // N
843 int S7[] = {0,1,5,6,10,-1}; // P
844 int S8[] = {0,1,2,6,11,-1}; // T
845 int S9[] = {0,2,5,6,7,-1}; // U
846 int S10[] = {0,5,10,11,12,-1}; // V
847 int S11[] = {0,5,6,11,12,-1}; // W
848 int S12[] = {1,5,6,11,16,-1}; // Y
849 int S13[] = {0,1,6,11,12,-1}; // Z
850 int S14[] = {1,6,11,15,16,-1}; // L'
851 int S15[] = {0,5,10,11,16,-1}; // N'
852 int S16[] = {0,1,5,6,11,-1}; // P'
853 int S17[] = {0,5,6,10,15,-1}; // Y'
854 int S18[] = {1,2,6,10,11,-1}; // Z'
855
856 //outline on a 6 x 6 grid:
857 int O1[] = {1,2,8,9,15,14,20,19,13,12,6,7,1,-1}; // X, Plus
858 int O2[] = {1,3,9,8,20,19,13,12,6,7,1,-1}; // F
859 int O3[] = {0,2,8,9,15,14,20,19,7,6,0,-1}; // F'
860 int O4[] = {0,1,31,30,0,-1}; // I
861 int O5[] = {0,1,19,20,26,24,0,-1}; // L
862 int O6[] = {1,2,20,19,25,24,12,13,1,-1}; // N
863 int O7[] = {0,2,14,13,19,18,0,-1}; // P
864 int O8[] = {0,3,9,8,20,19,7,6,0,-1}; // T
865 int O9[] = {0,1,7,8,2,3,15,12,0,-1}; // U
866 int O10[] = {0,1,13,15,21,18,0,-1}; // V
867 int O11[] = {0,1,7,8,14,15,21,19,13,12,0,-1}; // W
868 int O12[] = {1,2,26,25,13,12,6,7,1,-1}; // Y
869 int O13[] = {0,2,14,15,21,19,7,6,0,-1}; // Z
870 int O14[] = {1,2,26,24,18,19,1,-1}; // L'
871 int O15[] = {0,1,13,14,26,25,19,18,0,-1}; // N'
872 int O16[] = {0,2,20,19,13,12,0,-1}; // P'
873 int O17[] = {0,1,7,8,14,13,25,24,0,-1}; // Y'
874 int O18[] = {1,3,9,8,20,18,12,13,1,-1}; // Z'
875
876
877 // translations:
878 int T1[] = {0,1,2,5,6,7,10,11,12,-1}; // X, Plus
879 int T2[] = {0,1,2,5,6,7,10,11,12,-1}; // F
880 int T3[] = {0,1,2,5,6,7,10,11,12,-1}; // F'
881 int T4[] = {0,1,2,3,4,-1}; // I
882 int T5[] = {0,1,2,3,5,6,7,8,-1}; // L
883 int T6[] = {0,1,2,3,5,6,7,8,-1}; // N
884 int T7[] = {0,1,2,3,5,6,7,8,10,11,12,13,-1}; // P
885 int T8[] = {0,1,2,5,6,7,10,11,12,-1}; // T
886 int T9[] = {0,1,2,5,6,7,10,11,12,15,16,17,-1}; // U
887 int T10[] = {0,1,2,5,6,7,10,11,12,-1}; // V
888 int T11[] = {0,1,2,5,6,7,10,11,12,-1}; // W
889 int T12[] = {0,1,2,3,5,6,7,8,-1}; // Y
890 int T13[] = {0,1,2,5,6,7,10,11,12,-1}; // Z
891 int T14[] = {0,1,2,3,5,6,7,8,-1}; // L'
892 int T15[] = {0,1,2,3,5,6,7,8,-1}; // N'
893 int T16[] = {0,1,2,3,5,6,7,8,10,11,12,13,-1}; // P'
894 int T17[] = {0,1,2,3,5,6,7,8,-1}; // Y'
895 int T18[] = {0,1,2,5,6,7,10,11,12,-1}; // Z'
896
897 //rotations:
898 int R1[] = {0,-1}; // X, Plus
899 int R2[] = {0,1,2,3,-1}; // F
900 int R3[] = {0,1,2,3,-1}; // F'
901 int R4[] = {0,1,-1}; // I
902 int R5[] = {0,1,2,3,-1}; // L
903 int R6[] = {0,1,2,3,-1}; // N
904 int R7[] = {0,1,2,3,-1}; // P
905 int R8[] = {0,1,2,3,-1}; // T
906 int R9[] = {0,1,2,3,-1}; // U
907 int R10[] = {0,1,2,3,-1}; // V
908 int R11[] = {0,1,2,3,-1}; // W
909 int R12[] = {0,1,2,3,-1}; // Y
910 int R13[] = {0,1,-1}; // Z
911 int R14[] = {0,1,2,3,-1}; // L
912 int R15[] = {0,1,2,3,-1}; // N'
913 int R16[] = {0,1,2,3,-1}; // P'
914 int R17[] = {0,1,2,3,-1}; // Y'
915 int R18[] = {0,1,-1}; // Z'
916
917
918 int i, j;
919
920 S[0] = S1;
921 S[1] = S2;
922 S[2] = S3;
923 S[3] = S4;
924 S[4] = S5;
925 S[5] = S6;
926 S[6] = S7;
927 S[7] = S8;
928 S[8] = S9;
929 S[9] = S10;
930 S[10] = S11;
931 S[11] = S12;
932 S[12] = S13;
933 S[13] = S14;
934 S[14] = S15;
935 S[15] = S16;
936 S[16] = S17;
937 S[17] = S18;
938
939 O[0] = O1;
940 O[1] = O2;
941 O[2] = O3;
942 O[3] = O4;
943 O[4] = O5;
944 O[5] = O6;
945 O[6] = O7;
946 O[7] = O8;
947 O[8] = O9;
948 O[9] = O10;
949 O[10] = O11;
950 O[11] = O12;
951 O[12] = O13;
952 O[13] = O14;
953 O[14] = O15;
954 O[15] = O16;
955 O[16] = O17;
956 O[17] = O18;
957
958 T[0] = T1;
959 T[1] = T2;
960 T[2] = T3;
961 T[3] = T4;
962 T[4] = T5;
963 T[5] = T6;
964 T[6] = T7;
965 T[7] = T8;
966 T[8] = T9;
967 T[9] = T10;
968 T[10] = T11;
969 T[11] = T12;
970 T[12] = T13;
971 T[13] = T14;
972 T[14] = T15;
973 T[15] = T16;
974 T[16] = T17;
975 T[17] = T18;
976
977 R[0] = R1;
978 R[1] = R2;
979 R[2] = R3;
980 R[3] = R4;
981 R[4] = R5;
982 R[5] = R6;
983 R[6] = R7;
984 R[7] = R8;
985 R[8] = R9;
986 R[9] = R10;
987 R[10] = R11;
988 R[11] = R12;
989 R[12] = R13;
990 R[13] = R14;
991 R[14] = R15;
992 R[15] = R16;
993 R[16] = R17;
994 R[17] = R18;
995
996 for (i = 0; i < NB_PIECES; i++) {
997 for (j = 0; ; j++) {
998 if (S[i][j] == -1) {
999 S_length[i] = j;
1000 break;
1001 }
1002 }
1003 for (j = 0; ; j++) {
1004 if (O[i][j] == -1) {
1005 O_length[i] = j;
1006 break;
1007 }
1008 }
1009 for (j = 0; ; j++) {
1010 if (T[i][j] == -1) {
1011 T_length[i] = j;
1012 break;
1013 }
1014 }
1015 for (j = 0; ; j++) {
1016 if (R[i][j] == -1) {
1017 R_length[i] = j;
1018 break;
1019 }
1020 }
1021 }
1022}
1023
1025{
1026 int i, j, ii, jj, h;
1027
1028 for (i = 0; i < 5; i++) {
1029 for (j = 0; j < 5; j++) {
1030 Rotate[0 * 25 + i * 5 + j] = i * 5 + j;
1031 }
1032 }
1033 for (i = 0; i < 5; i++) {
1034 jj = 4 - i;
1035 for (j = 0; j < 5; j++) {
1036 ii = j;
1037 Rotate[1 * 25 + i * 5 + j] = ii * 5 + jj;
1038 }
1039 }
1040 for (i = 0; i < 25; i++) {
1041 Rotate[2 * 25 + i] = Rotate[1 * 25 + Rotate[1 * 25 + i]];
1042 }
1043 for (i = 0; i < 25; i++) {
1044 Rotate[3 * 25 + i] = Rotate[2 * 25 + Rotate[1 * 25 + i]];
1045 }
1046
1047 cout << "Rotate:" << endl;
1048 for (h = 0; h < 4; h++) {
1049 for (j = 0; j < 25; j++) {
1050 cout << setw(3) << Rotate[h * 25 + j] << " ";
1051 }
1052 cout << endl;
1053 }
1054
1055
1056 for (i = 0; i < 6; i++) {
1057 for (j = 0; j < 6; j++) {
1058 Rotate6[0 * 36 + i * 6 + j] = i * 6 + j;
1059 }
1060 }
1061 for (i = 0; i < 6; i++) {
1062 jj = 5 - i;
1063 for (j = 0; j < 6; j++) {
1064 ii = j;
1065 Rotate6[1 * 36 + i * 6 + j] = ii * 6 + jj;
1066 }
1067 }
1068 for (i = 0; i < 36; i++) {
1069 Rotate6[2 * 36 + i] = Rotate6[1 * 36 + Rotate6[1 * 36 + i]];
1070 }
1071 for (i = 0; i < 36; i++) {
1072 Rotate6[3 * 36 + i] = Rotate6[2 * 36 + Rotate6[1 * 36 + i]];
1073 }
1074
1075 cout << "Rotate6:" << endl;
1076 for (h = 0; h < 4; h++) {
1077 for (j = 0; j < 36; j++) {
1078 cout << setw(3) << Rotate6[h * 36 + j] << " ";
1079 }
1080 cout << endl;
1081 }
1082
1083
1084}
1085
1087{
1088 int h;
1089
1090 var_start[0] = 0;
1091 for (h = 0; h < NB_PIECES; h++) {
1092 var_length[h] = R_length[h] * T_length[h];
1093 var_start[h + 1] = var_start[h] + var_length[h];
1094 }
1095 cout << "i : var_start[i] : var_length[i]" << endl;
1096 for (h = 0; h < NB_PIECES; h++) {
1097 cout << h << " : " << var_start[h] << " : " << var_length[h] << endl;
1098 }
1099}
1100
1101
1103{
1104 int i, h, j0, r, t, rr, tt, s, x, y, z;
1105
1106 for (h = 0; h < NB_PIECES; h++) {
1107 j0 = var_start[h];
1108
1109 //cout << "h=" << h << "/" << NB_PIECES << " j0=" << j0 << ":" << endl;
1110 for (r = 0; r < R_length[h]; r++) {
1111 rr = R[h][r];
1112 //cout << "h=" << h << "/" << NB_PIECES << " r=" << r << "/" << R_length[h] << " rr=" << rr << ":" << endl;
1113 for (t = 0; t < T_length[h]; t++) {
1114 tt = T[h][t];
1115 //cout << "h=" << h << "/" << NB_PIECES << " r=" << r << "/" << R_length[h] << " rr=" << rr << " t=" << t << "/" << T_length[h] << " tt=" << tt << ":" << endl;
1116 for (s = 0; s < S_length[h]; s++) {
1117 x = S[h][s];
1118 y = x + tt;
1119 z = Rotate[rr * 25 + y];
1120
1121 //cout << "h=" << h << "/" << 6 << " r=" << r << "/" << R_length[h] << " rr=" << rr << " t=" << t << "/" << T_length[h] << " tt=" << tt << " s=" << s << "/" << S_length[h] << " x=" << x << " y=" << y << " z=" << z << " entry=(" << z << "," << j0 + r * T_length[h] + t << ")" << endl;
1122 D->Aij(z, j0 + r * T_length[h] + t) = 1;
1123 //M[z * nb_vars + j0 + r * T_length[h] + t] = 1;
1124 }
1125 }
1126 }
1127 }
1128
1129#if 0
1130 // make the bottom rows to ensure that each piece is chosen exactly once:
1131 for (h = 0; h < 6; h++) {
1132 j0 = var_start[h];
1133
1134 for (r = 0; r < R_length[h]; r++) {
1135 for (t = 0; t < T_length[h]; t++) {
1136 D->Aij(nb_eqn1 + h, j0 + r * T_length[h] + t) = 1;
1137 //M[(nb_eqn1 + h) * nb_vars + j0 + r * T_length[h] + t] = 1;
1138 }
1139 }
1140 }
1141#endif
1142
1143 for (i = 0; i < D->m; i++) {
1144 D->RHS[i] = 1;
1145 }
1146 D->f_has_sum = TRUE;
1147 D->sum = 5;
1148}
1149
1150
1151static void pentomino_puzzle_compute_image_function(data_structures::set_of_sets *S,
1152 void *compute_image_data, int elt_idx,
1153 int gen_idx, int &idx_of_image, int verbose_level)
1154{
1155 pentomino_puzzle *PP = (pentomino_puzzle *) compute_image_data;
1156
1157 PP->compute_image_function(S, elt_idx,
1158 gen_idx, idx_of_image, verbose_level);
1159}
1160
1161static int pentomino_puzzle_compare_func(void *vec, void *a, int b, void *data_for_compare)
1162{
1163 //pentomino_puzzle *PP = (pentomino_puzzle *) data_for_compare;
1165 int sz, c;
1167
1168 sz = S->Set_size[b];
1169 c = Sorting.lint_vec_compare((long int *) a, S->Sets[b], sz);
1170#if 0
1171 cout << "compare ";
1172 int_vec_print(cout, (int *) a, sz);
1173 cout << " : ";
1174 int_vec_print(cout, S->Sets[b], sz);
1175 cout << " yields " << c << endl;
1176#endif
1177 return -c;
1178}
1179
1180
1181}}}
1182
1183
generate all solutions of the pentomino puzzle
void compute_image_function(data_structures::set_of_sets *S, int elt_idx, int gen_idx, int &idx_of_image, int verbose_level)
void turn_piece(int &h, int &r, int &t, int verbose_level)
void flip_piece(int &h, int &r, int &t, int verbose_level)
void compute_orbits(int &nb_orbits, int *&orbit, int *&orbit_inv, int *&orbit_first, int *&orbit_len, void(*compute_image_function)(set_of_sets *S, void *compute_image_data, int elt_idx, int gen_idx, int &idx_of_image, int verbose_level), void *compute_image_data, int nb_gens, int verbose_level)
void init_basic_constant_size(int underlying_set_size, int nb_sets, int constant_size, int verbose_level)
void save_csv(std::string &fname, int f_make_heading, int verbose_level)
a collection of functions related to sorted vectors
int vec_search_general(void *vec, int(*compare_func)(void *vec, void *a, int b, void *data_for_compare), void *data_for_compare, int len, void *a, int &idx, int verbose_level)
Definition: sorting.cpp:1005
int lint_vec_compare(long int *p, long int *q, int len)
Definition: sorting.cpp:2326
int int_vec_search_linear(int *v, int len, int a, int &idx)
Definition: sorting.cpp:686
diophantine systems of equations (i.e., linear systems over the integers)
Definition: solvers.h:209
void get_solutions(long int *&Sol, int &nb_sol, int verbose_level)
Definition: diophant.cpp:1062
int solve_all_DLX_with_RHS(int f_write_tree, const char *fname_tree, int verbose_level)
Definition: diophant.cpp:1279
#define NB_PIECES
#define Lint_vec_copy(A, B, C)
Definition: foundations.h:694
#define FREE_int(p)
Definition: foundations.h:640
#define NEW_OBJECT(type)
Definition: foundations.h:638
#define Lint_vec_print(A, B, C)
Definition: foundations.h:686
#define FREE_OBJECT(p)
Definition: foundations.h:651
#define NEW_int(n)
Definition: foundations.h:625
#define TRUE
Definition: foundations.h:231
#define FALSE
Definition: foundations.h:234
#define FREE_lint(p)
Definition: foundations.h:642
#define NEW_lint(n)
Definition: foundations.h:628
the orbiter library for the classification of combinatorial objects