#define _GNU_SOURCE #include #include #include #include inline uint64_t parse_number(const char *end); #define MAPS_LEN 7 typedef struct { uint64_t dst, src, rng; } map_t; int main(int argc, char **argv) { FILE *input; char *line = NULL; size_t line_buf_length = 0; if (argc == 1 || argv[1][0] == '-') input = stdin; else if ((input = fopen(argv[1], "r")) == NULL) { fprintf(stderr, "Cannot open file %s\n", argv[1]); return -1; } if (getline(&line, &line_buf_length, input) == -1) { fprintf(stderr, "A file %s ended unexpectedly.", argv[1]); return -1; } char *colon_pos = strchr(line, ':'); size_t seed_ranges_len = 0; for (char *space_pos = colon_pos+1; space_pos != NULL; space_pos = strchr(space_pos, ' ')) { seed_ranges_len++; space_pos++; } uint64_t *seed_ranges = (uint64_t *) calloc(seed_ranges_len, sizeof(uint64_t)); for (size_t i = 0, seeds_pos = (size_t) colon_pos+2;; seeds_pos++) { while (*(char *)(seeds_pos)>>4 == 0x3) seeds_pos++; seed_ranges[i++] = parse_number((char *)(seeds_pos-1)); if (*(char *)seeds_pos == '\n') break; } map_t **maps = (map_t **) calloc(MAPS_LEN, sizeof(map_t *)); for (size_t i = 0; i < MAPS_LEN; ++i) maps[i] = (map_t *) calloc(1, sizeof(map_t)); size_t map_lengths[MAPS_LEN] = {1}; int8_t maps_cur = -1; while (getline(&line, &line_buf_length, input) != -1) { if (maps_cur == MAPS_LEN) break; if (line[0] == '\n') { maps_cur++; continue; } else if (line[0]>>4 != 0x3) continue; maps[maps_cur] = (map_t *) realloc(maps[maps_cur], ++map_lengths[maps_cur] * sizeof(map_t)); map_t new_range_map = {0}; sscanf(line, "%lu %lu %lu\n", &new_range_map.dst, &new_range_map.src, &new_range_map.rng); maps[maps_cur][map_lengths[maps_cur]-1] = new_range_map; memset(line, 0, line_buf_length); } uint64_t lowest_loc_n = UINT64_MAX; for (size_t i = 0; i < seed_ranges_len; i += 2) #pragma omp parallel for shared(lowest_loc_n) for (uint64_t r = seed_ranges[i]; r < seed_ranges[i] + seed_ranges[i+1]; ++r) { uint64_t seed = r; for (size_t j = 0; j < MAPS_LEN; ++j) for (size_t k = 0; k < map_lengths[j]; ++k) if (seed >= maps[j][k].src && seed <= maps[j][k].src + maps[j][k].rng) { seed = maps[j][k].dst + (seed - maps[j][k].src); break; } if (seed < lowest_loc_n) lowest_loc_n = seed; } free(seed_ranges); for (size_t i = 0; i < MAPS_LEN; ++i) free(maps[i]); printf("%lu\n", lowest_loc_n); return 0; } inline uint64_t parse_number(const char *end) { uint64_t num = 0; for (size_t m = 1;; m *= 10) { if (*end>>4 != 0x3) break; num += (*end&0xf) * m; --end; } return num; }