Day 2 Complete
* Added puzzle_input.c to help handle common input parsing * Accepts a parser callback function to do the day specific parsing * Updated day_1 to use new parsing systemmain
parent
a02302a516
commit
d853ba0b10
|
@ -3,4 +3,4 @@ project(aoc_2021 C)
|
||||||
|
|
||||||
set(CMAKE_C_STANDARD 99)
|
set(CMAKE_C_STANDARD 99)
|
||||||
|
|
||||||
add_executable(aoc_2021 src/main.c src/day_1.c src/day.h)
|
add_executable(aoc_2021 src/main.c src/day_1.c src/day.h src/day_2.c src/puzzle_input.c src/puzzle_input.h)
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -2,5 +2,6 @@
|
||||||
#define AOC_2021_DAY_H
|
#define AOC_2021_DAY_H
|
||||||
|
|
||||||
int day_1();
|
int day_1();
|
||||||
|
int day_2();
|
||||||
|
|
||||||
#endif //AOC_2021_DAY_H
|
#endif //AOC_2021_DAY_H
|
||||||
|
|
90
src/day_1.c
90
src/day_1.c
|
@ -4,77 +4,11 @@
|
||||||
#include <limits.h>
|
#include <limits.h>
|
||||||
|
|
||||||
#include "day.h"
|
#include "day.h"
|
||||||
|
#include "puzzle_input.h"
|
||||||
|
|
||||||
#define DATA_MAX_LEN 2048
|
#define DATA_MAX_LEN 2048
|
||||||
|
|
||||||
int parse_long_from_buff(char * buffer, int64_t * val) {
|
static void part_1(const int64_t * data, uint16_t data_len) {
|
||||||
*val = strtol(buffer, NULL, 16);
|
|
||||||
|
|
||||||
if (*val == LONG_MIN || *val == LONG_MAX) {
|
|
||||||
return -2;
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
int read_input(const char * file_path, int64_t *data, uint16_t max_len) {
|
|
||||||
char buffer[64];
|
|
||||||
int c;
|
|
||||||
int ret = 0;
|
|
||||||
FILE * file = fopen(file_path, "r");
|
|
||||||
int data_ndx = 0;
|
|
||||||
|
|
||||||
if (file != NULL) {
|
|
||||||
int buffer_ndx = 0;
|
|
||||||
while ((c = fgetc(file)) != EOF) {
|
|
||||||
if (c == '\n') {
|
|
||||||
buffer[buffer_ndx] = 0;
|
|
||||||
|
|
||||||
ret = parse_long_from_buff(buffer, &data[data_ndx]);
|
|
||||||
|
|
||||||
if (ret < 0) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
data_ndx++;
|
|
||||||
|
|
||||||
if (data_ndx >= max_len) {
|
|
||||||
ret = -3;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
buffer_ndx = 0;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
buffer[buffer_ndx] = (char)c;
|
|
||||||
buffer_ndx++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (buffer_ndx > 0) {
|
|
||||||
ret = parse_long_from_buff(buffer, &data[data_ndx]);
|
|
||||||
|
|
||||||
if (ret == 0) {
|
|
||||||
data_ndx++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
ret = -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (ret == 0) {
|
|
||||||
ret = data_ndx;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (file != NULL) {
|
|
||||||
fclose(file);
|
|
||||||
}
|
|
||||||
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
void part_1(const int64_t * data, uint16_t data_len) {
|
|
||||||
int64_t last_value;
|
int64_t last_value;
|
||||||
int16_t inc_count = 0;
|
int16_t inc_count = 0;
|
||||||
|
|
||||||
|
@ -89,7 +23,7 @@ void part_1(const int64_t * data, uint16_t data_len) {
|
||||||
printf("PART 1: %d values increased!\n", inc_count);
|
printf("PART 1: %d values increased!\n", inc_count);
|
||||||
}
|
}
|
||||||
|
|
||||||
void part_2(const int64_t * data, uint16_t data_len) {
|
static void part_2(const int64_t * data, uint16_t data_len) {
|
||||||
int64_t old_window_sum;
|
int64_t old_window_sum;
|
||||||
int64_t window_sum;
|
int64_t window_sum;
|
||||||
int16_t inc_count = 0;
|
int16_t inc_count = 0;
|
||||||
|
@ -111,19 +45,19 @@ void part_2(const int64_t * data, uint16_t data_len) {
|
||||||
|
|
||||||
int day_1() {
|
int day_1() {
|
||||||
char * path = "../inputs/day_1.txt";
|
char * path = "../inputs/day_1.txt";
|
||||||
int data_len;
|
uint16_t data_len;
|
||||||
int64_t data[DATA_MAX_LEN];
|
int64_t data[DATA_MAX_LEN];
|
||||||
|
|
||||||
data_len = read_input(path, data, DATA_MAX_LEN);
|
parse_ret_t res = read_input(path, (void *)data, DATA_MAX_LEN, parse_long_from_buff, &data_len);
|
||||||
|
|
||||||
if (data_len < 0) {
|
if (res == PARSER_OK) {
|
||||||
printf("read_input returned an error: %d\n", data_len);
|
part_1(data, data_len);
|
||||||
return data_len;
|
part_2(data, data_len);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
printf("Failed to parse data: %d\n", res);
|
||||||
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
part_1(data, data_len);
|
|
||||||
|
|
||||||
part_2(data, data_len);
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
|
@ -0,0 +1,120 @@
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <limits.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#include "puzzle_input.h"
|
||||||
|
#include "day.h"
|
||||||
|
|
||||||
|
#define MAX_COURSE_SIZE 1024
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
FORWARD,
|
||||||
|
DOWN ,
|
||||||
|
UP,
|
||||||
|
} course_dir_t;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
course_dir_t dir;
|
||||||
|
int64_t units;
|
||||||
|
} course_entry_t;
|
||||||
|
|
||||||
|
int parse_course_entry(char * buffer, void * data, uint16_t data_index) {
|
||||||
|
char * save_ptr;
|
||||||
|
char * dir_str = strtok_r(buffer, " ", &save_ptr);
|
||||||
|
char * unit_str = strtok_r(NULL, " ", &save_ptr);
|
||||||
|
parse_ret_t ret;
|
||||||
|
int64_t units;
|
||||||
|
|
||||||
|
ret = parse_long(unit_str, &units);
|
||||||
|
|
||||||
|
if (ret == PARSER_OK) {
|
||||||
|
course_dir_t dir;
|
||||||
|
|
||||||
|
switch (dir_str[0]) {
|
||||||
|
case 'f':
|
||||||
|
dir = FORWARD;
|
||||||
|
break;
|
||||||
|
case 'd':
|
||||||
|
dir = DOWN;
|
||||||
|
break;
|
||||||
|
case 'u':
|
||||||
|
dir = UP;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
ret = PARSER_INVALID;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ret == PARSER_OK) {
|
||||||
|
course_entry_t entry = {
|
||||||
|
.dir = dir,
|
||||||
|
.units = units
|
||||||
|
};
|
||||||
|
|
||||||
|
course_entry_t *course = (course_entry_t *)data;
|
||||||
|
course[data_index] = entry;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void part_1(course_entry_t * course, uint16_t course_len) {
|
||||||
|
int64_t horizontal_pos = 0;
|
||||||
|
int64_t depth = 0;
|
||||||
|
|
||||||
|
for (int course_ndx = 0; course_ndx < course_len; course_ndx++) {
|
||||||
|
int dir_sign = 1;
|
||||||
|
switch (course[course_ndx].dir) {
|
||||||
|
case FORWARD:
|
||||||
|
horizontal_pos += course[course_ndx].units;
|
||||||
|
break;
|
||||||
|
case UP:
|
||||||
|
dir_sign = -1;
|
||||||
|
case DOWN:
|
||||||
|
depth += dir_sign*course[course_ndx].units;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
printf("PART 1: Final Horizontal * Final Depth = %ld\n", horizontal_pos*depth);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void part_2(course_entry_t * course, uint16_t course_len) {
|
||||||
|
int64_t horizontal_pos = 0;
|
||||||
|
int64_t depth = 0;
|
||||||
|
int64_t aim = 0;
|
||||||
|
|
||||||
|
for (int course_ndx = 0; course_ndx < course_len; course_ndx++) {
|
||||||
|
int dir_sign = 1;
|
||||||
|
int64_t units = course[course_ndx].units;
|
||||||
|
switch (course[course_ndx].dir) {
|
||||||
|
case FORWARD:
|
||||||
|
horizontal_pos += units;
|
||||||
|
depth += units * aim;
|
||||||
|
break;
|
||||||
|
case UP:
|
||||||
|
dir_sign = -1;
|
||||||
|
case DOWN:
|
||||||
|
aim += dir_sign*units;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
printf("PART 2: Final Horizontal * Final Depth = %ld\n", horizontal_pos*depth);
|
||||||
|
}
|
||||||
|
|
||||||
|
int day_2() {
|
||||||
|
course_entry_t course[MAX_COURSE_SIZE];
|
||||||
|
uint16_t data_len;
|
||||||
|
parse_ret_t res = read_input("../inputs/day_2.txt", (void *)course, MAX_COURSE_SIZE, parse_course_entry, &data_len);
|
||||||
|
|
||||||
|
if (res == PARSER_OK) {
|
||||||
|
part_1(course, data_len);
|
||||||
|
part_2(course, data_len);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
printf("Failed to parse data: %d", res);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
|
@ -19,6 +19,9 @@ int main(int argc, char * argv[]) {
|
||||||
case 1:
|
case 1:
|
||||||
day_1();
|
day_1();
|
||||||
break;
|
break;
|
||||||
|
case 2:
|
||||||
|
day_2();
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
printf("Invalid day ding dong!\n");
|
printf("Invalid day ding dong!\n");
|
||||||
return -2;
|
return -2;
|
||||||
|
|
|
@ -0,0 +1,87 @@
|
||||||
|
#include <limits.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include "puzzle_input.h"
|
||||||
|
|
||||||
|
parse_ret_t parse_long(char * buffer, int64_t *val) {
|
||||||
|
*val = strtol(buffer, NULL, 10);
|
||||||
|
|
||||||
|
if (*val == LONG_MIN || *val == LONG_MAX) {
|
||||||
|
return PARSER_INVALID;
|
||||||
|
}
|
||||||
|
|
||||||
|
return PARSER_OK;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
parse_ret_t parse_long_from_buff(char * buffer, void * data, uint16_t index) {
|
||||||
|
uint64_t * int_data = (uint64_t *)data;
|
||||||
|
uint64_t val;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
ret = parse_long(buffer, (int64_t *)&val);
|
||||||
|
|
||||||
|
if (ret != PARSER_OK) {
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
int_data[index] = val;
|
||||||
|
|
||||||
|
return PARSER_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
parse_ret_t read_input(const char * file_path, void * data, uint16_t max_len, input_parser_t parser, uint16_t * len) {
|
||||||
|
char buffer[64];
|
||||||
|
int c;
|
||||||
|
int ret = 0;
|
||||||
|
FILE * file = fopen(file_path, "r");
|
||||||
|
uint16_t data_ndx = 0;
|
||||||
|
|
||||||
|
if (file != NULL) {
|
||||||
|
int buffer_ndx = 0;
|
||||||
|
while ((c = fgetc(file)) != EOF) {
|
||||||
|
if (c == '\n') {
|
||||||
|
buffer[buffer_ndx] = 0;
|
||||||
|
|
||||||
|
ret = parser(buffer, data, data_ndx);
|
||||||
|
|
||||||
|
if (ret != PARSER_OK) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
data_ndx++;
|
||||||
|
|
||||||
|
if (data_ndx >= max_len) {
|
||||||
|
ret = PARSER_RANGE_OVERFLOW;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
buffer_ndx = 0;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
buffer[buffer_ndx] = (char)c;
|
||||||
|
buffer_ndx++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (buffer_ndx > 0) {
|
||||||
|
ret = parser(buffer, data, data_ndx);
|
||||||
|
|
||||||
|
if (ret == PARSER_OK) {
|
||||||
|
data_ndx++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
ret = PARSE_FILE_ERR;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (file != NULL) {
|
||||||
|
fclose(file);
|
||||||
|
}
|
||||||
|
|
||||||
|
*len = data_ndx;
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
|
@ -0,0 +1,23 @@
|
||||||
|
#ifndef AOC_2021_PUZZLE_INPUT_H
|
||||||
|
#define AOC_2021_PUZZLE_INPUT_H
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
PARSER_OK = 0,
|
||||||
|
PARSER_INVALID = -1,
|
||||||
|
PARSER_RANGE_OVERFLOW = -2,
|
||||||
|
PARSE_FILE_ERR = -3,
|
||||||
|
} parse_ret_t;
|
||||||
|
|
||||||
|
typedef parse_ret_t (*input_parser_t)(char * buffer, void * data, uint16_t index);
|
||||||
|
|
||||||
|
parse_ret_t read_input(const char * file_path, void * data, uint16_t max_len, input_parser_t parser, uint16_t * len);
|
||||||
|
|
||||||
|
// Parsers
|
||||||
|
parse_ret_t parse_long_from_buff(char * buffer, void * data, uint16_t index);
|
||||||
|
|
||||||
|
//Helpers
|
||||||
|
parse_ret_t parse_long(char * buffer, int64_t * val);
|
||||||
|
|
||||||
|
#endif //AOC_2021_PUZZLE_INPUT_H
|
Loading…
Reference in New Issue