2023/day3: part1 C implementation
This commit is contained in:
parent
a3fe4010db
commit
f47dbb6691
164
2023/day3/part1.c
Normal file
164
2023/day3/part1.c
Normal file
@ -0,0 +1,164 @@
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdio.h>
|
||||
|
||||
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);
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user