summaryrefslogtreecommitdiff
path: root/trebuchet/trebuchet.c
blob: 72e735e76d24e61ede94e0322f7073ab07675937 (plain)
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
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>

static int first_half(FILE *fp) {
	size_t total = 0, size;
	ssize_t len;
	ssize_t first, last;
	char *line = NULL;
	while ((len = getline(&line, &size, fp)) != -1) {
		line[--len] = '\0';
		first = last = -1;
		for (size_t i = 0; i <= len; i++) {
			if (first == -1 && isdigit(line[i])) {
				first = line[i] - '0';
			}

			if (last == -1 && isdigit(line[len - i])) {
				last = line[len - i] - '0';
			}

			if (first > -1 && last > -1)
				break;
		}

		if (first == -1 || last == -1) {
			fprintf(stderr, "failed to find digit in input string: %s\n", line);
			free(line);
			return EXIT_FAILURE;
		}
		total += (first * 10) + last;
	}

	free(line);
	printf("result: %ld\n", total);
	return EXIT_SUCCESS;
}

const struct {
	size_t num;
	char *text;
} table[] = {
	{ 1, "one" },
	{ 2, "two" },
	{ 3, "three" },
	{ 4, "four" },
	{ 5, "five" },
	{ 6, "six" },
	{ 7, "seven" },
	{ 8, "eight" },
	{ 9, "nine" },
};

inline static ssize_t lookup_num(char *line, size_t i) {
	if (isdigit(line[i]))
		return line[i] - '0';

	for (size_t t = 0; t < sizeof(table) / sizeof(*table); t++)
		if (strncmp(&line[i], table[t].text, strlen(table[t].text)) == 0)
			return table[t].num;

	return -1;
}

static int second_half(FILE *fp) {
	size_t total = 0, size;
	ssize_t len;
	ssize_t first, last;
	char *line = NULL;
	while ((len = getline(&line, &size, fp)) != -1) {
		line[--len] = '\0';
		first = last = -1;
		for (size_t i = 0; i <= len; i++) {
			if (first == -1)
				first = lookup_num(line, i);
			if (last == -1)
				last = lookup_num(line, len - i);

			if (first > -1 && last > -1)
				break;
		}

		if (first == -1 || last == -1) {
			fprintf(stderr, "failed to find digit in input string: %s\n", line);
			free(line);
			return EXIT_FAILURE;
		}
		total += (first * 10) + last;
	}

	free(line);
	printf("result: %ld\n", total);
	return EXIT_SUCCESS;
}

int main(int argc, char **argv) {
	if (argc != 2) {
		fprintf(stderr, "usage: %s <input>\n", argv[0]);
		return EXIT_FAILURE;
	}

	FILE *fp = fopen(argv[1], "r");
	if (!fp) {
		fprintf(stderr, "failed to open input file: %s\n", argv[1]);
		return EXIT_FAILURE;
	}

	const char *half;
	int ret;
	if ((half = getenv("AOC_TREBUCHET_HALF")) && strcmp(half, "first") == 0)
		ret = first_half(fp);
	else
		ret = second_half(fp);
	fclose(fp);
	return ret;
}