day8
This commit is contained in:
parent
505fee997e
commit
eef69e8406
1
Makefile
1
Makefile
@ -9,6 +9,7 @@ include dreamcast/headers.mk
|
||||
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
|
||||
|
||||
include aoc.mk
|
||||
|
4
aoc.mk
4
aoc.mk
@ -3,7 +3,9 @@ OBJ = \
|
||||
heapsort.o \
|
||||
printf.o \
|
||||
runner.o \
|
||||
unparse.o
|
||||
unparse.o \
|
||||
cartesian.o \
|
||||
array.o
|
||||
|
||||
DREAMCAST_OBJ = \
|
||||
runner_dreamcast.o \
|
||||
|
19
array.c
Normal file
19
array.c
Normal file
@ -0,0 +1,19 @@
|
||||
#include "array.h"
|
||||
|
||||
int array_sum_char(char * a, int length)
|
||||
{
|
||||
int sum = 0;
|
||||
for (int i = 0; i < length; i++) {
|
||||
sum += a[i];
|
||||
}
|
||||
return sum;
|
||||
}
|
||||
|
||||
int array_sum_int(int * a, int length)
|
||||
{
|
||||
int sum = 0;
|
||||
for (int i = 0; i < length; i++) {
|
||||
sum += a[i];
|
||||
}
|
||||
return sum;
|
||||
}
|
12
array.h
Normal file
12
array.h
Normal file
@ -0,0 +1,12 @@
|
||||
#pragma once
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
int array_sum_char(char * a, int length);
|
||||
int array_sum_int(int * a, int length);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
13
cartesian.c
Normal file
13
cartesian.c
Normal file
@ -0,0 +1,13 @@
|
||||
#include <stdbool.h>
|
||||
|
||||
#include "cartesian.h"
|
||||
|
||||
bool cartesian_inside(int width, int height,
|
||||
int x, int y)
|
||||
{
|
||||
return
|
||||
x >= 0 &&
|
||||
y >= 0 &&
|
||||
x < width &&
|
||||
y < height ;
|
||||
}
|
12
cartesian.h
Normal file
12
cartesian.h
Normal file
@ -0,0 +1,12 @@
|
||||
#pragma once
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
bool cartesian_inside(int width, int height,
|
||||
int x, int y);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
@ -3,6 +3,7 @@
|
||||
|
||||
#include "printf.h"
|
||||
#include "parse.h"
|
||||
#include "cartesian.h"
|
||||
|
||||
enum offset_type {
|
||||
N,
|
||||
@ -26,18 +27,6 @@ static char offsets[][2] = {
|
||||
[SE] = { 1, 1},
|
||||
};
|
||||
|
||||
static bool xy_inside(int width, int height,
|
||||
int x, int y)
|
||||
{
|
||||
if (y < 0 || x < 0)
|
||||
return false;
|
||||
if (x >= width)
|
||||
return false;
|
||||
if (y >= height)
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
static char get_char(const char * input,
|
||||
int stride,
|
||||
int x, int y)
|
||||
@ -55,7 +44,7 @@ static bool offset_match(const char * input,
|
||||
int str_length)
|
||||
{
|
||||
for (int i = 0; i < str_length; i++) {
|
||||
if (!xy_inside(width, height, x, y))
|
||||
if (!cartesian_inside(width, height, x, y))
|
||||
return false;
|
||||
|
||||
char c = get_char(input, stride, x, y);
|
||||
|
@ -4,6 +4,7 @@
|
||||
|
||||
#include "printf.h"
|
||||
#include "parse.h"
|
||||
#include "cartesian.h"
|
||||
|
||||
#include "solution.h"
|
||||
|
||||
@ -26,22 +27,12 @@ static struct position find_guard(const char * input, int length,
|
||||
return (struct position){x, y};
|
||||
}
|
||||
|
||||
static bool position_inside_map(int width, int height,
|
||||
int x, int y)
|
||||
{
|
||||
return
|
||||
x >= 0 &&
|
||||
y >= 0 &&
|
||||
x < width &&
|
||||
y < height ;
|
||||
}
|
||||
|
||||
static bool position_contains_obstacle(const char * input,
|
||||
int stride,
|
||||
int width, int height,
|
||||
int x, int y)
|
||||
{
|
||||
if (!position_inside_map(width, height, x, y))
|
||||
if (!cartesian_inside(width, height, x, y))
|
||||
return false;
|
||||
|
||||
char c = input[y * stride + x];
|
||||
@ -151,8 +142,8 @@ int64_t day6_part1(const char * input, int length)
|
||||
day6_state.step = false;
|
||||
*/
|
||||
|
||||
bool guard_inside_map = position_inside_map(width, height,
|
||||
guard.position.x, guard.position.y);
|
||||
bool guard_inside_map = cartesian_inside(width, height,
|
||||
guard.position.x, guard.position.y);
|
||||
if (!guard_inside_map)
|
||||
break;
|
||||
|
||||
@ -183,8 +174,8 @@ static bool speculative_obstacle_causes_loop(const char * input,
|
||||
guard.position = origin;
|
||||
|
||||
while (true) {
|
||||
bool guard_inside_map = position_inside_map(width, height,
|
||||
guard.position.x, guard.position.y);
|
||||
bool guard_inside_map = cartesian_inside(width, height,
|
||||
guard.position.x, guard.position.y);
|
||||
if (!guard_inside_map)
|
||||
break;
|
||||
|
||||
@ -227,8 +218,8 @@ int64_t day6_part2(const char * input, int length)
|
||||
for (int i = 0; i < width * height; i++) loops[i] = 0;
|
||||
|
||||
while (true) {
|
||||
bool guard_inside_map = position_inside_map(width, height,
|
||||
guard.position.x, guard.position.y);
|
||||
bool guard_inside_map = cartesian_inside(width, height,
|
||||
guard.position.x, guard.position.y);
|
||||
if (!guard_inside_map)
|
||||
break;
|
||||
|
||||
|
50
day8/input.txt
Normal file
50
day8/input.txt
Normal file
@ -0,0 +1,50 @@
|
||||
.....8............1r.....a....................O...
|
||||
.a..............4..q.........................0...9
|
||||
....a.........8...................................
|
||||
.................D.....................V0.........
|
||||
.....d............................................
|
||||
.r..........q....................................O
|
||||
..................q...........................9...
|
||||
..............D..............X..................V.
|
||||
........D................X.................0......
|
||||
.........8............X...........................
|
||||
....................J....................9..0.....
|
||||
..a..B............r..W........J...............R..Q
|
||||
......WD...q.....1..........Q..............R..V...
|
||||
.1W...................u...........................
|
||||
..............................u.............R.....
|
||||
....B..............d..c..................R........
|
||||
.............J..............X............V........
|
||||
......1...........................3...............
|
||||
......B...........d...................3...........
|
||||
............8..J.......u.....3....................
|
||||
...........4.............6........................
|
||||
.....4v.............d.......................O.....
|
||||
..........................v.2.....................
|
||||
.............................................s....
|
||||
..................4...M..W..................s.....
|
||||
......................m...........................
|
||||
...........M......................................
|
||||
..b..................c............................
|
||||
....................Co..........KQ.......O.s......
|
||||
.................C............................s...
|
||||
.......x............c............................3
|
||||
........o......A....U.....Q.........5.............
|
||||
...............U..................j...5...........
|
||||
.....K.......U................j..........2........
|
||||
.......A.v.....w.....................c...5........
|
||||
..K....................................j..........
|
||||
...............K.yk....B.............2............
|
||||
......C....b..............x...........Y...........
|
||||
.....mA..C......U.................................
|
||||
........M.....A.....................2..6...5......
|
||||
.............................7.......Y............
|
||||
.m.M......w..v....................................
|
||||
............m...........x.....Y...................
|
||||
....................k....w........................
|
||||
......b.....w..S....7.............................
|
||||
..............S..............x...........Y........
|
||||
....................S...6.........................
|
||||
.y...............S..........7.6.................9.
|
||||
o..........k...............b......................
|
||||
yo...........k....................................
|
15
day8/input.txt.h
Normal file
15
day8/input.txt.h
Normal file
@ -0,0 +1,15 @@
|
||||
#pragma once
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
extern uint32_t _binary_day8_input_txt_start __asm("_binary_day8_input_txt_start");
|
||||
extern uint32_t _binary_day8_input_txt_end __asm("_binary_day8_input_txt_end");
|
||||
extern uint32_t _binary_day8_input_txt_size __asm("_binary_day8_input_txt_size");
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
12
day8/sample1.txt
Normal file
12
day8/sample1.txt
Normal file
@ -0,0 +1,12 @@
|
||||
............
|
||||
........0...
|
||||
.....0......
|
||||
.......0....
|
||||
....0.......
|
||||
......A.....
|
||||
............
|
||||
............
|
||||
........A...
|
||||
.........A..
|
||||
............
|
||||
............
|
15
day8/sample1.txt.h
Normal file
15
day8/sample1.txt.h
Normal file
@ -0,0 +1,15 @@
|
||||
#pragma once
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
extern uint32_t _binary_day8_sample1_txt_start __asm("_binary_day8_sample1_txt_start");
|
||||
extern uint32_t _binary_day8_sample1_txt_end __asm("_binary_day8_sample1_txt_end");
|
||||
extern uint32_t _binary_day8_sample1_txt_size __asm("_binary_day8_sample1_txt_size");
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
158
day8/solution.c
Normal file
158
day8/solution.c
Normal file
@ -0,0 +1,158 @@
|
||||
#include <stdint.h>
|
||||
|
||||
#include "parse.h"
|
||||
#include "printf.h"
|
||||
#include "cartesian.h"
|
||||
#include "array.h"
|
||||
|
||||
struct position {
|
||||
char x;
|
||||
char y;
|
||||
};
|
||||
|
||||
struct antenna {
|
||||
struct position position[8];
|
||||
char count;
|
||||
};
|
||||
|
||||
#define FIRST_ANTENNA '0'
|
||||
#define LAST_ANTENNA 'z'
|
||||
#define ANTENNA_TYPES ((LAST_ANTENNA - FIRST_ANTENNA) + 1)
|
||||
|
||||
void parse_antennas(const char * input, int length, struct antenna * antennas)
|
||||
{
|
||||
int x = 0;
|
||||
int y = 0;
|
||||
for (int i = 0; i < length; i++) {
|
||||
char c = input[i];
|
||||
if (c >= FIRST_ANTENNA && c <= LAST_ANTENNA) {
|
||||
struct antenna * ant = &antennas[c - FIRST_ANTENNA];
|
||||
ant->position[ant->count++] = (struct position){x, y};
|
||||
}
|
||||
if (c == '\n') {
|
||||
x = 0;
|
||||
y += 1;
|
||||
} else {
|
||||
x += 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
struct position vector(struct position a, struct position b)
|
||||
{
|
||||
return (struct position){b.x - a.x, b.y - a.y};
|
||||
}
|
||||
|
||||
void part1_antinodes(int width, int height,
|
||||
struct position p1, struct position p2,
|
||||
char * antinodes)
|
||||
{
|
||||
struct position slope = vector(p1, p2);
|
||||
|
||||
struct position a[2] = {
|
||||
{
|
||||
p1.x - slope.x,
|
||||
p1.y - slope.y,
|
||||
},
|
||||
{
|
||||
p2.x + slope.x,
|
||||
p2.y + slope.y,
|
||||
}
|
||||
};
|
||||
|
||||
for (int k = 0; k < 2; k++) {
|
||||
if (cartesian_inside(width, height, a[k].x, a[k].y)) {
|
||||
antinodes[a[k].y * width + a[k].x] = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void interpolate_antinodes(int width,
|
||||
int height,
|
||||
struct position ant,
|
||||
struct position slope,
|
||||
char * antinodes)
|
||||
{
|
||||
int x = ant.x;
|
||||
int y = ant.y;
|
||||
while (true) {
|
||||
if (!cartesian_inside(width, height, x, y))
|
||||
break;
|
||||
|
||||
antinodes[y * width + x] = 1;
|
||||
|
||||
x -= slope.x;
|
||||
y -= slope.y;
|
||||
}
|
||||
}
|
||||
|
||||
void part2_antinodes(int width, int height,
|
||||
struct position p1, struct position p2,
|
||||
char * antinodes)
|
||||
{
|
||||
struct position slope = vector(p1, p2);
|
||||
|
||||
interpolate_antinodes(width, height, p1, (struct position){-slope.x, -slope.y}, antinodes);
|
||||
interpolate_antinodes(width, height, p2, (struct position){ slope.x, slope.y}, antinodes);
|
||||
}
|
||||
|
||||
typedef void (* part_solver)(int width, int height,
|
||||
struct position p1, struct position p2,
|
||||
char * antinodes);
|
||||
|
||||
void find_antinodes(int width, int height,
|
||||
const struct antenna * antennas,
|
||||
char * antinodes,
|
||||
part_solver func)
|
||||
{
|
||||
for (int t = FIRST_ANTENNA; t <= LAST_ANTENNA; t++) {
|
||||
const struct antenna * ant = &antennas[t - FIRST_ANTENNA];
|
||||
for (int i = 0; i < ant->count; i++) {
|
||||
for (int j = i + 1; j < ant->count; j++) {
|
||||
func(width, height,
|
||||
ant->position[i], ant->position[j],
|
||||
antinodes);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int64_t day8_part1(const char * input, int length)
|
||||
{
|
||||
int stride = parse_stride(input, length);
|
||||
int height = parse_height(input, length);
|
||||
int width = stride - 1;
|
||||
|
||||
struct antenna antennas[ANTENNA_TYPES];
|
||||
for (int i = 0; i < ANTENNA_TYPES; i++)
|
||||
antennas[i].count = 0;
|
||||
char antinodes[width * height];
|
||||
for (int i = 0; i < width * height; i++)
|
||||
antinodes[i] = 0;
|
||||
|
||||
parse_antennas(input, length, antennas);
|
||||
|
||||
find_antinodes(width, height, antennas, antinodes, part1_antinodes);
|
||||
|
||||
return array_sum_char(antinodes, width * height);
|
||||
}
|
||||
|
||||
int64_t day8_part2(const char * input, int length)
|
||||
{
|
||||
int stride = parse_stride(input, length);
|
||||
int height = parse_height(input, length);
|
||||
int width = stride - 1;
|
||||
|
||||
struct antenna antennas[ANTENNA_TYPES];
|
||||
for (int i = 0; i < ANTENNA_TYPES; i++)
|
||||
antennas[i].count = 0;
|
||||
char antinodes[width * height];
|
||||
for (int i = 0; i < width * height; i++)
|
||||
antinodes[i] = 0;
|
||||
|
||||
parse_antennas(input, length, antennas);
|
||||
|
||||
find_antinodes(width, height, antennas, antinodes, part2_antinodes);
|
||||
|
||||
return array_sum_char(antinodes, width * height);
|
||||
}
|
4
gen.sh
4
gen.sh
@ -15,12 +15,12 @@ if [ ! -z "$day" ]; then
|
||||
cat <<EOF > day${day}/solution.c
|
||||
#include <stdint.h>
|
||||
|
||||
int day${day}_part1(const char * input, int length)
|
||||
int64_t day${day}_part1(const char * input, int length)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
int day${day}_part2(const char * input, int length)
|
||||
int64_t day${day}_part2(const char * input, int length)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
@ -13,6 +13,8 @@
|
||||
#include "day6/input.txt.h"
|
||||
#include "day7/sample1.txt.h"
|
||||
#include "day7/input.txt.h"
|
||||
#include "day8/sample1.txt.h"
|
||||
#include "day8/input.txt.h"
|
||||
|
||||
static struct start_size sample[][2] = {
|
||||
{
|
||||
@ -57,6 +59,12 @@ static struct start_size sample[][2] = {
|
||||
{ ( char *)&_binary_day7_sample1_txt_start,
|
||||
(uint32_t)&_binary_day7_sample1_txt_size },
|
||||
},
|
||||
{
|
||||
{ ( char *)&_binary_day8_sample1_txt_start,
|
||||
(uint32_t)&_binary_day8_sample1_txt_size },
|
||||
{ ( char *)&_binary_day8_sample1_txt_start,
|
||||
(uint32_t)&_binary_day8_sample1_txt_size },
|
||||
},
|
||||
};
|
||||
|
||||
static struct start_size input[] = {
|
||||
@ -74,4 +82,6 @@ static struct start_size input[] = {
|
||||
(uint32_t)&_binary_day6_input_txt_size },
|
||||
{ ( char *)&_binary_day7_input_txt_start,
|
||||
(uint32_t)&_binary_day7_input_txt_size },
|
||||
{ ( char *)&_binary_day8_input_txt_start,
|
||||
(uint32_t)&_binary_day8_input_txt_size },
|
||||
};
|
||||
|
10
printf.c
10
printf.c
@ -11,6 +11,7 @@ enum format_type {
|
||||
FORMAT_BASE10_64,
|
||||
FORMAT_BASE16,
|
||||
FORMAT_STRING,
|
||||
FORMAT_CHAR,
|
||||
FORMAT_PERCENT,
|
||||
};
|
||||
|
||||
@ -48,6 +49,9 @@ static const char * parse_escape(const char * format, struct format * ft)
|
||||
case 's':
|
||||
ft->type = FORMAT_STRING;
|
||||
return format + 1;
|
||||
case 'c':
|
||||
ft->type = FORMAT_CHAR;
|
||||
return format + 1;
|
||||
case '%':
|
||||
ft->type = FORMAT_PERCENT;
|
||||
return format + 1;
|
||||
@ -105,6 +109,12 @@ void _printf(const char * format, ...)
|
||||
}
|
||||
}
|
||||
break;
|
||||
case FORMAT_CHAR:
|
||||
{
|
||||
const int c = va_arg(args, const int);
|
||||
global_output_buffer.buf[global_output_buffer.buf_ix++] = (char)c;
|
||||
}
|
||||
break;
|
||||
case FORMAT_PERCENT:
|
||||
global_output_buffer.buf[global_output_buffer.buf_ix++] = '%';
|
||||
break;
|
||||
|
2
printf.h
2
printf.h
@ -10,6 +10,8 @@ void _printf(const char * format, ...);
|
||||
#define printf(...) _printf(__VA_ARGS__)
|
||||
#endif
|
||||
|
||||
void print_char(char c);
|
||||
|
||||
struct output_buffer {
|
||||
int buf_ix;
|
||||
char buf[16 * 1024];
|
||||
|
9
runner.c
9
runner.c
@ -18,17 +18,20 @@ struct day_funcs {
|
||||
|
||||
#include "runner.inc"
|
||||
const int solution_days = (sizeof (solution)) / (sizeof (solution[0]));
|
||||
const int solution_ticks = solution_days * 2;
|
||||
|
||||
bool runner_tick(struct runner_state * runner_state)
|
||||
{
|
||||
int part = runner_state->tick % 2;
|
||||
int day = runner_state->tick / 2;
|
||||
int tick = (solution_ticks - 1) - runner_state->tick;
|
||||
|
||||
if (day >= solution_days) {
|
||||
if (tick < 0) {
|
||||
runner_state->want_render = false;
|
||||
return true;
|
||||
}
|
||||
|
||||
int part = tick % 2;
|
||||
int day = tick / 2;
|
||||
|
||||
runner_state->want_render = solution[day].render != NULL;
|
||||
|
||||
char * buf;
|
||||
|
@ -15,6 +15,8 @@ void day6_render(const struct font * font,
|
||||
const void * maple_ft0_data);
|
||||
int64_t day7_part1(const char * input, int length);
|
||||
int64_t day7_part2(const char * input, int length);
|
||||
int64_t day8_part1(const char * input, int length);
|
||||
int64_t day8_part2(const char * input, int length);
|
||||
|
||||
struct day_funcs solution[] = {
|
||||
{
|
||||
@ -45,4 +47,8 @@ struct day_funcs solution[] = {
|
||||
{day7_part1, day7_part2},
|
||||
NULL,
|
||||
},
|
||||
{
|
||||
{day8_part1, day8_part2},
|
||||
NULL,
|
||||
},
|
||||
};
|
||||
|
@ -444,3 +444,11 @@ int main()
|
||||
|
||||
serial::string("return\n");
|
||||
}
|
||||
|
||||
|
||||
extern "C"
|
||||
void print_char(char c)
|
||||
{
|
||||
global_output_buffer.buf[global_output_buffer.buf_ix++] = c;
|
||||
serial::character(c);
|
||||
}
|
||||
|
@ -21,4 +21,7 @@ DAY_OBJ = \
|
||||
day6/solution.o \
|
||||
day7/sample1.txt.o \
|
||||
day7/input.txt.o \
|
||||
day7/solution.o
|
||||
day7/solution.o \
|
||||
day8/sample1.txt.o \
|
||||
day8/input.txt.o \
|
||||
day8/solution.o
|
||||
|
Loading…
x
Reference in New Issue
Block a user