2024-12-12 04:47:18 -06:00

147 lines
3.3 KiB
C

#include <stdint.h>
#include "parse.h"
#include "printf.h"
enum cube_color {
red = 0,
green = 1,
blue = 2,
};
struct cube_set {
int color[3];
};
static const char * parse_color(const char * input, enum cube_color * color)
{
const char * end;
if ((end = parse_match(input, "red"))) {
*color = red;
} else if ((end = parse_match(input, "blue"))) {
*color = blue;
} else if ((end = parse_match(input, "green"))) {
*color = green;
}
return end;
}
static const char * parse_cube(const char * input, int * value, enum cube_color * color)
{
input = parse_skip(input, ' ');
input = parse_base10(input, value);
input = parse_skip(input, ' ');
input = parse_color(input, color);
return input;
}
static const char * parse_game(const char * input, int * number)
{
input = parse_match(input, "Game ");
input = parse_base10(input, number);
input = parse_skip(input, ':');
return input;
}
static const char * parse_round(const char * input, struct cube_set * set)
{
while (true) {
int value;
enum cube_color color;
input = parse_cube(input, &value, &color);
set->color[color] = value;
if (*input != ',')
break;
input++;
}
return input;
}
static void part1_set(const struct cube_set * set, void * data)
{
bool * valid = data;
bool v = set->color[red] <= 12 && set->color[green] <= 13 && set->color[blue] <= 14;
*valid &= v;
}
static int part1_sum(int game_number, void * data)
{
bool * valid = data;
int res = ((int)*valid) * game_number;
*valid = true;
return res;
}
static void part2_set(const struct cube_set * set, void * data)
{
struct cube_set * max_set = data;
if (max_set->color[red] < set->color[red])
max_set->color[red] = set->color[red];
if (max_set->color[green] < set->color[green])
max_set->color[green] = set->color[green];
if (max_set->color[blue] < set->color[blue])
max_set->color[blue] = set->color[blue];
}
static int part2_sum(int game_number, void * data)
{
struct cube_set * set = data;
int res = set->color[red] * set->color[green] * set->color[blue];
set->color[red] = 0; set->color[green] = 0; set->color[blue] = 0;
return res;
}
typedef void (* part_set_func)(const struct cube_set * set, void * data);
typedef int (* part_sum_func)(int game_number, void * data);
static int solve(const char * input, int length, part_set_func part_set, part_sum_func part_sum, void * data)
{
const char * end = input + length;
int game_number;
int sum = 0;
while (input < end) {
input = parse_game(input, &game_number);
struct cube_set set;
while (true) {
set.color[red] = 0; set.color[green] = 0; set.color[blue] = 0;
input = parse_round(input, &set);
part_set(&set, data);
if (*input != ';')
break;
input++;
}
int next_sum = sum + part_sum(game_number, data);
if (next_sum < sum)
printf("overflow\n");
sum = next_sum;
input = parse_skip(input, '\n');
}
return sum;
}
int64_t _2023_day2_part1(const char * input, int length)
{
bool valid = true;
return solve(input, length, part1_set, part1_sum, (void *)&valid);
}
int64_t _2023_day2_part2(const char * input, int length)
{
struct cube_set set;
set.color[red] = 0; set.color[green] = 0; set.color[blue] = 0;
return solve(input, length, part2_set, part2_sum, (void *)&set);
}