diff options
| author | Sebastiano Tronto <sebastiano@tronto.net> | 2023-09-17 19:54:37 +0200 |
|---|---|---|
| committer | Sebastiano Tronto <sebastiano@tronto.net> | 2023-09-17 19:54:37 +0200 |
| commit | 7c1cffb3f7c2be0d9ccc954a00b00db3bf4e2899 (patch) | |
| tree | 1fbd4817fddc120cc789a35b6b2178b7e944f773 | |
| parent | a37185d488b90eb89f5e9a949819e905919c84a8 (diff) | |
| download | nissy-classic-7c1cffb3f7c2be0d9ccc954a00b00db3bf4e2899.tar.gz nissy-classic-7c1cffb3f7c2be0d9ccc954a00b00db3bf4e2899.zip | |
Solution output sorting
Diffstat (limited to '')
| -rw-r--r-- | src/alg.c | 163 | ||||
| -rw-r--r-- | src/alg.h | 1 | ||||
| -rw-r--r-- | src/commands.c | 6 |
3 files changed, 168 insertions, 2 deletions
| @@ -13,6 +13,12 @@ static int axis(Move m); | |||
| 13 | static void free_alglistnode(AlgListNode *aln); | 13 | static void free_alglistnode(AlgListNode *aln); |
| 14 | static void realloc_alg(Alg *alg, int n); | 14 | static void realloc_alg(Alg *alg, int n); |
| 15 | 15 | ||
| 16 | static int niss_type(Alg *a); | ||
| 17 | static void find_last_moves(Alg *a, bool inv, int *, int *, int *); | ||
| 18 | static int last_move_pair(Alg *a, bool inv); | ||
| 19 | static int compare_algs_firstmoves(Alg * a, Alg *b, bool inv); | ||
| 20 | static int compare_algs(const void * a, const void *b); | ||
| 21 | |||
| 16 | /* Movesets ******************************************************************/ | 22 | /* Movesets ******************************************************************/ |
| 17 | 23 | ||
| 18 | Moveset | 24 | Moveset |
| @@ -459,6 +465,163 @@ realloc_alg(Alg *alg, int n) | |||
| 459 | alg->allocated = n; | 465 | alg->allocated = n; |
| 460 | } | 466 | } |
| 461 | 467 | ||
| 468 | static int | ||
| 469 | niss_type(Alg *a) | ||
| 470 | { | ||
| 471 | /* 0 if all moves are on normal, 1 if all on inverse, 2 otherwise */ | ||
| 472 | |||
| 473 | int i; | ||
| 474 | bool found_normal = false, found_inverse = false; | ||
| 475 | |||
| 476 | for (i = 0; i < a->len; i++) { | ||
| 477 | found_normal = found_normal || !a->inv[i]; | ||
| 478 | found_inverse = found_inverse || a->inv[i]; | ||
| 479 | } | ||
| 480 | |||
| 481 | if (found_normal && !found_inverse) | ||
| 482 | return 0; | ||
| 483 | if (!found_normal && found_inverse) | ||
| 484 | return 1; | ||
| 485 | return 2; | ||
| 486 | } | ||
| 487 | |||
| 488 | static void | ||
| 489 | find_last_moves(Alg *a, bool inv, int *n, int *nlast, int *nslast) | ||
| 490 | { | ||
| 491 | int i; | ||
| 492 | |||
| 493 | for (i = 0, *n = 0, *nlast = -1, *nslast = -1; i < a->len; i++) { | ||
| 494 | if (inv == a->inv[i]) { | ||
| 495 | (*n)++; | ||
| 496 | *nslast = *nlast; | ||
| 497 | *nlast = i; | ||
| 498 | } | ||
| 499 | } | ||
| 500 | } | ||
| 501 | |||
| 502 | static int | ||
| 503 | last_move_pair(Alg *a, bool inv) | ||
| 504 | { | ||
| 505 | /* The number of the move in the moves enum, or a higher number | ||
| 506 | * (working in base NMOVES) if the last two moves are parallel. | ||
| 507 | * -1 if there are no moves on the specified side of the alg. | ||
| 508 | */ | ||
| 509 | |||
| 510 | int n, nlast, nslast; | ||
| 511 | |||
| 512 | find_last_moves(a, inv, &n, &nlast, &nslast); | ||
| 513 | |||
| 514 | if (n == 0) | ||
| 515 | return -1; | ||
| 516 | if (nlast == 0 || !commute(a->move[nlast], a->move[nslast])) | ||
| 517 | return a->move[nlast]; | ||
| 518 | return a->move[nlast] * NMOVES + a->move[nslast]; | ||
| 519 | } | ||
| 520 | |||
| 521 | static int | ||
| 522 | compare_algs_firstmoves(Alg *a, Alg *b, bool inv) | ||
| 523 | { | ||
| 524 | /* Compare algs up to the last or the last two moves if parallel */ | ||
| 525 | |||
| 526 | int i, j, na, nlasta, nslasta, nb, nlastb, nslastb, ma, mb, m1, m2; | ||
| 527 | |||
| 528 | find_last_moves(a, inv, &na, &nlasta, &nslasta); | ||
| 529 | find_last_moves(b, inv, &nb, &nlastb, &nslastb); | ||
| 530 | |||
| 531 | ma = na > 0 ? ((na > 1 ? nslasta : nlasta) + 1) : 0; | ||
| 532 | mb = nb > 0 ? ((nb > 1 ? nslastb : nlastb) + 1) : 0; | ||
| 533 | |||
| 534 | if (ma == 0 && mb == 0) | ||
| 535 | return 0; | ||
| 536 | if (ma == 0) | ||
| 537 | return -1; | ||
| 538 | if (mb == 0) | ||
| 539 | return 1; | ||
| 540 | |||
| 541 | for (i = 0, j = 0; i < ma && j < mb; i++, j++) { | ||
| 542 | while (a->inv[i] != inv) i++; | ||
| 543 | while (a->inv[j] != inv) j++; | ||
| 544 | m1 = a->move[i]; | ||
| 545 | m2 = b->move[j]; | ||
| 546 | if (m1 - m2) | ||
| 547 | return m1 - m2; | ||
| 548 | } | ||
| 549 | |||
| 550 | return ma - mb; | ||
| 551 | } | ||
| 552 | |||
| 553 | static int | ||
| 554 | compare_algs(const void *avoid, const void *bvoid) | ||
| 555 | { | ||
| 556 | /* We sort a list of algs in a way that makes the most sense for the | ||
| 557 | * commands and steps where one usually wants many results, for | ||
| 558 | * example EO and DR. We sort by, in order: | ||
| 559 | * 1. Length of the solution | ||
| 560 | * 2. NISS type (first algs that are all on normal, then those that | ||
| 561 | * are all on inverse, then those that use NISS) | ||
| 562 | * 3. Last move on normal, or last two moves if they are parallel | ||
| 563 | * 4. All other moves on normal scramble | ||
| 564 | * 5. Last move on inverse, or last two moves if they are parallel | ||
| 565 | * 6. All other moves on inverse | ||
| 566 | */ | ||
| 567 | |||
| 568 | Alg *a = *(Alg **)avoid; | ||
| 569 | Alg *b = *(Alg **)bvoid; | ||
| 570 | |||
| 571 | int ntype_a, ntype_b, last_a, last_b, cmp; | ||
| 572 | |||
| 573 | /* 1. Compare length */ | ||
| 574 | if (a->len - b->len) | ||
| 575 | return a->len - b->len; | ||
| 576 | |||
| 577 | /* 2. Algs have the same length, compare NISS type */ | ||
| 578 | ntype_a = niss_type(a); | ||
| 579 | ntype_b = niss_type(b); | ||
| 580 | if (ntype_a - ntype_b) | ||
| 581 | return ntype_a - ntype_b; | ||
| 582 | |||
| 583 | /* 3. Algs have same NISS type, compare last moves on normal */ | ||
| 584 | last_a = last_move_pair(a, false); | ||
| 585 | last_b = last_move_pair(b, false); | ||
| 586 | if (last_a - last_b) | ||
| 587 | return last_a - last_b; | ||
| 588 | |||
| 589 | /* 4. Algs have same last moves on normal, compare all other moves */ | ||
| 590 | cmp = compare_algs_firstmoves(a, b, false); | ||
| 591 | if (cmp) | ||
| 592 | return cmp; | ||
| 593 | |||
| 594 | /* 5. Algs have same moves on normal, compare last on inverse */ | ||
| 595 | last_a = last_move_pair(a, true); | ||
| 596 | last_b = last_move_pair(b, true); | ||
| 597 | if (last_a - last_b) | ||
| 598 | return last_a - last_b; | ||
| 599 | |||
| 600 | /* 6. Algs have same last moves on inverse, compare other */ | ||
| 601 | cmp = compare_algs_firstmoves(a, b, true); | ||
| 602 | if (cmp) | ||
| 603 | return cmp; | ||
| 604 | |||
| 605 | /* Algs are equal */ | ||
| 606 | return 0; | ||
| 607 | } | ||
| 608 | |||
| 609 | void | ||
| 610 | sort_alglist(AlgList *al) | ||
| 611 | { | ||
| 612 | int i, n = al->len; | ||
| 613 | Alg* alg_array[n]; | ||
| 614 | AlgListNode *node; | ||
| 615 | |||
| 616 | for (i = 0, node = al->first; i < n; i++, node = node->next) | ||
| 617 | alg_array[i] = node->alg; | ||
| 618 | |||
| 619 | qsort(alg_array, n, sizeof(Alg *), &compare_algs); | ||
| 620 | |||
| 621 | for (i = 0, node = al->first; i < n; i++, node = node->next) | ||
| 622 | node->alg = alg_array[i]; | ||
| 623 | } | ||
| 624 | |||
| 462 | void | 625 | void |
| 463 | swapmove(Move *m1, Move *m2) | 626 | swapmove(Move *m1, Move *m2) |
| 464 | { | 627 | { |
| @@ -33,6 +33,7 @@ AlgList * new_alglist(void); | |||
| 33 | Alg * on_inverse(Alg *alg); | 33 | Alg * on_inverse(Alg *alg); |
| 34 | void print_alg(Alg *alg, bool l); | 34 | void print_alg(Alg *alg, bool l); |
| 35 | void print_alglist(AlgList *al, bool l); | 35 | void print_alglist(AlgList *al, bool l); |
| 36 | void sort_alglist(AlgList *al); | ||
| 36 | void swapmove(Move *m1, Move *m2); | 37 | void swapmove(Move *m1, Move *m2); |
| 37 | Alg * unniss(Alg *alg); | 38 | Alg * unniss(Alg *alg); |
| 38 | 39 | ||
diff --git a/src/commands.c b/src/commands.c index 7dd2e45..78d7583 100644 --- a/src/commands.c +++ b/src/commands.c | |||
| @@ -398,10 +398,12 @@ solve_exec(CommandArgs *args) | |||
| 398 | c = apply_alg(args->scramble, (Cube){0}); | 398 | c = apply_alg(args->scramble, (Cube){0}); |
| 399 | sols = solve(c, args->step, args->opts); | 399 | sols = solve(c, args->step, args->opts); |
| 400 | 400 | ||
| 401 | if (args->opts->count_only) | 401 | if (args->opts->count_only) { |
| 402 | printf("%d\n", sols->len); | 402 | printf("%d\n", sols->len); |
| 403 | else | 403 | } else { |
| 404 | sort_alglist(sols); | ||
| 404 | print_alglist(sols, args->opts->print_number); | 405 | print_alglist(sols, args->opts->print_number); |
| 406 | } | ||
| 405 | 407 | ||
| 406 | free_alglist(sols); | 408 | free_alglist(sols); |
| 407 | } | 409 | } |
