diff --git a/day18p1/main.c b/day18p1/main.c index 49c7809..a124626 100644 --- a/day18p1/main.c +++ b/day18p1/main.c @@ -10,9 +10,10 @@ struct size2d { }; struct buffer { - char *data; + void *data; size_t len; size_t alloc; + unsigned element; }; void *xrealloc(void *ptr, size_t size) @@ -25,22 +26,23 @@ void *xrealloc(void *ptr, size_t size) return res; } -struct buffer buffer_alloc() +struct buffer buffer_alloc(const unsigned element_size) { struct buffer buffer; buffer.len = 0; buffer.alloc = 0x10; - buffer.data = xrealloc(NULL, buffer.alloc); + buffer.element = element_size; + buffer.data = xrealloc(NULL, buffer.alloc * buffer.element); return buffer; } -void buffer_append(struct buffer *buffer, char c) +void buffer_append(struct buffer *buffer, void *data) { if (buffer->alloc <= buffer->len) { buffer->alloc *= 2; - buffer->data = xrealloc(buffer->data, buffer->alloc); + buffer->data = xrealloc(buffer->data, buffer->alloc * buffer->element); } - buffer->data[buffer->len++] = c; + memcpy((char *)buffer->data + buffer->len++ * buffer->element, data, buffer->element); } char *parse_acres(const char *fname, struct size2d *size) @@ -51,7 +53,7 @@ char *parse_acres(const char *fname, struct size2d *size) return NULL; } - struct buffer buffer = buffer_alloc(); + struct buffer buffer = buffer_alloc(sizeof(char)); size->w = 0; size->h = 0; @@ -79,7 +81,7 @@ char *parse_acres(const char *fname, struct size2d *size) goto error; } - buffer_append(&buffer, c); + buffer_append(&buffer, &c); width++; } funlockfile(f); @@ -184,6 +186,19 @@ int render_bitmap(const char *fname, const char *acres, const struct size2d size return 0; } +uint32_t adler32(const unsigned char *data, const size_t len) +{ + // Shamelessly copied from wikipedia... + uint32_t a = 1, b = 0; + + for (size_t index = 0; index < len; index++) { + a = (a + data[index]) % 65521; + b = (b + a) % 65521; + } + + return (b << 16) | a; +} + int main(int argc, char *argv[]) { struct size2d size; @@ -198,6 +213,10 @@ int main(int argc, char *argv[]) char *next = xrealloc(NULL, size.w * size.h); memcpy(next, acres, size.w * size.h); + struct buffer hashes = buffer_alloc(sizeof(uint32_t)); + unsigned loop_found = 0; + unsigned loop_iterlen = 0; + char *fname = NULL; clock_t start = clock(); for (unsigned i = 0; i <= minutes; i++) { @@ -205,6 +224,24 @@ int main(int argc, char *argv[]) advance_frame(acres, next, size); memcpy(acres, next, size.w * size.h); + if (!loop_found) { + uint32_t hash = adler32((unsigned char *)acres, size.w * size.h); + for (unsigned i = 0; i < hashes.len; i++) { + uint32_t check = ((uint32_t *)hashes.data)[i]; + if (check == hash) { + loop_found = i + 1; + break; + } + } + + if (loop_found) { + loop_iterlen = (i - loop_found); + minutes = (minutes - i) % loop_iterlen + i; + } else { + buffer_append(&hashes, &hash); + } + } + if (i % 10000 == 0) { double framespers = 10000 / ((double)(clock() - start) / CLOCKS_PER_SEC); unsigned eta = (double)(minutes - i) / framespers; @@ -235,8 +272,10 @@ int main(int argc, char *argv[]) } } + if (loop_found) printf("Loop starting frame: %u (length %u)\n", loop_found, loop_iterlen); printf("Resource value: %u\n", wood * lumber); + free(hashes.data); free(next); free(acres); return 0; diff --git a/day18p1/out.gif b/day18p1/out.gif index f05e320..0fd6845 100644 Binary files a/day18p1/out.gif and b/day18p1/out.gif differ diff --git a/day18p2 b/day18p2 new file mode 120000 index 0000000..505a8bc --- /dev/null +++ b/day18p2 @@ -0,0 +1 @@ +day18p1 \ No newline at end of file