1
0

solve day 1

This commit is contained in:
Rokas Puzonas 2022-12-01 21:39:07 +02:00
commit 6709bf83e9
5 changed files with 292 additions and 0 deletions

2
.gitignore vendored Normal file
View File

@ -0,0 +1,2 @@
build
input.txt

6
Makefile Normal file
View File

@ -0,0 +1,6 @@
main: main.c
mkdir -p build
gcc -o build/main main.c -lcurl
run: main
./build/main

39
aoc.h Normal file
View File

@ -0,0 +1,39 @@
#ifndef AOC_H_
#define AOC_H_
#include <stdbool.h>
typedef int (*solution_cb)(void*);
typedef struct {
int day;
void* (*parse)(char** lines, int count);
int (*part1)(void* data);
int (*part2)(void* data);
} Solution;
// Macro magic for easy of use
#define ADD_SOLUTION(_day, parse, part1, part2) \
static Solution ptr_##parse; \
static Solution ptr_##part1; \
static Solution ptr_##part2 \
__attribute((used, section("g_solutions"))) = { \
.parse = parse, \
.part1 = part1, \
.part2 = part2, \
.day = _day \
}
#define SOLUTIONS ({ \
extern Solution __start_##g_solutions; \
&__start_##g_solutions; \
})
#define SOLUTIONS_END ({ \
extern Solution __stop_##g_solutions; \
&__stop_##g_solutions; \
})
#define SOLUTIONS_COUNT SOLUTIONS_END - SOLUTIONS
#endif //AOC_H_

85
day1.c Normal file
View File

@ -0,0 +1,85 @@
#include <stddef.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/param.h>
#include "aoc.h"
typedef struct {
int *calories;
size_t count;
} Calories;
typedef struct {
Calories *elfs;
size_t count;
} Data;
static void *parse(char **lines, int line_count) {
int elf_indexes[300] = { 0 };
int elf_count = 1;
for (int i = 1; i < line_count; i++) {
if (strlen(lines[i-1]) == 0) {
elf_indexes[elf_count++] = i;
}
}
elf_indexes[elf_count] = line_count+1;
Data *data = calloc(1, sizeof(Data));
data->elfs = calloc(elf_count, sizeof(Calories));
data->count = elf_count;
for (int i = 0; i < elf_count; i++) {
int count = (elf_indexes[i+1]-elf_indexes[i])-1;
Calories *calories = &data->elfs[i];
calories->calories = calloc(count, sizeof(int));
calories->count = count;
for (int j = 0; j < count; j++) {
int line = elf_indexes[i]+j;
calories->calories[j] = atoi(lines[line]);
}
}
return data;
}
static int part1(void *p) {
Data *data = (Data*)p;
int max_calories = 0;
for (int i = 0; i < data->count; i++) {
int calories = 0;
for (int j = 0; j < data->elfs[i].count; j++) {
calories += data->elfs[i].calories[j];
}
max_calories = MAX(max_calories, calories);
}
return max_calories;
}
static int part2(void *p) {
Data *data = (Data*)p;
int max_calories1 = 0;
int max_calories2 = 0;
int max_calories3 = 0;
for (int i = 0; i < data->count; i++) {
int calories = 0;
for (int j = 0; j < data->elfs[i].count; j++) {
calories += data->elfs[i].calories[j];
}
if (calories > max_calories1) {
max_calories3 = max_calories2;
max_calories2 = max_calories1;
max_calories1 = calories;
} else if (calories > max_calories2) {
max_calories3 = max_calories2;
max_calories2 = calories;
} else if(calories > max_calories3) {
max_calories3 = calories;
}
}
return max_calories1 + max_calories2 + max_calories3;
}
ADD_SOLUTION(1, parse, part1, part2);

160
main.c Normal file
View File

@ -0,0 +1,160 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <unistd.h>
#include <curl/curl.h>
#include <curl/easy.h>
#include "aoc.h"
#include "day1.c"
Solution *find_solution(int day)
{
for (int i = 0; i < SOLUTIONS_COUNT; i++) {
Solution *s = &SOLUTIONS[i];
if (s->day == day) {
return s;
}
}
return NULL;
}
char **read_lines(int *line_count, FILE *f)
{
*line_count = 0;
rewind(f);
while(!feof(f)){
char ch = fgetc(f);
if(ch == '\n') {
(*line_count)++;
}
}
char **lines = malloc(*line_count * sizeof(char*));
char *line;
size_t len = 0;
int i = 0;
size_t read;
rewind(f);
while ((read = getline(&line, &len, f)) != -1) {
line[read-1] = '\0';
lines[i++] = strdup(line);
}
return lines;
}
int download_input(int day, char *filename, char *session)
{
int rc = 0;
curl_global_init(CURL_GLOBAL_ALL);
FILE *f = fopen(filename, "w");
CURL *curl = curl_easy_init();
CURLcode curl_code;
if (curl) {
char *cookie_header = calloc(42 + strlen(session), sizeof(char));
sprintf(cookie_header, "Cookie: session=%s", session);
char url[81] = { 0 };
sprintf(url, "https://adventofcode.com/2022/day/%d/input", day);
struct curl_slist *chunk = NULL;
chunk = curl_slist_append(chunk, cookie_header);
curl_easy_setopt(curl, CURLOPT_HTTPHEADER, chunk);
curl_easy_setopt(curl, CURLOPT_WRITEDATA, f);
curl_easy_setopt(curl, CURLOPT_URL, &url);
curl_code = curl_easy_perform(curl);
if (curl_code == CURLE_OK) {
long http_code = 0;
curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &http_code);
if (http_code != 200) {
fprintf(stderr, "Request failed: HTTP code %ld\n", http_code);
rc = -1;
}
} else {
fprintf(stderr, "Request failed: %s\n", curl_easy_strerror(curl_code));
rc = -1;
}
curl_easy_cleanup(curl);
curl_slist_free_all(chunk);
}
end:
curl_global_cleanup();
fclose(f);
if (rc) {
remove(filename);
}
return rc;
}
void print_solutions()
{
fprintf(stderr, "Available solutions: ");
for (int i = 0; i < SOLUTIONS_COUNT; i++) {
Solution *s = &SOLUTIONS[i];
fprintf(stderr, "%d ", s->day);
}
fprintf(stderr, "\n");
}
int main(int argc, char** argv) {
if (argc < 2) {
fprintf(stderr, "Usage: %s <day> [input.txt]\n", argv[0]);
exit(1);
}
int day = atoi(argv[1]);
if (day == 0) {
fprintf(stderr, "Day number is invalid\n");
print_solutions();
exit(1);
}
Solution *solution = find_solution(day);
if (solution == NULL) {
fprintf(stderr, "Failed to find solution to %d\n", day);
print_solutions();
exit(1);
}
char *input_file = NULL;
if (argc >= 3) {
input_file = argv[2];
} else if ( access( "input.txt", F_OK ) != -1 ) {
input_file = "input.txt";
} else {
char* session = getenv("AOC_SESSION");
if (session && !download_input(1, "input.txt", session)) {
input_file = "input.txt";
} else {
fprintf(stderr, "Missing input file");
exit(1);
}
}
FILE *f = fopen(input_file, "r");
if (f == NULL) {
fprintf(stderr, "Failed to open file solution to day '%s': %s\n", input_file, strerror(errno));
return 1;
}
int line_count;
char **lines = read_lines(&line_count, f);
fclose(f);
void* parsed = solution->parse(lines, line_count);
printf("part1: %d\n", solution->part1(parsed));
printf("part2: %d\n", solution->part2(parsed));
return 0;
}