From 192545c9a3c0e26a3b588f2cd2521d16f31a3125 Mon Sep 17 00:00:00 2001 From: Bruno Raoult Date: Fri, 10 Dec 2021 17:39:51 +0100 Subject: [PATCH] complete part 8 (switched to bitmasks). --- 2021/OUTPUT | 12 ++++ 2021/day08/EXAMPLE2.txt | 1 + 2021/day08/Makefile | 2 +- 2021/day08/README.txt | 6 +- 2021/day08/aoc-c.c | 154 +++++++++++++++++++++++++++++++++------- 5 files changed, 145 insertions(+), 30 deletions(-) create mode 100644 2021/day08/EXAMPLE2.txt diff --git a/2021/OUTPUT b/2021/OUTPUT index 8ae1145..1ab2dca 100644 --- a/2021/OUTPUT +++ b/2021/OUTPUT @@ -91,3 +91,15 @@ aoc-c : res=349769 aoc-c : res=99540554 time: 0:00.00 real, 0.00 user, 0.00 sys context-switch: 1+1, page-faults: 0+93 + +========================================= +================= day08 ================= +========================================= + +aoc-c : res=543 + time: 0:00.00 real, 0.00 user, 0.00 sys + context-switch: 0+1, page-faults: 0+85 + +aoc-c : res=994266 + time: 0:00.00 real, 0.00 user, 0.00 sys + context-switch: 0+1, page-faults: 0+86 diff --git a/2021/day08/EXAMPLE2.txt b/2021/day08/EXAMPLE2.txt new file mode 100644 index 0000000..42b3bfd --- /dev/null +++ b/2021/day08/EXAMPLE2.txt @@ -0,0 +1 @@ +acedgfb cdfbe gcdfa fbcad dab cefabd cdfgeb eafb cagedb ab | cdfeb fcadb cdfeb cdbaf diff --git a/2021/day08/Makefile b/2021/day08/Makefile index 23f0299..e585a35 100644 --- a/2021/day08/Makefile +++ b/2021/day08/Makefile @@ -24,7 +24,7 @@ LDLIB := -l$(LIB) export LD_LIBRARY_PATH = $(LIBDIR) CFLAGS += -std=gnu99 -#CFLAGS += -O2 +CFLAGS += -O2 CFLAGS += -g CFLAGS += -Wall CFLAGS += -Wextra diff --git a/2021/day08/README.txt b/2021/day08/README.txt index ee8f31c..63f2ce7 100644 --- a/2021/day08/README.txt +++ b/2021/day08/README.txt @@ -71,8 +71,6 @@ Because the digits 1, 4, 7, and 8 each use a unique number of segments, you shou In the output values, how many times do digits 1, 4, 7, or 8 appear? Your puzzle answer was 543. - -The first half of this puzzle is complete! It provides one gold star: * --- Part Two --- Through a little deduction, you should now be able to determine the remaining digits. Consider again the first example above: @@ -128,3 +126,7 @@ Following this same process for each entry in the second, larger example above, Adding all of the output values in this larger example produces 61229. For each entry, determine all of the wire/segment connections and decode the four-digit output values. What do you get if you add up all of the output values? + +Your puzzle answer was 994266. + +Both parts of this puzzle are complete! They provide two gold stars: ** diff --git a/2021/day08/aoc-c.c b/2021/day08/aoc-c.c index 8a9d417..e3b93fc 100644 --- a/2021/day08/aoc-c.c +++ b/2021/day08/aoc-c.c @@ -20,17 +20,25 @@ #include "bits.h" #include "list.h" -typedef struct { - int len; - char *code; -} token; +/* bitmask (last 7 bits): ... g f e d c b a + */ +typedef u64 token; typedef struct { token unique[10]; token output[4]; } code; -//#ifdef DEBUG +#ifdef DEBUG +inline static char *bits_str(u64 c) +{ + static char str[9]; + + for (int i = 7; i >= 0; --i) + str[7 - i] = c & (1 << i) ? '1': '0'; + return str; +} + static void print_code(code *code) { int i = 0; @@ -38,14 +46,26 @@ static void print_code(code *code) //printf("crabs=%d max=%d\n", ncrabs, crab_max); printf("unique: "); for (i = 0; i < 10; ++i) - printf("[%d]%s ", code->unique[i].len, code->unique[i].code); + printf("[%d]%s ", popcount64(code->unique[i]), bits_str(code->unique[i])); printf("\n"); printf("output: "); for (i = 0; i < 4; ++i) - printf("[%d]%s ", code->output[i].len, code->output[i].code); + printf("[%d]%s ", popcount64(code->unique[i]), bits_str(code->unique[i])); printf("\n"); } -//#endif +#endif + +#define BIT(c) (1 << ((c) - 'a')) + +inline static u64 a2bit(char *token) +{ + u64 res = 0; + while (*token) { + res |= BIT(*token); + token++; + } + return res; +} static code *read_code() { @@ -64,47 +84,127 @@ static code *read_code() while (token) { if (*token == '|') break; - code.unique[i].code = token; - code.unique[i].len = strlen(token); + code.unique[i] = a2bit(token); i++; token = strtok(NULL, " \n"); } - //printf("cont = %c\n", *token); - //print_code(&code); i = 0; while ((token = strtok(NULL, " \n"))) { - //printf("output %d = [%s]\n", i, token); - code.output[i].code = token; - code.output[i].len = strlen(token); + code.output[i] = a2bit(token); i++; } - if (i != 4) - printf("output = %d\n", i); free(buf); return &code; } -static u64 doit(int part) + +static u64 part1() { code *code; int res = 0; while ((code = read_code())) { - if (part == 1) { - for (int i = 0; i < 4; ++i) { - int len = code->output[i].len; - /* digits: 1 4 7 8 */ - if (len == 2 || len == 4 || len == 3 || len == 7) { - printf("%d : %s\n", len, code->output[i].code); - res++; - } - } + for (int i = 0; i < 4; ++i) { + int len = popcount64(code->output[i]); + /* digits: 1 4 7 8 */ + if (len == 2 || len == 4 || len == 3 || len == 7) + res++; } } return res; } + +static u64 part2() +{ + code *code; + u64 bits; + int res = 0, tmp; + + while ((code = read_code())) { + u64 digits[10] = { 0 }; + + /* find digits 1, 4, 7, 8 */ + for (int i = 0; i < 10; ++i) { + bits = code->unique[i]; + switch (popcount64(bits)) { + case 2: + digits[1] = bits; + code->unique[i] = 0; + break; + case 3: + digits[7] = bits; + code->unique[i] = 0; + break; + case 4: + digits[4] = bits; + code->unique[i] = 0; + break; + case 7: + digits[8] = bits; + code->unique[i] = 0; + break; + } + } + /* find digits 3 & 6: 2 and 1 bits in common with 1 */ + for (int i = 0; i < 10; ++i) { + bits = code->unique[i]; + if (popcount64(bits) == 5) { + if (popcount64(bits & digits[1]) == 2) { + digits[3] = bits; + code->unique[i] = 0; + } + } + if (popcount64(bits) == 6) { + if (popcount64(bits & digits[1]) == 1) { + digits[6] = bits; + code->unique[i] = 0; + } + } + } + /* find digits 9 and 0: 9 has 5 bits in common with 5 */ + for (int i = 0; i < 10; ++i) { + bits = code->unique[i]; + if (popcount64(bits) == 6) { + if (popcount64(bits & digits[3]) == 5) + digits[9] = bits; + else + digits[0] = bits; + code->unique[i] = 0; + } + } + /* find digits 2 and 5: 2 has 4 bits in common with 9 */ + for (int i = 0; i < 10; ++i) { + bits = code->unique[i]; + if (popcount64(bits) == 5) { + if (popcount64(bits & digits[9]) == 4) + digits[2] = bits; + else + digits[5] = bits; + code->unique[i] = 0; + } + } + tmp = 0; + for (int i = 0; i < 4; ++i) { + for (int j = 0; j < 10; ++j) { + if (code->output[i] == digits[j]) { + tmp = tmp * 10 + j; + break; + } + } + } + res += tmp; + } + + return res; +} + +static u64 doit(int part) +{ + return part == 1? part1(): part2(); +} + static int usage(char *prg) { fprintf(stderr, "Usage: %s [-d debug_level] [-p part]\n", prg);