aboutsummaryrefslogtreecommitdiff
path: root/2020/16/solve.c
blob: 0dd7665fc705433335505b0956f07c24cc1c887d (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>

struct rule {
	int low1;
	int high1;
	int low2;
	int high2;
};

int solve(FILE *fp)
{
	// Part one
	char *line = NULL;
	size_t len = 0;
	int paragraph = 0;
	char name[64] = { 0 };
	int ticket[64] = { 0 };
	int valid[256][128] = { 0 };
	int invalid[4096] = { 0 };
	struct rule rules[64] = { 0 };
	int rule_cnt = 0, invalid_cnt = 0, valid_cnt = 0;
	while (getline(&line, &len, fp) != -1) {
		if (line[0] == '\n') {
			paragraph++;
			continue;
		}
		if (paragraph == 0) {
			int low1, high1, low2, high2;
			sscanf(line, "%[^:]: %u-%u or %u-%u\n", name, &low1, &high1, &low2, &high2);
			struct rule rule = {
				.low1 = low1, .high1 = high1, .low2 = low2, .high2 = high2
			};
			rules[rule_cnt++] = rule;
		} else if (paragraph == 1) {
			if (line[0] == 'y')
				continue;
			int num, ind = 0;
			int bytes_now, bytes_consumed = 0;
			while (sscanf(line + bytes_consumed, "%d,%n", &num, &bytes_now) == 1) {
				ticket[ind++] = num;
				bytes_consumed += bytes_now;
			}
		} else if (paragraph == 2) {
			if (line[0] == 'n')
				continue;

			int num;
			int bytes_now, bytes_consumed = 0;

			int valid_nums[128] = { 0 };
			int invalid_ticket = 0, valid_nums_index = 0;
			while (sscanf(line + bytes_consumed, "%d,%n", &num, &bytes_now) > 0) {
				int inc = 0;
				for (int i = 0; i < rule_cnt; i++) {
					struct rule rule = rules[i];
					if ((num >= rule.low1 && num <= rule.high1) ||
					    (num >= rule.low2 && num <= rule.high2)) {
						inc = 0;
						break;
					} else {
						inc = num;
					}
				}
				if (inc) {
					invalid[invalid_cnt++] = num;
					invalid_ticket = 1;
				}

				if (!invalid_ticket)
					valid_nums[valid_nums_index++] = num;
				bytes_consumed += bytes_now;
			}
			if (!invalid_ticket)
				memcpy(&valid[valid_cnt++], valid_nums,
				       valid_nums_index * sizeof(int));
		}
	}

	int cnt = 0;
	for (int i = 0; i < invalid_cnt; i++) {
		cnt += invalid[i];
	}
	printf("%d\n", cnt);

	// Part two
	int used_rules[256] = { 0 };
	int rule_used[64] = { 0 };
	for (int x = 0; x < rule_cnt; x++) {
		for (int j = 0; j < rule_cnt; j++) {
			cnt = 0;
			struct rule rule = rules[j];
			for (int y = 0; y < valid_cnt; y++) {
				int num = valid[y][x];
				if ((num >= rule.low1 && num <= rule.high1) ||
				    (num >= rule.low2 && num <= rule.high2)) {
					cnt++;
				}
			}
			if (cnt == valid_cnt && !rule_used[j]) {
				rule_used[j] = 1;
				used_rules[x] = j;
				break;
			}
		}
	}

	int res = 1;
	for (int i = 0; i < rule_cnt; i++) {
		if (used_rules[i] < 6)
			res *= ticket[i];
	}

	return res;
}

int main(int argc, char *argv[])
{
	FILE *fp = fopen("input", "r");
	if (!fp)
		exit(EXIT_FAILURE);

	clock_t tic = clock();
	printf("%d\n", solve(fp));
	clock_t toc = clock();
	printf("TIME: %f seconds\n", (double)(toc - tic) / CLOCKS_PER_SEC);

	fclose(fp);
	return 0;
}