#define _GNU_SOURCE #include #include #include #include uint64_t parse_number(char *end); int main(int argc, char **argv) { FILE *input; char *line = NULL; size_t line_length = 0; if (argc == 1 || argv[1][0] == '-') input = stdin; else if ((input = fopen(argv[1], "r")) == NULL) { printf("Cannot open file %s\n", argv[1]); return -1; } uint64_t total_points = 0; size_t winning_numbers_len = 0; uint8_t *winning_numbers = NULL; char *colon_pos = NULL, *pipe_pos = NULL; while (getline(&line, &line_length, input) != -1) { colon_pos = strchr(line, ':'); pipe_pos = strchr(line, '|'); if (winning_numbers == NULL) { winning_numbers_len = (pipe_pos - colon_pos - 2) / 3; winning_numbers = (uint8_t *) calloc(winning_numbers_len, sizeof(uint8_t)); } for (size_t i = 0, wl_pos = (size_t)colon_pos+4; i < winning_numbers_len; ++i, wl_pos += 3) winning_numbers[i] = parse_number((char *)(wl_pos-1)); uint64_t points = 0; for (char *n_pos = pipe_pos + 4;; n_pos += 3) { uint8_t n = parse_number(n_pos-1); for (size_t i = 0; i < winning_numbers_len; ++i) { if (n != winning_numbers[i]) continue; points = (points == 0) ? 1 : points * 2; break; } if (*n_pos == '\n') break; } total_points += points; memset(line, 0, line_length); } free(winning_numbers); printf("%lu\n", total_points); return 0; } uint64_t parse_number(char *end) { uint64_t num = 0; for (size_t n = 1;; n *= 10) { if (*end>>4 != 0x3) break; num += (*end&0xf) * n; --end; } return num; }