2023/day3: add part2 C solution

This commit is contained in:
Zack Buhman 2024-04-12 14:12:07 +08:00
parent f47dbb6691
commit 959989750e
2 changed files with 80 additions and 27 deletions

1
.gitignore vendored
View File

@ -3,3 +3,4 @@
*.bin *.bin
*.d *.d
*.map *.map
*.out

View File

@ -66,15 +66,9 @@ uint32_t ix_from_xy(uint8_t const * const start,
return (stride * y + x); return (stride * y + x);
} }
static const uint8_t symbols[] = {'@', '&', '=', '/', '-', '+', '%', '*', '$', '#'}; bool is_symbol(uint8_t const c)
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); static uint8_t const symbols[] = {'@', '&', '=', '/', '-', '+', '%', '*', '$', '#'};
uint8_t const c = start[ix];
for (uint32_t i = 0; i < (sizeof (symbols)) / (sizeof (*symbols)); i++) { for (uint32_t i = 0; i < (sizeof (symbols)) / (sizeof (*symbols)); i++) {
if (c == symbols[i]) { if (c == symbols[i]) {
@ -84,38 +78,90 @@ bool is_symbol(uint8_t const * const start,
return false; 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, bool has_adjacent_symbol(uint8_t const * const start,
uint32_t const stride, uint32_t const stride,
int32_t const max_x, int32_t const max_x,
int32_t const max_y, int32_t const max_y,
int32_t const x, int32_t const x,
int32_t const y, int32_t const y,
int32_t const digits) uint32_t const num,
int32_t const digits
)
{ {
bool neighbor = false;
/* check top/bottom/diagonals */ /* check top/bottom/diagonals */
for (int32_t xi = x - 1; xi <= x + digits; xi++) { for (int32_t xi = x - 1; xi <= x + digits; xi++) {
if (xy_in_bounds(max_x, max_y, xi, y - 1)) { adjacency_check(start, stride, max_x, max_y, xi, y + 1, num, &neighbor);
if (is_symbol(start, stride, xi, y - 1)) adjacency_check(start, stride, max_x, max_y, xi, y - 1, num, &neighbor);
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 */ /* check left/right side */
if (xy_in_bounds(max_x, max_y, x + digits, y)) { adjacency_check(start, stride, max_x, max_y, x + digits, y, num, &neighbor);
if (is_symbol(start, stride, x + digits, y)) adjacency_check(start, stride, max_x, max_y, x - 1 , y, num, &neighbor);
return true;
return neighbor;
} }
if (xy_in_bounds(max_x, max_y, x - 1, y)) { uint64_t part2_mac(void)
if (is_symbol(start, stride, x - 1, y)) {
return true; 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 false; return mac;
} }
void solve(uint8_t const * const start, void solve(uint8_t const * const start,
@ -146,12 +192,18 @@ void solve(uint8_t const * const start,
max_y, max_y,
x, x,
y, y,
(int32_t)digits); num,
(int32_t)digits
);
if (has) if (has)
sum += num; sum += num;
} }
printf("part1 sum: %d\n", sum); printf("part1 sum: %d\n", sum);
printf("part2:\n");
printf(" gears : %d\n", last_gear);
printf(" answer: %ld\n", part2_mac());
} }
int main(void) int main(void)