solve day 1
This commit is contained in:
commit
6709bf83e9
2
.gitignore
vendored
Normal file
2
.gitignore
vendored
Normal file
@ -0,0 +1,2 @@
|
||||
build
|
||||
input.txt
|
6
Makefile
Normal file
6
Makefile
Normal 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
39
aoc.h
Normal 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
85
day1.c
Normal 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
160
main.c
Normal 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;
|
||||
}
|
Loading…
Reference in New Issue
Block a user