2024 day13
This commit is contained in:
parent
9f3fb5b481
commit
992460f534
@ -3,6 +3,8 @@
|
||||
#include "parse.h"
|
||||
#include "printf.h"
|
||||
|
||||
#include "double.h"
|
||||
|
||||
struct vec3 {
|
||||
double x;
|
||||
double y;
|
||||
@ -48,14 +50,6 @@ static bool line_line_intersection_2d(vec3 * a, vec3 * da,
|
||||
return true;
|
||||
}
|
||||
|
||||
static double int64_to_double(int64_t n)
|
||||
{
|
||||
double l = (uint32_t)n;
|
||||
double h = (int32_t)(n >> 32);
|
||||
|
||||
return h * 4294967296.0 + l;
|
||||
}
|
||||
|
||||
static const char * parse_line(const char * input, vec3 * p, vec3 * v)
|
||||
{
|
||||
int64_t x, y, z;
|
||||
@ -81,12 +75,12 @@ static const char * parse_line(const char * input, vec3 * p, vec3 * v)
|
||||
input = parse_skip(input, ' ');
|
||||
input = parse_skip(input, '\n');
|
||||
|
||||
p->x = int64_to_double(x);
|
||||
p->y = int64_to_double(y);
|
||||
p->z = int64_to_double(z);
|
||||
v->x = int64_to_double(dx);
|
||||
v->y = int64_to_double(dy);
|
||||
v->z = int64_to_double(dz);
|
||||
p->x = (double)(x);
|
||||
p->y = (double)(y);
|
||||
p->z = (double)(z);
|
||||
v->x = (double)(dx);
|
||||
v->y = (double)(dy);
|
||||
v->z = (double)(dz);
|
||||
|
||||
return input;
|
||||
}
|
||||
|
1279
2024/day13/input.txt
Normal file
1279
2024/day13/input.txt
Normal file
File diff suppressed because it is too large
Load Diff
15
2024/day13/input.txt.h
Normal file
15
2024/day13/input.txt.h
Normal file
@ -0,0 +1,15 @@
|
||||
#pragma once
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
extern uint32_t _binary_2024_day13_input_txt_start __asm("_binary_2024_day13_input_txt_start");
|
||||
extern uint32_t _binary_2024_day13_input_txt_end __asm("_binary_2024_day13_input_txt_end");
|
||||
extern uint32_t _binary_2024_day13_input_txt_size __asm("_binary_2024_day13_input_txt_size");
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
15
2024/day13/sample1.txt
Normal file
15
2024/day13/sample1.txt
Normal file
@ -0,0 +1,15 @@
|
||||
Button A: X+94, Y+34
|
||||
Button B: X+22, Y+67
|
||||
Prize: X=8400, Y=5400
|
||||
|
||||
Button A: X+26, Y+66
|
||||
Button B: X+67, Y+21
|
||||
Prize: X=12748, Y=12176
|
||||
|
||||
Button A: X+17, Y+86
|
||||
Button B: X+84, Y+37
|
||||
Prize: X=7870, Y=6450
|
||||
|
||||
Button A: X+69, Y+23
|
||||
Button B: X+27, Y+71
|
||||
Prize: X=18641, Y=10279
|
15
2024/day13/sample1.txt.h
Normal file
15
2024/day13/sample1.txt.h
Normal file
@ -0,0 +1,15 @@
|
||||
#pragma once
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
extern uint32_t _binary_2024_day13_sample1_txt_start __asm("_binary_2024_day13_sample1_txt_start");
|
||||
extern uint32_t _binary_2024_day13_sample1_txt_end __asm("_binary_2024_day13_sample1_txt_end");
|
||||
extern uint32_t _binary_2024_day13_sample1_txt_size __asm("_binary_2024_day13_sample1_txt_size");
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
124
2024/day13/solution.c
Normal file
124
2024/day13/solution.c
Normal file
@ -0,0 +1,124 @@
|
||||
#include <stdint.h>
|
||||
|
||||
#include "linear_algebra.h"
|
||||
#include "parse.h"
|
||||
|
||||
struct button {
|
||||
int x;
|
||||
int y;
|
||||
};
|
||||
|
||||
struct prize {
|
||||
int x;
|
||||
int y;
|
||||
};
|
||||
|
||||
struct claw_machine {
|
||||
struct {
|
||||
struct button a;
|
||||
struct button b;
|
||||
} button;
|
||||
struct prize prize;
|
||||
};
|
||||
|
||||
static const char * parse_button(const char * input, char c,
|
||||
int * x, int * y)
|
||||
{
|
||||
input = parse_match(input, "Button ");
|
||||
input = parse_skip(input, c);
|
||||
input = parse_match(input, ": X+");
|
||||
input = parse_base10(input, x);
|
||||
input = parse_match(input, ", Y+");
|
||||
input = parse_base10(input, y);
|
||||
input = parse_skip(input, '\n');
|
||||
return input;
|
||||
}
|
||||
|
||||
static const char * parse_prize(const char * input,
|
||||
int * x, int * y)
|
||||
{
|
||||
input = parse_match(input, "Prize: X=");
|
||||
input = parse_base10(input, x);
|
||||
input = parse_match(input, ", Y=");
|
||||
input = parse_base10(input, y);
|
||||
input = parse_skip(input, '\n');
|
||||
return input;
|
||||
}
|
||||
|
||||
static const char * parse_claw_machine(const char * input,
|
||||
struct claw_machine * cm)
|
||||
{
|
||||
input = parse_button(input, 'A', &cm->button.a.x, &cm->button.a.y);
|
||||
input = parse_button(input, 'B', &cm->button.b.x, &cm->button.b.y);
|
||||
input = parse_prize(input, &cm->prize.x, &cm->prize.y);
|
||||
return input;
|
||||
}
|
||||
|
||||
static bool is_integral(double x)
|
||||
{
|
||||
int64_t ix = x;
|
||||
double dx = ix;
|
||||
double diff = dx - x;
|
||||
return (diff < 0.00000001) && (diff > -0.00000001);
|
||||
}
|
||||
|
||||
int64_t _2024_day13_part1(const char * input, int length)
|
||||
{
|
||||
const char * end = input + length;
|
||||
|
||||
int cost = 0;
|
||||
|
||||
while (input < end) {
|
||||
struct claw_machine cm;
|
||||
input = parse_claw_machine(input, &cm);
|
||||
|
||||
double ax = cm.button.a.x;
|
||||
double ay = cm.button.a.y;
|
||||
double bx = cm.button.b.x;
|
||||
double by = cm.button.b.y;
|
||||
double x = cm.prize.x;
|
||||
double y = cm.prize.y;
|
||||
|
||||
struct double2 r = cramers_rule_2x2(ax, bx, x,
|
||||
ay, by, y);
|
||||
if (is_integral(r.x) && is_integral(r.y)) {
|
||||
int a = (int)r.x;
|
||||
int b = (int)r.y;
|
||||
cost += a * 3 + b;
|
||||
}
|
||||
}
|
||||
return cost;
|
||||
}
|
||||
|
||||
int64_t _2024_day13_part2(const char * input, int length)
|
||||
{
|
||||
const char * end = input + length;
|
||||
|
||||
int64_t cost = 0;
|
||||
|
||||
while (input < end) {
|
||||
struct claw_machine cm;
|
||||
input = parse_claw_machine(input, &cm);
|
||||
|
||||
double ax = cm.button.a.x;
|
||||
double ay = cm.button.a.y;
|
||||
double bx = cm.button.b.x;
|
||||
double by = cm.button.b.y;
|
||||
double x = cm.prize.x;
|
||||
double y = cm.prize.y;
|
||||
x += 10000000000000;
|
||||
y += 10000000000000;
|
||||
|
||||
struct double2 r = cramers_rule_2x2(ax, bx, x,
|
||||
ay, by, y);
|
||||
if (r.x == infinity || r.y == infinity) {
|
||||
continue;
|
||||
}
|
||||
if (is_integral(r.x) && is_integral(r.y)) {
|
||||
int64_t a = (int64_t)(r.x);
|
||||
int64_t b = (int64_t)(r.y);
|
||||
cost += a * 3 + b;
|
||||
}
|
||||
}
|
||||
return cost;
|
||||
}
|
3
Makefile
3
Makefile
@ -1,12 +1,13 @@
|
||||
all: $(patsubst %.cpp,%.elf,$(wildcard example/*.cpp))
|
||||
|
||||
OPT = -Og
|
||||
OPT = -O0
|
||||
|
||||
MAKEFILE_PATH := $(patsubst %/,%,$(dir $(abspath $(firstword $(MAKEFILE_LIST)))))
|
||||
CFLAGS += -I$(MAKEFILE_PATH)
|
||||
CFLAGS += -I$(MAKEFILE_PATH)/dreamcast/
|
||||
CFLAGS += -Wno-char-subscripts
|
||||
LIB ?= $(MAKEFILE_PATH)/dreamcast
|
||||
|
||||
CARCH = -m4 -ml
|
||||
|
||||
include dreamcast/base.mk
|
||||
|
8
aoc.mk
8
aoc.mk
@ -7,7 +7,8 @@ OBJ = \
|
||||
cartesian.o \
|
||||
array.o \
|
||||
memory.o \
|
||||
heap.o
|
||||
heap.o \
|
||||
linear_algebra.o
|
||||
|
||||
DREAMCAST_OBJ = \
|
||||
runner_dreamcast.o \
|
||||
@ -25,7 +26,10 @@ DREAMCAST_OBJ = \
|
||||
libgcc/_moddi3.o \
|
||||
libgcc/_udiv_qrnnd_16.o \
|
||||
libgcc/_clz.o \
|
||||
libgcc/_div_table.o
|
||||
libgcc/_div_table.o \
|
||||
libgcc/_fixdfdi.o \
|
||||
libgcc/_fixunsdfdi.o \
|
||||
libgcc/_floatdidf.o
|
||||
|
||||
include solutions.mk
|
||||
|
||||
|
18
double.h
Normal file
18
double.h
Normal file
@ -0,0 +1,18 @@
|
||||
#pragma once
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#define infinity (__builtin_inf())
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
struct double2 {
|
||||
double x;
|
||||
double y;
|
||||
};
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
@ -33,6 +33,8 @@
|
||||
#include "2024/day12/sample1.txt.h"
|
||||
#include "2024/day12/sample2.txt.h"
|
||||
#include "2024/day12/input.txt.h"
|
||||
#include "2024/day13/sample1.txt.h"
|
||||
#include "2024/day13/input.txt.h"
|
||||
|
||||
static struct start_size sample[][2] = {
|
||||
{
|
||||
@ -131,6 +133,12 @@ static struct start_size sample[][2] = {
|
||||
{ ( char *)&_binary_2024_day12_sample2_txt_start,
|
||||
(uint32_t)&_binary_2024_day12_sample2_txt_size },
|
||||
},
|
||||
{
|
||||
{ ( char *)&_binary_2024_day13_sample1_txt_start,
|
||||
(uint32_t)&_binary_2024_day13_sample1_txt_size },
|
||||
{ ( char *)&_binary_2024_day13_sample1_txt_start,
|
||||
(uint32_t)&_binary_2024_day13_sample1_txt_size },
|
||||
},
|
||||
};
|
||||
|
||||
static struct start_size input[] = {
|
||||
@ -166,4 +174,6 @@ static struct start_size input[] = {
|
||||
(uint32_t)&_binary_2024_day11_input_txt_size },
|
||||
{ ( char *)&_binary_2024_day12_input_txt_start,
|
||||
(uint32_t)&_binary_2024_day12_input_txt_size },
|
||||
{ ( char *)&_binary_2024_day13_input_txt_start,
|
||||
(uint32_t)&_binary_2024_day13_input_txt_size },
|
||||
};
|
||||
|
56
linear_algebra.c
Normal file
56
linear_algebra.c
Normal file
@ -0,0 +1,56 @@
|
||||
#include "linear_algebra.h"
|
||||
|
||||
#include "printf.h"
|
||||
//#include <stdio.h>
|
||||
|
||||
double determinant_2x2(double a, double b,
|
||||
double c, double d)
|
||||
{
|
||||
/*
|
||||
a b
|
||||
c d
|
||||
*/
|
||||
|
||||
return a * d - b * c;
|
||||
}
|
||||
|
||||
/*
|
||||
5550.00 450000000444000.00 600000000222000.00
|
||||
81081081161.08 108108108148.11
|
||||
|
||||
-3876.00 -460000000548084.00 -400000000524792.00
|
||||
118679050709.00 103199174542.00
|
||||
|
||||
-6595.00 -470000000250610.00 -690000000567170.00
|
||||
71266110727.92 104624715779.71
|
||||
|
||||
4278.00 440000001045978.00 460000000280508.00
|
||||
102851800151.00 107526881786.00
|
||||
*/
|
||||
|
||||
union di {
|
||||
double d;
|
||||
int64_t i;
|
||||
};
|
||||
|
||||
static int64_t raw_double(double n)
|
||||
{
|
||||
union di di;
|
||||
di.d = n;
|
||||
return di.i;
|
||||
}
|
||||
|
||||
struct double2 cramers_rule_2x2(double a1, double b1, double c1,
|
||||
double a2, double b2, double c2)
|
||||
{
|
||||
double denom = determinant_2x2(a1, b1,
|
||||
a2, b2);
|
||||
|
||||
double x_numer = determinant_2x2(c1, b1,
|
||||
c2, b2);
|
||||
|
||||
double y_numer = determinant_2x2(a1, c1,
|
||||
a2, c2);
|
||||
|
||||
return (struct double2){x_numer / denom, y_numer / denom};
|
||||
}
|
19
linear_algebra.h
Normal file
19
linear_algebra.h
Normal file
@ -0,0 +1,19 @@
|
||||
#pragma once
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#include "double.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
double determinant_2x2(double a, double b,
|
||||
double c, double d);
|
||||
|
||||
struct double2 cramers_rule_2x2(double a1, double b1, double c1,
|
||||
double a2, double b2, double c2);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
2
runner.c
2
runner.c
@ -38,7 +38,7 @@ bool runner_tick(struct runner_state * runner_state)
|
||||
int year = solution[ix].year;
|
||||
int day = solution[ix].day;
|
||||
|
||||
if (year != 2023 || day != 24) {
|
||||
if (year != 2024 || day != 13) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -33,6 +33,8 @@ int64_t _2024_day11_part1(const char * input, int length);
|
||||
int64_t _2024_day11_part2(const char * input, int length);
|
||||
int64_t _2024_day12_part1(const char * input, int length);
|
||||
int64_t _2024_day12_part2(const char * input, int length);
|
||||
int64_t _2024_day13_part1(const char * input, int length);
|
||||
int64_t _2024_day13_part2(const char * input, int length);
|
||||
|
||||
struct day_funcs solution[] = {
|
||||
{
|
||||
@ -115,4 +117,9 @@ struct day_funcs solution[] = {
|
||||
{_2024_day12_part1, _2024_day12_part2},
|
||||
NULL,
|
||||
},
|
||||
{
|
||||
2024, 13,
|
||||
{_2024_day13_part1, _2024_day13_part2},
|
||||
NULL,
|
||||
},
|
||||
};
|
||||
|
@ -50,4 +50,7 @@ DAY_OBJ = \
|
||||
2024/day12/sample1.txt.o \
|
||||
2024/day12/sample2.txt.o \
|
||||
2024/day12/input.txt.o \
|
||||
2024/day12/solution.o
|
||||
2024/day12/solution.o \
|
||||
2024/day13/sample1.txt.o \
|
||||
2024/day13/input.txt.o \
|
||||
2024/day13/solution.o
|
||||
|
Loading…
x
Reference in New Issue
Block a user