From 959989750edb651725c02d5ca0bb42acf88448bd Mon Sep 17 00:00:00 2001 From: Zack Buhman Date: Fri, 12 Apr 2024 14:12:07 +0800 Subject: [PATCH] 2023/day3: add part2 C solution --- .gitignore | 1 + 2023/day3/{part1.c => _solution.c} | 106 +++++++++++++++++++++-------- 2 files changed, 80 insertions(+), 27 deletions(-) rename 2023/day3/{part1.c => _solution.c} (62%) diff --git a/.gitignore b/.gitignore index e1938bb..225078a 100644 --- a/.gitignore +++ b/.gitignore @@ -3,3 +3,4 @@ *.bin *.d *.map +*.out \ No newline at end of file diff --git a/2023/day3/part1.c b/2023/day3/_solution.c similarity index 62% rename from 2023/day3/part1.c rename to 2023/day3/_solution.c index 0d5f3e9..6c9b8fc 100644 --- a/2023/day3/part1.c +++ b/2023/day3/_solution.c @@ -66,15 +66,9 @@ uint32_t ix_from_xy(uint8_t const * const start, 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) +bool is_symbol(uint8_t const c) { - uint32_t const ix = ix_from_xy(start, stride, x, y); - uint8_t const c = start[ix]; + static uint8_t const symbols[] = {'@', '&', '=', '/', '-', '+', '%', '*', '$', '#'}; for (uint32_t i = 0; i < (sizeof (symbols)) / (sizeof (*symbols)); i++) { if (c == symbols[i]) { @@ -84,38 +78,90 @@ bool is_symbol(uint8_t const * const start, 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, - int32_t const digits) + 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++) { - 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; - } + 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 */ - if (xy_in_bounds(max_x, max_y, x + digits, y)) { - if (is_symbol(start, stride, x + digits, y)) - return true; - } + 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); - if (xy_in_bounds(max_x, max_y, x - 1, y)) { - if (is_symbol(start, stride, x - 1, y)) - return true; - } + return neighbor; +} - return false; +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, @@ -146,12 +192,18 @@ void solve(uint8_t const * const start, max_y, x, y, - (int32_t)digits); + 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)