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;
}
|