#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); } static const uint8_t symbols[] = {'@', '&', '=', '/', '-', '+', '%', '*', '$', '#'}; bool is_symbol(uint8_t const * const start, uint32_t const stride, uint32_t const x, uint32_t const y) { uint32_t const ix = ix_from_xy(start, stride, x, y); uint8_t const c = start[ix]; for (uint32_t i = 0; i < (sizeof (symbols)) / (sizeof (*symbols)); i++) { if (c == symbols[i]) { return true; } } return false; } 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, int32_t const digits) { /* check top/bottom/diagonals */ for (int32_t xi = x - 1; xi <= x + digits; xi++) { if (xy_in_bounds(max_x, max_y, xi, y - 1)) { if (is_symbol(start, stride, xi, y - 1)) return true; } if (xy_in_bounds(max_x, max_y, xi, y + 1)) { if (is_symbol(start, stride, xi, y + 1)) return true; } } /* check left/right side */ if (xy_in_bounds(max_x, max_y, x + digits, y)) { if (is_symbol(start, stride, x + digits, y)) return true; } if (xy_in_bounds(max_x, max_y, x - 1, y)) { if (is_symbol(start, stride, x - 1, y)) return true; } return false; } 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, (int32_t)digits); if (has) sum += num; } printf("part1 sum: %d\n", sum); } 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); }