#include #include #include extern uint32_t _binary_2023_day3_input_txt_start __asm("_binary_input_txt_start"); extern uint32_t _binary_2023_day3_input_txt_end __asm("_binary_input_txt_end"); uint32_t parse_base10(uint8_t const ** const buf, uint32_t * num) { uint8_t const * const start_pos = *buf + 1; *num = 0; while (true) { uint8_t c = *(*buf)++; if (c >= '0' && c <= '9') { c = c - '0'; *num = *num * 10 + c; } else { /* return number of parsed digits */ return *buf - start_pos; } } } uint32_t next_number(uint8_t const * const end, uint8_t const ** const buf, uint32_t * num) { uint32_t digits = 0; while (digits == 0 && *buf < end) digits = parse_base10(buf, num); return digits; } uint32_t stride_newline(uint8_t const * const start) { uint8_t const * buf = start; while (*buf++ != '\n'); return buf - start; } void xy_from_ix(uint8_t const * const start, uint8_t const * const buf, uint32_t const stride, int32_t * x, int32_t * y) { uint32_t const offset = buf - start; *y = offset / stride; *x = offset % stride; } bool xy_in_bounds(int32_t const max_x, int32_t const max_y, int32_t const x, int32_t const y) { return x >= 0 && y >= 0 && y <= max_y && x <= max_x; } uint32_t ix_from_xy(uint8_t const * const start, uint32_t const stride, int32_t const x, int32_t const y) { return (stride * y + x); } bool is_symbol(uint8_t const c) { static uint8_t const symbols[] = {'@', '&', '=', '/', '-', '+', '%', '*', '$', '#'}; for (uint32_t i = 0; i < (sizeof (symbols)) / (sizeof (*symbols)); i++) { if (c == symbols[i]) { return true; } } return false; } bool is_gear(uint8_t const c) { return c == '*'; } struct adjacency { uint32_t ix; int32_t count; int32_t neighbors[4]; }; int32_t last_gear = 0; struct adjacency gears[512] = {0}; void update_gear_adjacencies(uint32_t gear_ix, uint32_t num) { for (int i = 0; i < (sizeof (gears)) / (sizeof (*gears)); i++) { if (i >= last_gear) { gears[last_gear++].ix = gear_ix; } if (gears[i].ix == gear_ix) { if (gears[i].count < 4) { gears[i].neighbors[gears[i].count++] = num; } break; } } } void adjacency_check(uint8_t const * const start, uint32_t const stride, int32_t const max_x, int32_t const max_y, int32_t const x, int32_t const y, uint32_t const num, bool * neighbor) { if (xy_in_bounds(max_x, max_y, x, y)) { uint32_t const ix = ix_from_xy(start, stride, x, y); uint8_t const c = start[ix]; if (is_symbol(c)) *neighbor = true; if (is_gear(c)) update_gear_adjacencies(ix, num); } } bool has_adjacent_symbol(uint8_t const * const start, uint32_t const stride, int32_t const max_x, int32_t const max_y, int32_t const x, int32_t const y, uint32_t const num, int32_t const digits ) { bool neighbor = false; /* check top/bottom/diagonals */ for (int32_t xi = x - 1; xi <= x + digits; xi++) { adjacency_check(start, stride, max_x, max_y, xi, y + 1, num, &neighbor); adjacency_check(start, stride, max_x, max_y, xi, y - 1, num, &neighbor); } /* check left/right side */ adjacency_check(start, stride, max_x, max_y, x + digits, y, num, &neighbor); adjacency_check(start, stride, max_x, max_y, x - 1 , y, num, &neighbor); return neighbor; } uint64_t part2_mac(void) { uint64_t mac = 0; for (int i = 0; i < last_gear; i++) { if (gears[i].count == 2) { mac += (uint64_t)gears[i].neighbors[0] * (uint64_t)gears[i].neighbors[1]; } } return mac; } void solve(uint8_t const * const start, uint8_t const * const end, uint32_t const stride) { uint8_t const * buf = start; int32_t max_x, max_y; xy_from_ix(start, end - 1, stride, &max_x, &max_y); uint32_t sum = 0; while (true) { uint32_t num, digits; digits = next_number(end, &buf, &num); if (digits == 0) break; uint8_t const * const num_start = buf - (digits + 1); int32_t x, y; xy_from_ix(start, num_start, stride, &x, &y); const bool has = has_adjacent_symbol(start, stride, max_x, max_y, x, y, num, (int32_t)digits ); if (has) sum += num; } printf("part1 sum: %d\n", sum); printf("part2:\n"); printf(" gears : %d\n", last_gear); printf(" answer: %ld\n", part2_mac()); } int main(void) { uint8_t const * const start = (uint8_t *)&_binary_2023_day3_input_txt_start; uint8_t const * const end = (uint8_t *)&_binary_2023_day3_input_txt_end; uint32_t const stride = stride_newline(start); solve(start, end, stride); }