#include #include #include #include struct num { long val; long ord; }; // Proper mathematical modulo, which returns a value in the range 0 <= n < m // Even if n is negative. // Warning, evaluates `m` multiple times (but `n` only once) #define modulo(n, m) ((((n) % (m)) + (m)) % (m)) int main(int argc, char ** argv) { long key = 1, rounds = 1; char buf[BUFSIZ]; struct num * nums = NULL; int nnums = 0, numsize = 0, r, i, pos; // Parse options while ((i = getopt(argc, argv, "p:k:r:")) != -1) { switch (i) { case 'p': switch (atoi(optarg)) { case 1: key = 1; rounds = 1; break; case 2: key = 811589153; rounds = 10; break; default: fprintf(stderr, "Invalid part %s\n", optarg); return -1; } break; case 'k': key = atoi(optarg); if (!key) { fprintf(stderr, "Invalid key %s\n", optarg); return -1; } break; case 'r': rounds = atoi(optarg); if (rounds < 0) { fprintf(stderr, "Invalid rounds %s\n", optarg); return -1; } break; default: return -1; } } // Read file. while (fgets(buf, sizeof(buf), stdin)) { char * end; if (nnums == numsize) { void * p; numsize += BUFSIZ; if ((p = realloc(nums, numsize * sizeof(struct num))) == NULL) { fprintf(stderr, "Bad realloc(%zu)\n", numsize * sizeof(struct num)); free(nums); return -1; } nums = p; } if ((nums[nnums].val = strtol(buf, &end, 10)) == 0 && end == buf) { fprintf(stderr, "Invalid entry: %s\n", buf); free(nums); return -1; } nums[nnums].val *= key; nums[nnums].ord = nnums; ++nnums; } // Mix file. for (r = 0; r < rounds; ++r) { for (i = 0, pos = 0; i < nnums; ++i) { int newpos; struct num tmp; // Look for the num whose ordinal is i, starting from the // position of the last num we looked at. while (nums[pos].ord != i) pos = modulo(pos + 1, nnums); if (nums[pos].val == 0) continue; // Move this. tmp = nums[pos]; newpos = modulo(pos + nums[pos].val, nnums - 1); // Buffer of nums does not include moving num if (newpos > pos) memmove(nums + pos, nums + pos + 1, (newpos - pos) * sizeof(struct num)); else memmove(nums + newpos + 1, nums + newpos, (pos - newpos) * sizeof(struct num)); nums[newpos] = tmp; } } // Find zero. for (i = 0; i < nnums; ++i) if (nums[i].val == 0) break; if (i == nnums) { fprintf(stderr, "No zero found!\n"); free(nums); return -1; } printf("Coords: %ld,%ld,%ld; sum %ld\n", nums[modulo(i + 1000, nnums)].val, nums[modulo(i + 2000, nnums)].val, nums[modulo(i + 3000, nnums)].val, nums[modulo(i + 1000, nnums)].val + nums[modulo(i + 2000, nnums)].val + nums[modulo(i + 3000, nnums)].val); free(nums); return 0; }