From 3c39a9143cad06f3e05d3c7478d8313380003361 Mon Sep 17 00:00:00 2001 From: Alex Karle Date: Mon, 6 Dec 2021 00:59:24 -0500 Subject: [PATCH] day6: Add hyper-optimized C solution Ok, so the parser was a huge struggle here and I was *reallllly* tempted to just rewrite the `input` to be split on newlines (using sed)... but I figured part of the "learning" is learning how to tokenize strings in C and not relying on existing tools... Other hiccups: * b required the use of long longs due to overflow * it took FOREVER to realize that despite fish aging to the '6th' index, I really needed them to age to the 7th which is the 6th on the next iteration... --- 6/a.c | 37 +++++++++++++++++++++++++++++++++++++ 6/b.c | 39 +++++++++++++++++++++++++++++++++++++++ Makefile | 2 +- 3 files changed, 77 insertions(+), 1 deletion(-) create mode 100644 6/a.c create mode 100644 6/b.c diff --git a/6/a.c b/6/a.c new file mode 100644 index 0000000..bfe4f66 --- /dev/null +++ b/6/a.c @@ -0,0 +1,37 @@ +#include +#include +#include + +int main(void) { + int counts[9] = {0}; + + /* Wow, the parser is more complex than the algorithm :( */ + char *line = NULL; + size_t linesize = 0; + getline(&line, &linesize, stdin); + char *p; + for (p = strtok(line, ","); p; p = strtok(NULL, ",")) { + counts[atoi(p)]++; + } + free(line); + + /* Phew, made it */ + for (int i = 0; i < 80; i++) { + /* Rather than pop & append, just edit in place and rotate + * the start index in use; i.e. on day 2, idx 1 is '0'. + * + * In fact, really all we need to do is add the current + * "populating fish" (mod 0) to the 7th index (which will + * be the 6th index on the next "lifecycle". + * */ + counts[(i + 7) % 9] += counts[i % 9]; + } + + int sum = 0; + for (int i = 0; i < 9; i++) { + sum += counts[i]; + } + printf("%d\n", sum); + + return 0; +} diff --git a/6/b.c b/6/b.c new file mode 100644 index 0000000..1f9c485 --- /dev/null +++ b/6/b.c @@ -0,0 +1,39 @@ +/* NOTE: only diff from a.c is the 256 rotation and use of a long long for + * big vals (tm). Duplicated for the sake of the build system :) */ +#include +#include +#include + +int main(void) { + unsigned long long counts[9] = {0}; + + /* Wow, the parser is more complex than the algorithm :( */ + char *line = NULL; + size_t linesize = 0; + getline(&line, &linesize, stdin); + char *p; + for (p = strtok(line, ","); p; p = strtok(NULL, ",")) { + counts[atoi(p)]++; + } + free(line); + + /* Phew, made it */ + for (int i = 0; i < 256; i++) { + /* Rather than pop & append, just edit in place and rotate + * the start index in use; i.e. on day 2, idx 1 is '0'. + * + * In fact, really all we need to do is add the current + * "populating fish" (mod 0) to the 7th index (which will + * be the 6th index on the next "lifecycle". + * */ + counts[(i + 7) % 9] += counts[i % 9]; + } + + unsigned long long sum = 0; + for (int i = 0; i < 9; i++) { + sum += counts[i]; + } + printf("%llu\n", sum); + + return 0; +} diff --git a/Makefile b/Makefile index dcb3500..055ccfc 100644 --- a/Makefile +++ b/Makefile @@ -11,7 +11,7 @@ CFLAGS = -g -O2 -Wall -Wpedantic -Wextra DAY = * -TARGETS = 1/a 1/b 2/a 2/b 3/a 5/a 5/b +TARGETS = 1/a 1/b 2/a 2/b 3/a 5/a 5/b 6/a 6/b .PHONY: build build: $(TARGETS) -- libgit2 1.8.1