solve day 13
This commit is contained in:
parent
a3d746e285
commit
861826d3ff
1
aoc.h
1
aoc.h
@ -2,6 +2,7 @@
|
|||||||
#define AOC_H_
|
#define AOC_H_
|
||||||
|
|
||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
typedef void (*solution_cb)(void*);
|
typedef void (*solution_cb)(void*);
|
||||||
typedef void* (*parse_cb)(char** lines, int count);
|
typedef void* (*parse_cb)(char** lines, int count);
|
||||||
|
3
day12.c
3
day12.c
@ -1,12 +1,11 @@
|
|||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
#include <stddef.h>
|
#include <stddef.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
|
#include "aoc.h"
|
||||||
#include "types.h"
|
#include "types.h"
|
||||||
#include "point.h"
|
#include "point.h"
|
||||||
#include "aoc.h"
|
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
u8 *map;
|
u8 *map;
|
||||||
|
230
day13.c
Normal file
230
day13.c
Normal file
@ -0,0 +1,230 @@
|
|||||||
|
#include <assert.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <sys/param.h>
|
||||||
|
|
||||||
|
#include "types.h"
|
||||||
|
#include "aoc.h"
|
||||||
|
|
||||||
|
typedef struct day13_packet *day13_packet_ptr;
|
||||||
|
|
||||||
|
struct day13_packet {
|
||||||
|
bool is_number;
|
||||||
|
union {
|
||||||
|
u8 number;
|
||||||
|
struct {
|
||||||
|
day13_packet_ptr list;
|
||||||
|
size_t list_size;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
struct day13_packet left;
|
||||||
|
struct day13_packet right;
|
||||||
|
} day13_packet_pair;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
day13_packet_pair* pairs;
|
||||||
|
size_t count;
|
||||||
|
} day13_packet_pairs;
|
||||||
|
|
||||||
|
static bool day13_is_digit(char c)
|
||||||
|
{
|
||||||
|
return '0' <= c && c <= '9';
|
||||||
|
}
|
||||||
|
|
||||||
|
static size_t day13_parse_packet(struct day13_packet *result, char *packet)
|
||||||
|
{
|
||||||
|
size_t bytes_read = 0;
|
||||||
|
|
||||||
|
if (packet[0] == '[') {
|
||||||
|
bytes_read++;
|
||||||
|
result->is_number = false;
|
||||||
|
result->list_size = 0;
|
||||||
|
result->list = NULL;
|
||||||
|
if (packet[1] != ']') {
|
||||||
|
while (true) {
|
||||||
|
result->list = realloc(result->list, sizeof(struct day13_packet)*(result->list_size+1));
|
||||||
|
bytes_read += day13_parse_packet(&result->list[result->list_size], packet+bytes_read);
|
||||||
|
result->list_size++;
|
||||||
|
|
||||||
|
if (packet[bytes_read] == ',') {
|
||||||
|
bytes_read++;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (packet[bytes_read] == ']') break;
|
||||||
|
assert(false && "fuck");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
bytes_read++;
|
||||||
|
} else if (day13_is_digit(packet[0])) {
|
||||||
|
bytes_read++;
|
||||||
|
result->is_number = true;
|
||||||
|
result->number = (packet[0] - '0');
|
||||||
|
for (int i = 1; i < strlen(packet); i++) {
|
||||||
|
if (!day13_is_digit(packet[i])) break;
|
||||||
|
result->number *= 10;
|
||||||
|
result->number += (packet[i] - '0');
|
||||||
|
bytes_read++;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
assert(false && "Failed to parse packet");
|
||||||
|
}
|
||||||
|
|
||||||
|
return bytes_read;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void printf_day13_packet(struct day13_packet *packet)
|
||||||
|
{
|
||||||
|
if (packet->is_number) {
|
||||||
|
printf("%d", packet->number);
|
||||||
|
} else {
|
||||||
|
printf("[");
|
||||||
|
if (packet->list_size > 0) {
|
||||||
|
for (int i = 0; i < packet->list_size-1; i++) {
|
||||||
|
printf_day13_packet(&packet->list[i]);
|
||||||
|
printf(",");
|
||||||
|
}
|
||||||
|
printf_day13_packet(&packet->list[packet->list_size-1]);
|
||||||
|
}
|
||||||
|
printf("]");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void *day13_parse(char **lines, int line_count)
|
||||||
|
{
|
||||||
|
size_t n = (line_count+1)/3;
|
||||||
|
day13_packet_pair *pairs = malloc(sizeof(day13_packet_pair)*n);
|
||||||
|
|
||||||
|
for (int i = 0; i < n; i++)
|
||||||
|
{
|
||||||
|
day13_parse_packet(&pairs[i].left , lines[3*i+0]);
|
||||||
|
day13_parse_packet(&pairs[i].right, lines[3*i+1]);
|
||||||
|
}
|
||||||
|
|
||||||
|
day13_packet_pairs *result = malloc(sizeof(day13_packet_pairs));
|
||||||
|
result->pairs = pairs;
|
||||||
|
result->count = n;
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Return values:
|
||||||
|
// -1 = left is lower
|
||||||
|
// 0 = equal
|
||||||
|
// 1 = right is lower
|
||||||
|
static int day13_compare(struct day13_packet *left, struct day13_packet *right)
|
||||||
|
{
|
||||||
|
if (left->is_number && right->is_number) {
|
||||||
|
if (left->number == right->number) {
|
||||||
|
return 0;
|
||||||
|
} else if (left->number < right->number) {
|
||||||
|
return -1;
|
||||||
|
} else {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
} else if (!left->is_number && !right->is_number) {
|
||||||
|
for (int i = 0; i < MIN(left->list_size, right->list_size); i++) {
|
||||||
|
int item_result = day13_compare(&left->list[i], &right->list[i]);
|
||||||
|
if (item_result != 0) {
|
||||||
|
return item_result;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (left->list_size < right->list_size) {
|
||||||
|
return -1;
|
||||||
|
} else if (left->list_size > right->list_size) {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
} else if (left->is_number && !right->is_number) {
|
||||||
|
struct day13_packet packet = {
|
||||||
|
.is_number = false,
|
||||||
|
.list = left,
|
||||||
|
.list_size = 1
|
||||||
|
};
|
||||||
|
return day13_compare(&packet, right);
|
||||||
|
} else if (!left->is_number && right->is_number) {
|
||||||
|
struct day13_packet packet = {
|
||||||
|
.is_number = false,
|
||||||
|
.list = right,
|
||||||
|
.list_size = 1
|
||||||
|
};
|
||||||
|
return day13_compare(left, &packet);
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void day13_part1(void *p)
|
||||||
|
{
|
||||||
|
day13_packet_pairs *pairs = (day13_packet_pairs*)p;
|
||||||
|
int result = 0;
|
||||||
|
for (int i = 0; i < pairs->count; i++) {
|
||||||
|
if (day13_compare(&pairs->pairs[i].left, &pairs->pairs[i].right) == -1) {
|
||||||
|
result += (i+1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
printf("Answer: %d\n", result);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int day13_find_packet(struct day13_packet **packets, size_t count, struct day13_packet *target)
|
||||||
|
{
|
||||||
|
for (int i = 0; i < count; i++) {
|
||||||
|
if (packets[i] == target) {
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void day13_swap(struct day13_packet **A, struct day13_packet **B)
|
||||||
|
{
|
||||||
|
struct day13_packet *C = *A;
|
||||||
|
*A = *B;
|
||||||
|
*B = C;
|
||||||
|
}
|
||||||
|
|
||||||
|
// bubble sort
|
||||||
|
static void day13_sort_packets(struct day13_packet **packets, size_t count)
|
||||||
|
{
|
||||||
|
for (int i = 0; i < count-1; i++) {
|
||||||
|
for (int j = i+1; j < count; j++) {
|
||||||
|
int cmp = day13_compare(packets[i], packets[j]);
|
||||||
|
if (cmp == 1) {
|
||||||
|
day13_swap(&packets[i], &packets[j]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void day13_part2(void *p)
|
||||||
|
{
|
||||||
|
day13_packet_pairs *pairs = (day13_packet_pairs*)p;
|
||||||
|
|
||||||
|
size_t packet_count = pairs->count*2 + 2;
|
||||||
|
struct day13_packet **packets = malloc(sizeof(struct day13_packet*)*packet_count);
|
||||||
|
|
||||||
|
// insert divider [[2]]
|
||||||
|
struct day13_packet divider1;
|
||||||
|
day13_parse_packet(÷r1, "[[2]]");
|
||||||
|
packets[0] = ÷r1;
|
||||||
|
|
||||||
|
// insert divider [[6]]
|
||||||
|
struct day13_packet divider2;
|
||||||
|
day13_parse_packet(÷r2, "[[6]]");
|
||||||
|
packets[1] = ÷r2;
|
||||||
|
|
||||||
|
// insert packets from `pairs.pairs`
|
||||||
|
for (int i = 0; i < pairs->count; i++) {
|
||||||
|
packets[2 + i*2+0] = &pairs->pairs[i].left;
|
||||||
|
packets[2 + i*2+1] = &pairs->pairs[i].right;
|
||||||
|
}
|
||||||
|
|
||||||
|
day13_sort_packets(packets, packet_count);
|
||||||
|
|
||||||
|
int divider1_idx = day13_find_packet(packets, packet_count, ÷r1);
|
||||||
|
int divider2_idx = day13_find_packet(packets, packet_count, ÷r2);
|
||||||
|
int answer = (divider1_idx+1) * (divider2_idx+1);
|
||||||
|
printf("Answer: %d\n", answer);
|
||||||
|
}
|
||||||
|
|
||||||
|
ADD_SOLUTION(13, day13_parse, day13_part1, day13_part2);
|
5
main.c
5
main.c
@ -21,6 +21,7 @@
|
|||||||
#include "day10.c"
|
#include "day10.c"
|
||||||
#include "day11.c"
|
#include "day11.c"
|
||||||
#include "day12.c"
|
#include "day12.c"
|
||||||
|
#include "day13.c"
|
||||||
|
|
||||||
Solution *find_solution(int day)
|
Solution *find_solution(int day)
|
||||||
{
|
{
|
||||||
@ -170,10 +171,12 @@ int main(int argc, char** argv) {
|
|||||||
|
|
||||||
fclose(f);
|
fclose(f);
|
||||||
|
|
||||||
|
uint64_t start_time = get_current_time_us();
|
||||||
void* parsed = solution->parse(lines, line_count);
|
void* parsed = solution->parse(lines, line_count);
|
||||||
|
printf("Parsing took %ldus\n", get_current_time_us() - start_time);
|
||||||
|
|
||||||
printf("part1:\n");
|
printf("part1:\n");
|
||||||
uint64_t start_time = get_current_time_us();
|
start_time = get_current_time_us();
|
||||||
solution->part1(parsed);
|
solution->part1(parsed);
|
||||||
printf("Part 1 took %ldus\n\n", get_current_time_us() - start_time);
|
printf("Part 1 took %ldus\n\n", get_current_time_us() - start_time);
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user