advent-of-c-ode/day2/day2.c

198 lines
3.8 KiB
C

#include <ctype.h>
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "../libs/buffered_reader.h"
#include "../libs/data_structures.h"
#define MAX_RED 12
#define MAX_GREEN 13
#define MAX_BLUE 14
int decodea(char *str);
int decodeb(char *str);
int get_color(const char *str);
bool validate_round(char *str, int dice[]);
// SEPARATORS
const char *GAME_SEP = ":";
const char *COLOR_SEP = ",";
const char *ROUND_SEP = ";";
// COLOR
const char *RED = "red";
const char *GREEN = "green";
const char *BLUE = "blue";
list *stack;
enum Color { Red = 0, Green = 1, Blue = 2 };
int main(int argc, char *argv[]) {
if (argc < 3) {
printf("usage: day2 INPUT_FILE a|b\n");
exit(1);
}
char part = *argv[2];
filelines *lines = flines(argv[1]);
if (lines == NULL) {
printf("Failed to read file");
exit(1);
}
// init stack
initList(&stack);
int sum = 0;
for (int i = 0; i < lines->size; i++) {
int d = 0;
//based on cli input change function
switch (part) {
case 'a':
d = decodea(get(lines, i));
break;
case 'b':
d = decodeb(get(lines, i));
break;
}
/*
if (d == 0) {
printf("^^^^ Game %d ^^^^^\n", i + 1);
} else {
printf("---- Game %d -----\n", i + 1);
}
*/
sum += d;
}
printf("Sum: %d\n", sum);
}
int decodea(char *str) {
// find semicolon
int game_split = strcspn(str, GAME_SEP);
char *game_str = str + game_split + 1;
if (!*game_str || str == game_str) {
printf("Could not find game separator.\n");
exit(1);
}
// parse colors
char *token;
token = strtok(game_str, ";");
filelines *rounds;
initFileLines(&rounds);
// Get rounds
while (token) {
insert(rounds, token);
token = strtok(NULL, ";");
}
// validate rounds
for (int i = 0; i < rounds->size; i++) {
int dice[] = {0, 0, 0};
if (!validate_round(get(rounds, i), dice)) {
return 0;
}
}
freeLines(rounds);
clears(stack);
int space_index = strcspn(str, " ");
for (int i = space_index + 1; i < game_split; i++) {
pushs(stack, *(str + i));
}
return atoi(contents(stack));
}
int decodeb(char *str) {
// find semicolon
int game_split = strcspn(str, GAME_SEP);
char *game_str = str + game_split + 1;
if (!*game_str || str == game_str) {
printf("Could not find game separator.\n");
exit(1);
}
// parse colors
char *token;
token = strtok(game_str, ";");
filelines *rounds;
initFileLines(&rounds);
// Get rounds
while (token) {
insert(rounds, token);
token = strtok(NULL, ";");
}
int min[] = {0,0,0};
// validate rounds
for (int i = 0; i < rounds->size; i++) {
int dice[] = {0, 0, 0};
validate_round(get(rounds, i), dice);
min[Red] = dice[Red] >= min[Red] ? dice[Red] : min[Red];
min[Green] = dice[Green] >= min[Green] ? dice[Green] : min[Green];
min[Blue] = dice[Blue] >= min[Blue] ? dice[Blue] : min[Blue];
}
return min[Red] * min[Green] * min[Blue];
}
int get_color(const char *str) {
if (strstr(str, RED)) {
return Red;
}
if (strstr(str, GREEN)) {
return Green;
}
if (strstr(str, BLUE)) {
return Blue;
}
return -1;
}
bool validate_round(char *str, int dice[]) {
list *color_list;
initList(&color_list);
char *token;
token = strtok(str, ",");
while (token) {
// trim leading whitespace
while (isspace(*token))
token++;
// printf("%s,", token);
// actually do the stuff
clears(color_list);
char *c = token;
while (c) {
if (isspace(*c)) {
break;
}
pushs(color_list, *c);
c++;
}
enum Color color = get_color(token);
dice[color] += atoi(contents(color_list));
token = strtok(NULL, ",");
}
// printf("\n");
freelist(color_list);
return dice[Red] <= MAX_RED && dice[Green] <= MAX_GREEN &&
dice[Blue] <= MAX_BLUE;
}