complete part 8 (switched to bitmasks).

This commit is contained in:
2021-12-10 17:39:51 +01:00
parent 3235bd3b15
commit 192545c9a3
5 changed files with 145 additions and 30 deletions

View File

@@ -91,3 +91,15 @@ aoc-c : res=349769
aoc-c : res=99540554 aoc-c : res=99540554
time: 0:00.00 real, 0.00 user, 0.00 sys time: 0:00.00 real, 0.00 user, 0.00 sys
context-switch: 1+1, page-faults: 0+93 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

1
2021/day08/EXAMPLE2.txt Normal file
View File

@@ -0,0 +1 @@
acedgfb cdfbe gcdfa fbcad dab cefabd cdfgeb eafb cagedb ab | cdfeb fcadb cdfeb cdbaf

View File

@@ -24,7 +24,7 @@ LDLIB := -l$(LIB)
export LD_LIBRARY_PATH = $(LIBDIR) export LD_LIBRARY_PATH = $(LIBDIR)
CFLAGS += -std=gnu99 CFLAGS += -std=gnu99
#CFLAGS += -O2 CFLAGS += -O2
CFLAGS += -g CFLAGS += -g
CFLAGS += -Wall CFLAGS += -Wall
CFLAGS += -Wextra CFLAGS += -Wextra

View File

@@ -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? In the output values, how many times do digits 1, 4, 7, or 8 appear?
Your puzzle answer was 543. Your puzzle answer was 543.
The first half of this puzzle is complete! It provides one gold star: *
--- Part Two --- --- Part Two ---
Through a little deduction, you should now be able to determine the remaining digits. Consider again the first example above: 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. 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? 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: **

View File

@@ -20,17 +20,25 @@
#include "bits.h" #include "bits.h"
#include "list.h" #include "list.h"
typedef struct { /* bitmask (last 7 bits): ... g f e d c b a
int len; */
char *code; typedef u64 token;
} token;
typedef struct { typedef struct {
token unique[10]; token unique[10];
token output[4]; token output[4];
} code; } 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) static void print_code(code *code)
{ {
int i = 0; int i = 0;
@@ -38,14 +46,26 @@ static void print_code(code *code)
//printf("crabs=%d max=%d\n", ncrabs, crab_max); //printf("crabs=%d max=%d\n", ncrabs, crab_max);
printf("unique: "); printf("unique: ");
for (i = 0; i < 10; ++i) 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("\n");
printf("output: "); printf("output: ");
for (i = 0; i < 4; ++i) 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"); 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() static code *read_code()
{ {
@@ -64,47 +84,127 @@ static code *read_code()
while (token) { while (token) {
if (*token == '|') if (*token == '|')
break; break;
code.unique[i].code = token; code.unique[i] = a2bit(token);
code.unique[i].len = strlen(token);
i++; i++;
token = strtok(NULL, " \n"); token = strtok(NULL, " \n");
} }
//printf("cont = %c\n", *token);
//print_code(&code);
i = 0; i = 0;
while ((token = strtok(NULL, " \n"))) { while ((token = strtok(NULL, " \n"))) {
//printf("output %d = [%s]\n", i, token); code.output[i] = a2bit(token);
code.output[i].code = token;
code.output[i].len = strlen(token);
i++; i++;
} }
if (i != 4)
printf("output = %d\n", i);
free(buf); free(buf);
return &code; return &code;
} }
static u64 doit(int part)
static u64 part1()
{ {
code *code; code *code;
int res = 0; int res = 0;
while ((code = read_code())) { while ((code = read_code())) {
if (part == 1) {
for (int i = 0; i < 4; ++i) { for (int i = 0; i < 4; ++i) {
int len = code->output[i].len; int len = popcount64(code->output[i]);
/* digits: 1 4 7 8 */ /* digits: 1 4 7 8 */
if (len == 2 || len == 4 || len == 3 || len == 7) { if (len == 2 || len == 4 || len == 3 || len == 7)
printf("%d : %s\n", len, code->output[i].code);
res++; res++;
} }
} }
}
}
return 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) static int usage(char *prg)
{ {
fprintf(stderr, "Usage: %s [-d debug_level] [-p part]\n", prg); fprintf(stderr, "Usage: %s [-d debug_level] [-p part]\n", prg);