From f47dbb66910a222278b18c10059910e35c89e6cf Mon Sep 17 00:00:00 2001 From: Zack Buhman Date: Wed, 10 Apr 2024 21:31:49 +0800 Subject: [PATCH] 2023/day3: part1 C implementation --- 2023/day3/part1.c | 164 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 164 insertions(+) create mode 100644 2023/day3/part1.c diff --git a/2023/day3/part1.c b/2023/day3/part1.c new file mode 100644 index 0000000..0d5f3e9 --- /dev/null +++ b/2023/day3/part1.c @@ -0,0 +1,164 @@ +#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); +}