summary refs log tree commit diff homepage
path: root/2020
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--2020/day16.c46
1 files changed, 43 insertions, 3 deletions
diff --git a/2020/day16.c b/2020/day16.c
index 6b3d29e..df28ae6 100644
--- a/2020/day16.c
+++ b/2020/day16.c
@@ -40,16 +40,56 @@ int main(void) {
 	int len;
 	for (len = 0; parse(&nearby[len]); ++len);
 	int error = 0;
+	struct Ticket valids[256];
+	int vlen = 0;
 	for (int i = 0; i < len; ++i) {
+		bool ticket = true;
 		for (int j = 0; j < nrules; ++j) {
-			bool valid = false;
+			bool field = false;
 			for (int r = 0; r < nrules; ++r) {
 				if (!check(&rules[r], nearby[i].fields[j])) continue;
-				valid = true;
+				field = true;
 				break;
 			}
-			if (!valid) error += nearby[i].fields[j];
+			if (!field) {
+				error += nearby[i].fields[j];
+				ticket = false;
+			}
 		}
+		if (ticket) valids[vlen++] = nearby[i];
 	}
 	printf("%d\n", error);
+	int map[32] = {0};
+	for (int r = 0; r < nrules; ++r) {
+		for (int f = 0; f < nrules; ++f) {
+			bool valid = true;
+			for (int i = 0; i < vlen; ++i) {
+				if (check(&rules[r], valids[i].fields[f])) continue;
+				valid = false;
+				break;
+			}
+			if (valid) map[r] |= 1 << f;
+		}
+	}
+	for (bool done = false; !done;) {
+		for (int i = 0; i < nrules; ++i) {
+			if (__builtin_popcount(map[i]) > 1) continue;
+			for (int j = 0; j < nrules; ++j) {
+				if (j != i) map[j] &= ~map[i];
+			}
+		}
+		done = true;
+		for (int i = 0; i < nrules; ++i) {
+			if (__builtin_popcount(map[i]) > 1) done = false;
+		}
+	}
+	for (int i = 0; i < nrules; ++i) {
+		map[i] = __builtin_ctz(map[i]);
+	}
+	long departure = 1;
+	for (int i = 0; i < nrules; ++i) {
+		if (strncmp(rules[i].name, "departure", 9)) continue;
+		departure *= mine.fields[map[i]];
+	}
+	printf("%ld\n", departure);
 }