diff options
Diffstat (limited to 'apps/plugins/puzzles/src/divvy.c')
-rw-r--r-- | apps/plugins/puzzles/src/divvy.c | 141 |
1 files changed, 13 insertions, 128 deletions
diff --git a/apps/plugins/puzzles/src/divvy.c b/apps/plugins/puzzles/src/divvy.c index ea018010cf..61b04eb80d 100644 --- a/apps/plugins/puzzles/src/divvy.c +++ b/apps/plugins/puzzles/src/divvy.c | |||
@@ -260,9 +260,10 @@ static bool addremcommon(int w, int h, int x, int y, int *own, int val) | |||
260 | * In both of the above suggested use cases, the user would | 260 | * In both of the above suggested use cases, the user would |
261 | * probably want w==h==k, but that isn't a requirement. | 261 | * probably want w==h==k, but that isn't a requirement. |
262 | */ | 262 | */ |
263 | static int *divvy_internal(int w, int h, int k, random_state *rs) | 263 | DSF *divvy_rectangle_attempt(int w, int h, int k, random_state *rs) |
264 | { | 264 | { |
265 | int *order, *queue, *tmp, *own, *sizes, *addable, *retdsf; | 265 | int *order, *queue, *tmp, *own, *sizes, *addable; |
266 | DSF *retdsf, *tmpdsf; | ||
266 | bool *removable; | 267 | bool *removable; |
267 | int wh = w*h; | 268 | int wh = w*h; |
268 | int i, j, n, x, y, qhead, qtail; | 269 | int i, j, n, x, y, qhead, qtail; |
@@ -277,6 +278,7 @@ static int *divvy_internal(int w, int h, int k, random_state *rs) | |||
277 | queue = snewn(n, int); | 278 | queue = snewn(n, int); |
278 | addable = snewn(wh*4, int); | 279 | addable = snewn(wh*4, int); |
279 | removable = snewn(wh, bool); | 280 | removable = snewn(wh, bool); |
281 | retdsf = tmpdsf = NULL; | ||
280 | 282 | ||
281 | /* | 283 | /* |
282 | * Permute the grid squares into a random order, which will be | 284 | * Permute the grid squares into a random order, which will be |
@@ -609,7 +611,7 @@ static int *divvy_internal(int w, int h, int k, random_state *rs) | |||
609 | assert(own[i] >= 0 && own[i] < n); | 611 | assert(own[i] >= 0 && own[i] < n); |
610 | tmp[own[i]] = i; | 612 | tmp[own[i]] = i; |
611 | } | 613 | } |
612 | retdsf = snew_dsf(wh); | 614 | retdsf = dsf_new(wh); |
613 | for (i = 0; i < wh; i++) { | 615 | for (i = 0; i < wh; i++) { |
614 | dsf_merge(retdsf, i, tmp[own[i]]); | 616 | dsf_merge(retdsf, i, tmp[own[i]]); |
615 | } | 617 | } |
@@ -619,18 +621,18 @@ static int *divvy_internal(int w, int h, int k, random_state *rs) | |||
619 | * the ominoes really are k-ominoes and we haven't | 621 | * the ominoes really are k-ominoes and we haven't |
620 | * accidentally split one into two disconnected pieces. | 622 | * accidentally split one into two disconnected pieces. |
621 | */ | 623 | */ |
622 | dsf_init(tmp, wh); | 624 | tmpdsf = dsf_new(wh); |
623 | for (y = 0; y < h; y++) | 625 | for (y = 0; y < h; y++) |
624 | for (x = 0; x+1 < w; x++) | 626 | for (x = 0; x+1 < w; x++) |
625 | if (own[y*w+x] == own[y*w+(x+1)]) | 627 | if (own[y*w+x] == own[y*w+(x+1)]) |
626 | dsf_merge(tmp, y*w+x, y*w+(x+1)); | 628 | dsf_merge(tmpdsf, y*w+x, y*w+(x+1)); |
627 | for (x = 0; x < w; x++) | 629 | for (x = 0; x < w; x++) |
628 | for (y = 0; y+1 < h; y++) | 630 | for (y = 0; y+1 < h; y++) |
629 | if (own[y*w+x] == own[(y+1)*w+x]) | 631 | if (own[y*w+x] == own[(y+1)*w+x]) |
630 | dsf_merge(tmp, y*w+x, (y+1)*w+x); | 632 | dsf_merge(tmpdsf, y*w+x, (y+1)*w+x); |
631 | for (i = 0; i < wh; i++) { | 633 | for (i = 0; i < wh; i++) { |
632 | j = dsf_canonify(retdsf, i); | 634 | j = dsf_canonify(retdsf, i); |
633 | assert(dsf_canonify(tmp, j) == dsf_canonify(tmp, i)); | 635 | assert(dsf_equivalent(tmpdsf, j, i)); |
634 | } | 636 | } |
635 | 637 | ||
636 | cleanup: | 638 | cleanup: |
@@ -640,6 +642,7 @@ static int *divvy_internal(int w, int h, int k, random_state *rs) | |||
640 | */ | 642 | */ |
641 | sfree(order); | 643 | sfree(order); |
642 | sfree(tmp); | 644 | sfree(tmp); |
645 | dsf_free(tmpdsf); | ||
643 | sfree(own); | 646 | sfree(own); |
644 | sfree(sizes); | 647 | sfree(sizes); |
645 | sfree(queue); | 648 | sfree(queue); |
@@ -652,131 +655,13 @@ static int *divvy_internal(int w, int h, int k, random_state *rs) | |||
652 | return retdsf; | 655 | return retdsf; |
653 | } | 656 | } |
654 | 657 | ||
655 | #ifdef TESTMODE | 658 | DSF *divvy_rectangle(int w, int h, int k, random_state *rs) |
656 | static int fail_counter = 0; | ||
657 | #endif | ||
658 | |||
659 | int *divvy_rectangle(int w, int h, int k, random_state *rs) | ||
660 | { | 659 | { |
661 | int *ret; | 660 | DSF *ret; |
662 | 661 | ||
663 | do { | 662 | do { |
664 | ret = divvy_internal(w, h, k, rs); | 663 | ret = divvy_rectangle_attempt(w, h, k, rs); |
665 | |||
666 | #ifdef TESTMODE | ||
667 | if (!ret) | ||
668 | fail_counter++; | ||
669 | #endif | ||
670 | |||
671 | } while (!ret); | 664 | } while (!ret); |
672 | 665 | ||
673 | return ret; | 666 | return ret; |
674 | } | 667 | } |
675 | |||
676 | #ifdef TESTMODE | ||
677 | |||
678 | /* | ||
679 | * gcc -g -O0 -DTESTMODE -I.. -o divvy divvy.c ../random.c ../malloc.c ../dsf.c ../misc.c ../nullfe.c | ||
680 | * | ||
681 | * or to debug | ||
682 | * | ||
683 | * gcc -g -O0 -DDIVVY_DIAGNOSTICS -DTESTMODE -I.. -o divvy divvy.c ../random.c ../malloc.c ../dsf.c ../misc.c ../nullfe.c | ||
684 | */ | ||
685 | |||
686 | int main(int argc, char **argv) | ||
687 | { | ||
688 | int *dsf; | ||
689 | int i; | ||
690 | int w = 9, h = 4, k = 6, tries = 100; | ||
691 | random_state *rs; | ||
692 | |||
693 | rs = random_new("123456", 6); | ||
694 | |||
695 | if (argc > 1) | ||
696 | w = atoi(argv[1]); | ||
697 | if (argc > 2) | ||
698 | h = atoi(argv[2]); | ||
699 | if (argc > 3) | ||
700 | k = atoi(argv[3]); | ||
701 | if (argc > 4) | ||
702 | tries = atoi(argv[4]); | ||
703 | |||
704 | for (i = 0; i < tries; i++) { | ||
705 | int x, y; | ||
706 | |||
707 | dsf = divvy_rectangle(w, h, k, rs); | ||
708 | assert(dsf); | ||
709 | |||
710 | for (y = 0; y <= 2*h; y++) { | ||
711 | for (x = 0; x <= 2*w; x++) { | ||
712 | int miny = y/2 - 1, maxy = y/2; | ||
713 | int minx = x/2 - 1, maxx = x/2; | ||
714 | int classes[4], tx, ty; | ||
715 | for (ty = 0; ty < 2; ty++) | ||
716 | for (tx = 0; tx < 2; tx++) { | ||
717 | int cx = minx+tx, cy = miny+ty; | ||
718 | if (cx < 0 || cx >= w || cy < 0 || cy >= h) | ||
719 | classes[ty*2+tx] = -1; | ||
720 | else | ||
721 | classes[ty*2+tx] = dsf_canonify(dsf, cy*w+cx); | ||
722 | } | ||
723 | switch (y%2 * 2 + x%2) { | ||
724 | case 0: /* corner */ | ||
725 | /* | ||
726 | * Cases for the corner: | ||
727 | * | ||
728 | * - if all four surrounding squares belong | ||
729 | * to the same omino, we print a space. | ||
730 | * | ||
731 | * - if the top two are the same and the | ||
732 | * bottom two are the same, we print a | ||
733 | * horizontal line. | ||
734 | * | ||
735 | * - if the left two are the same and the | ||
736 | * right two are the same, we print a | ||
737 | * vertical line. | ||
738 | * | ||
739 | * - otherwise, we print a cross. | ||
740 | */ | ||
741 | if (classes[0] == classes[1] && | ||
742 | classes[1] == classes[2] && | ||
743 | classes[2] == classes[3]) | ||
744 | printf(" "); | ||
745 | else if (classes[0] == classes[1] && | ||
746 | classes[2] == classes[3]) | ||
747 | printf("-"); | ||
748 | else if (classes[0] == classes[2] && | ||
749 | classes[1] == classes[3]) | ||
750 | printf("|"); | ||
751 | else | ||
752 | printf("+"); | ||
753 | break; | ||
754 | case 1: /* horiz edge */ | ||
755 | if (classes[1] == classes[3]) | ||
756 | printf(" "); | ||
757 | else | ||
758 | printf("--"); | ||
759 | break; | ||
760 | case 2: /* vert edge */ | ||
761 | if (classes[2] == classes[3]) | ||
762 | printf(" "); | ||
763 | else | ||
764 | printf("|"); | ||
765 | break; | ||
766 | case 3: /* square centre */ | ||
767 | printf(" "); | ||
768 | break; | ||
769 | } | ||
770 | } | ||
771 | printf("\n"); | ||
772 | } | ||
773 | printf("\n"); | ||
774 | sfree(dsf); | ||
775 | } | ||
776 | |||
777 | printf("%d retries needed for %d successes\n", fail_counter, tries); | ||
778 | |||
779 | return 0; | ||
780 | } | ||
781 | |||
782 | #endif | ||