#include "aoc.h" #include namespace aoc2016 { typedef void (*scramble)(char cs[8], int, int); static int index(char cs[8], char x) { for (int i = 0; i < 8; i++) { if (cs[i] == x) { return i; } } return 8; } // swap position X with position Y static void swap(char cs[8], int x, int y) { std::swap(cs[x], cs[y]); } // swap letter X with letter Y static void swap_char(char cs[8], int x, int y) { auto xi = index(cs, (char)x); auto yi = index(cs, (char)y); std::swap(cs[xi], cs[yi]); } // rotate left/right X steps static void rotate(char cs[8], int left, int right) { while (left-- > 0) { char head = cs[0]; for (int i = 1; i < 8; i++) { cs[i - 1] = cs[i]; } cs[7] = head; } while (right-- > 0) { char tail = cs[7]; for (int i = 6; i >= 0; i--) { cs[i + 1] = cs[i]; } cs[0] = tail; } } static void undo_rotate(char cs[8], int left, int right) { rotate(cs, right, left); } // rotate based on position of letter X // determine the index of letter X // rotate the string to the right one time // plus a number of times equal to that index // plus one additional time if the index was at least 4 static void rotate_char(char cs[8], int x, int y) { int i = index(cs, x); int s = i >= 4 ? 2 + i : 1 + i; rotate(cs, 0, s); } static void undo_rotate_char(char cs[8], int x, int y) { char xs[8] = {0}; int left = 8; for (int i = 0; i < 8; i++) { memcpy(xs, cs, 8); rotate(xs, i, 0); rotate_char(xs, x, y); if (memcmp(xs, cs, 8) == 0) { left = i; break; } } rotate(cs, left, 0); } // reverse positions X through Y // including the letters at X and Y static void reverse(char cs[8], int x, int y) { while (x < y) { std::swap(cs[x], cs[y]); x++; y--; } } // move position X to position Y static void move(char cs[8], int x, int y) { char c = cs[x]; if (x > y) { for (int i = x; i > y; i--) { cs[i] = cs[i - 1]; } } if (x < y) { for (int i = x; i < y; i++) { cs[i] = cs[i + 1]; } } cs[y] = c; } static void undo_move(char cs[8], int x, int y) { move(cs, y, x); } typedef void (*parse)(const char*, int ds[2]); static void parse_swap(const char* p, int ds[2]) { ds[0] = *(p + 14) - '0'; ds[1] = *(p + 30) - '0'; } static void parse_swap_char(const char* p, int ds[2]) { ds[0] = *(p + 12); ds[1] = *(p + 26); } static void parse_rotate(const char* p, int ds[2]) { if (*(p + 7) == 'l') { ds[0] = *(p + 12) - '0'; } if (*(p + 7) == 'r') { ds[1] = *(p + 13) - '0'; } } static void parse_rotate_char(const char* p, int ds[2]) { ds[0] = *(p + 35); ds[1] = 0; } static void parse_reverse(const char* p, int ds[2]) { ds[0] = *(p + 18) - '0'; ds[1] = *(p + 28) - '0'; } static void parse_move(const char* p, int ds[2]) { ds[0] = *(p + 14) - '0'; ds[1] = *(p + 28) - '0'; } //static void print(char* cs) { // for (int i = 0; i < 8; i++) { // auto c = cs[i]; // printf("%c", c); // } // printf("\n"); //} int action(const char* p) { int i = 6; if (*p == 's' && *(p + 5) == 'p') { i = 0; } if (*p == 's' && *(p + 5) == 'l') { i = 1; } if (*p == 'r' && *(p + 1) == 'o' && *(p + 7) == 'r') { i = 2; } if (*p == 'r' && *(p + 1) == 'o' && *(p + 7) == 'l') { i = 2; } if (*p == 'r' && *(p + 1) == 'o' && *(p + 7) == 'b') { i = 3; } if (*p == 'r' && *(p + 1) == 'e') { i = 4; } if (*p == 'm') { i = 5; } return i; } void day21(line_view file, char cs[8], char xs[8]) { struct { parse pf; scramble sf; scramble uf; } fs[] = {{parse_swap, swap, swap}, {parse_swap_char, swap_char, swap_char}, {parse_rotate, rotate, undo_rotate}, {parse_rotate_char, rotate_char, undo_rotate_char}, {parse_reverse, reverse, reverse}, {parse_move, move, undo_move}}; std::vector vs; // char cs[8] = {'g', 'd', 'f', 'c', 'a', 'b', 'e', 'h'}; per_line( file, [fs](line_view lv, char cs[8], std::vector& vs) { vs.emplace_back(lv); const char* p = lv.line; int ds[2] = {0, 0}; int i = action(p); fs[i].pf(p, ds); fs[i].sf(cs, ds[0], ds[1]); // print(cs); return true; }, cs, vs); // char xs[8] = {'b', 'd', 'f', 'h', 'g', 'e', 'c', 'a'}; // print(xs); for (size_t i = 0; i < vs.size(); i++) { size_t ii = vs.size() - i - 1; const char* p = vs[ii].line; int ds[2] = {0, 0}; int x = action(p); fs[x].pf(p, ds); fs[x].uf(xs, ds[0], ds[1]); // print(xs); } } } // namespace aoc2016