-
Notifications
You must be signed in to change notification settings - Fork 4
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
AoC days 18, 19, 20, 21, 22, 23 (#475)
- Loading branch information
Showing
25 changed files
with
2,093 additions
and
3 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,119 @@ | ||
import "stdlib/io.jou" | ||
import "stdlib/str.jou" | ||
import "stdlib/mem.jou" | ||
import "../grid.jou" | ||
|
||
|
||
def prepend_blank_row(grid: Grid*) -> None: | ||
assert strlen(grid->data) == (grid->width + 1)*grid->height | ||
grid->data = realloc(grid->data, grid->width + 1 + strlen(grid->data) + 1) | ||
memmove(&grid->data[grid->width + 1], grid->data, strlen(grid->data) + 1) | ||
memset(grid->data, '.', grid->width) | ||
grid->data[grid->width] = '\n' | ||
grid->height++ | ||
assert strlen(grid->data) == (grid->width + 1)*grid->height | ||
|
||
|
||
def append_blank_row(grid: Grid*) -> None: | ||
assert strlen(grid->data) == (grid->width + 1)*grid->height | ||
grid->data = realloc(grid->data, grid->width + 1 + strlen(grid->data) + 1) | ||
p = &grid->data[strlen(grid->data)] | ||
memset(p, '.', grid->width) | ||
p[grid->width] = '\n' | ||
p[grid->width + 1] = '\0' | ||
grid->height++ | ||
assert strlen(grid->data) == (grid->width + 1)*grid->height | ||
|
||
|
||
def surround_with_blanks(grid: Grid*) -> None: | ||
prepend_blank_row(grid) | ||
append_blank_row(grid) | ||
grid->transpose() | ||
prepend_blank_row(grid) | ||
append_blank_row(grid) | ||
grid->transpose() | ||
|
||
|
||
def read_input_to_grid(filename: byte*) -> Grid: | ||
f = fopen(filename, "r") | ||
assert f != NULL | ||
|
||
direction_letter: byte | ||
step_count: int | ||
color: byte[7] | ||
|
||
grid = Grid{width = 1, height = 1, data = strdup("#\n")} | ||
x = 0 | ||
y = 0 | ||
|
||
while fscanf(f, "%c %d (#%6s)\n", &direction_letter, &step_count, color) == 3: | ||
while step_count --> 0: | ||
if direction_letter == 'U': | ||
y-- | ||
elif direction_letter == 'D': | ||
y++ | ||
elif direction_letter == 'L': | ||
x-- | ||
elif direction_letter == 'R': | ||
x++ | ||
else: | ||
assert False | ||
|
||
if y == -1: | ||
prepend_blank_row(&grid) | ||
y++ | ||
if y == grid.height: | ||
append_blank_row(&grid) | ||
if x == -1: | ||
grid.transpose() | ||
prepend_blank_row(&grid) | ||
grid.transpose() | ||
x++ | ||
if x == grid.width: | ||
grid.transpose() | ||
append_blank_row(&grid) | ||
grid.transpose() | ||
|
||
grid.set([x, y], '#') | ||
|
||
fclose(f) | ||
return grid | ||
|
||
|
||
def fill_with_f(grid: Grid*) -> None: | ||
todo: int[2]* = malloc(sizeof(todo[0])) | ||
todo_len = 1 | ||
todo_alloc = 1 | ||
todo[0] = [0, 0] | ||
|
||
while todo_len > 0: | ||
point = todo[--todo_len] | ||
if not grid->is_in_bounds(point) or grid->get(point) != '.': | ||
continue | ||
|
||
grid->set(point, 'f') | ||
|
||
# Append neighbors to todo list | ||
neighbors: int[2][4] = [ | ||
[point[0], point[1]-1], | ||
[point[0], point[1]+1], | ||
[point[0]-1, point[1]], | ||
[point[0]+1, point[1]], | ||
] | ||
while todo_alloc < todo_len + 4: | ||
todo_alloc *= 2 | ||
todo = realloc(todo, sizeof(todo[0]) * todo_alloc) | ||
assert todo != NULL | ||
memcpy(&todo[todo_len], &neighbors, sizeof(neighbors)) | ||
todo_len += 4 | ||
|
||
free(todo) | ||
|
||
|
||
def main() -> int: | ||
grid = read_input_to_grid("sampleinput.txt") | ||
surround_with_blanks(&grid) | ||
fill_with_f(&grid) | ||
printf("%d\n", grid.width*grid.height - grid.count('f')) # Output: 62 | ||
free(grid.data) | ||
return 0 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,95 @@ | ||
import "stdlib/io.jou" | ||
import "stdlib/str.jou" | ||
import "stdlib/mem.jou" | ||
import "stdlib/ascii.jou" | ||
import "stdlib/math.jou" | ||
|
||
|
||
# TODO: figure out better way | ||
def parse_hex_string(s: byte*, len: int) -> int: | ||
result = 0 | ||
for i = 0; i < len; i++: | ||
result *= 16 | ||
if is_ascii_digit(s[i]): | ||
result += s[i] - '0' | ||
else: | ||
assert 'a' <= s[i] and s[i] <= 'f' | ||
result += 10 + (s[i] - 'a') | ||
return result | ||
|
||
|
||
# returned array is [-1, -1] terminated | ||
def read_input_as_points(filename: byte*, result_len: int*) -> int[2]*: | ||
result: int[2]* = malloc(sizeof(result[0])) | ||
assert result != NULL | ||
result[0] = [0, 0] | ||
*result_len = 1 | ||
|
||
f = fopen(filename, "r") | ||
assert f != NULL | ||
|
||
direction_letter: byte | ||
step_count: int | ||
hex: byte[7] | ||
x = 0 | ||
y = 0 | ||
|
||
while fscanf(f, "%c %d (#%6s)\n", &direction_letter, &step_count, hex) == 3: | ||
assert strlen(hex) == 6 | ||
step_count = parse_hex_string(hex, 5) | ||
if hex[5] == '0': | ||
# right | ||
x += step_count | ||
elif hex[5] == '1': | ||
# down | ||
y += step_count | ||
elif hex[5] == '2': | ||
# left | ||
x -= step_count | ||
elif hex[5] == '3': | ||
# up | ||
y -= step_count | ||
else: | ||
assert False | ||
|
||
result = realloc(result, sizeof(result[0]) * (*result_len + 1)) | ||
result[(*result_len)++] = [x, y] | ||
|
||
fclose(f) | ||
|
||
return result | ||
|
||
|
||
# See day 10 part 2 | ||
def polygon_area(corners: int[2]*, ncorners: int) -> long: | ||
double_area = 0L | ||
for i = 0; i < ncorners; i++: | ||
a: long = corners[i][0] | ||
b: long = corners[i][1] | ||
c: long = corners[(i+1) % ncorners][0] | ||
d: long = corners[(i+1) % ncorners][1] | ||
double_area += a*d - b*c | ||
return llabs(double_area)/2 | ||
|
||
|
||
def main() -> int: | ||
n: int | ||
points = read_input_as_points("sampleinput.txt", &n) | ||
|
||
# must end where it starts | ||
assert n > 0 | ||
assert points[0][0] == 0 | ||
assert points[0][1] == 0 | ||
assert points[n-1][0] == 0 | ||
assert points[n-1][1] == 0 | ||
|
||
path_len = 0L | ||
for i = 1; i < n; i++: | ||
path_len += abs(points[i-1][0] - points[i][0]) | ||
path_len += abs(points[i-1][1] - points[i][1]) | ||
|
||
assert path_len % 2 == 0 | ||
printf("%lld\n", polygon_area(points, n-1) + 1 + path_len/2) # Output: 952408144115 | ||
|
||
free(points) | ||
return 0 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
R 6 (#70c710) | ||
D 5 (#0dc571) | ||
L 2 (#5713f0) | ||
D 2 (#d2c081) | ||
R 2 (#59c680) | ||
D 2 (#411b91) | ||
L 5 (#8ceee2) | ||
U 2 (#caa173) | ||
L 1 (#1b58a2) | ||
U 2 (#caa171) | ||
R 2 (#7807d2) | ||
U 3 (#a77fa3) | ||
L 2 (#015232) | ||
U 2 (#7a21e3) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,148 @@ | ||
import "stdlib/ascii.jou" | ||
import "stdlib/io.jou" | ||
import "stdlib/str.jou" | ||
import "stdlib/mem.jou" | ||
|
||
|
||
class XMAS: | ||
x: int | ||
m: int | ||
a: int | ||
s: int | ||
|
||
def sum(self) -> int: | ||
return self->x + self->m + self->a + self->s | ||
|
||
|
||
class Expression: | ||
var: byte | ||
greater_than: bool # if False, this is a less than | ||
value: int | ||
|
||
def applies_to(self, xmas: XMAS) -> bool: | ||
if self->var == 'x': | ||
actual_value = xmas.x | ||
elif self->var == 'm': | ||
actual_value = xmas.m | ||
elif self->var == 'a': | ||
actual_value = xmas.a | ||
elif self->var == 's': | ||
actual_value = xmas.s | ||
else: | ||
assert False | ||
|
||
if self->greater_than: | ||
return actual_value > self->value | ||
else: | ||
return actual_value < self->value | ||
|
||
|
||
class Workflow: | ||
name: byte[10] | ||
ifs: Expression* | ||
thens: byte[10]* | ||
n_ifs_and_thens: int | ||
the_else: byte[10] | ||
|
||
def run(self, xmas: XMAS) -> byte*: | ||
for i = 0; i < self->n_ifs_and_thens; i++: | ||
if self->ifs[i].applies_to(xmas): | ||
return self->thens[i] | ||
return self->the_else | ||
|
||
|
||
def take_word(p: byte**) -> byte[10]: | ||
result: byte[10] | ||
|
||
i = 0 | ||
while is_ascii_letter(**p): | ||
assert i < sizeof(result) | ||
result[i++] = *(*p)++ | ||
|
||
assert i < sizeof(result) | ||
result[i] = '\0' | ||
return result | ||
|
||
|
||
def parse_workflow(s: byte*) -> Workflow: | ||
wf = Workflow{name = take_word(&s)} | ||
assert *s++ == '{' | ||
|
||
while True: | ||
# Check for the special else word | ||
p = s | ||
possibly_the_else = take_word(&p) | ||
if *p == '}': | ||
assert p[1] == '\0' | ||
wf.the_else = possibly_the_else | ||
return wf | ||
|
||
# "s>1188:ktb," --> var="s", op='>', num=1188, then="ktb" | ||
var = take_word(&s) | ||
op = *s++ | ||
num = atoi(s) | ||
while is_ascii_digit(*s): | ||
s++ | ||
assert *s++ == ':' | ||
then = take_word(&s) | ||
assert *s++ == ',' | ||
|
||
wf.ifs = realloc(wf.ifs, sizeof(wf.ifs[0]) * (wf.n_ifs_and_thens + 1)) | ||
wf.thens = realloc(wf.thens, sizeof(wf.thens[0]) * (wf.n_ifs_and_thens + 1)) | ||
|
||
assert strlen(var) == 1 | ||
assert op == '>' or op == '<' | ||
wf.ifs[wf.n_ifs_and_thens] = Expression{var = var[0], greater_than = (op == '>'), value = num} | ||
wf.thens[wf.n_ifs_and_thens] = then | ||
wf.n_ifs_and_thens++ | ||
|
||
|
||
def find_workflow(workflows: Workflow*, nworkflows: int, name: byte*) -> Workflow*: | ||
for i = 0; i < nworkflows; i++: | ||
if strcmp(workflows[i].name, name) == 0: | ||
return &workflows[i] | ||
assert False | ||
|
||
|
||
def run(workflows: Workflow*, nworkflows: int, xmas: XMAS) -> bool: | ||
result = "in" | ||
|
||
while True: | ||
result = find_workflow(workflows, nworkflows, result)->run(xmas) | ||
if strcmp(result, "A") == 0: | ||
return True | ||
if strcmp(result, "R") == 0: | ||
return False | ||
|
||
|
||
def main() -> int: | ||
f = fopen("sampleinput.txt", "r") | ||
assert f != NULL | ||
|
||
workflows: Workflow* = NULL | ||
nworkflows = 0 | ||
|
||
line: byte[200] | ||
while fgets(line, sizeof(line) as int, f) != NULL: | ||
trim_ascii_whitespace(line) | ||
if line[0] == '\0': | ||
# end of workflows | ||
break | ||
|
||
workflows = realloc(workflows, sizeof(workflows[0]) * (nworkflows + 1)) | ||
workflows[nworkflows++] = parse_workflow(line) | ||
|
||
xmas: XMAS | ||
result = 0 | ||
while fscanf(f, "{x=%d,m=%d,a=%d,s=%d}\n", &xmas.x, &xmas.m, &xmas.a, &xmas.s) == 4: | ||
if run(workflows, nworkflows, xmas): | ||
result += xmas.sum() | ||
|
||
printf("%d\n", result) # Output: 19114 | ||
|
||
for i = 0; i < nworkflows; i++: | ||
free(workflows[i].ifs) | ||
free(workflows[i].thens) | ||
free(workflows) | ||
fclose(f) | ||
return 0 |
Oops, something went wrong.