Skip to content

Commit

Permalink
Aoc2024 day 21 (#542)
Browse files Browse the repository at this point in the history
  • Loading branch information
Akuli authored Jan 4, 2025
1 parent 7df5770 commit a34bef6
Show file tree
Hide file tree
Showing 3 changed files with 437 additions and 0 deletions.
187 changes: 187 additions & 0 deletions examples/aoc2024/day21/part1.jou
Original file line number Diff line number Diff line change
@@ -0,0 +1,187 @@
import "stdlib/io.jou"
import "stdlib/ascii.jou"
import "stdlib/math.jou"
import "stdlib/mem.jou"
import "stdlib/str.jou"


class List:
ptr: byte[100]*
length: int
alloc: int

def append(self, string: byte*) -> None:
if self->length == self->alloc:
if self->alloc == 0:
self->alloc = 4
else:
self->alloc *= 2
self->ptr = realloc(self->ptr, sizeof(self->ptr[0]) * self->alloc)
assert self->ptr != NULL

assert strlen(string) < sizeof(self->ptr[0])
strcpy(self->ptr[self->length++], string)

def dedup(self) -> None:
i = 0
while i < self->length:
exists_before = False
for k = 0; k < i; k++:
if strcmp(self->ptr[k], self->ptr[i]) == 0:
exists_before = True
break
if exists_before:
self->ptr[k] = self->ptr[--self->length]
else:
i++


class KeyPad:
rows: byte[3][4]

def find_button(self, button_label: byte) -> int[2]:
for x = 0; x < 3; x++:
for y = 0; y < 4; y++:
if self->rows[y][x] == button_label:
return [x, y]
assert False

def goes_to_blank(self, directions: byte*) -> bool:
pos = self->find_button('A')
x = pos[0]
y = pos[1]

for p = directions; *p != '\0'; p++:
if *p == '<':
x--
elif *p == '>':
x++
elif *p == '^':
y--
elif *p == 'v':
y++
else:
assert *p == 'A'
continue

assert 0 <= x and x < 3
assert 0 <= y and y < 4
if self->rows[y][x] == ' ':
return True

return False

def get_presses(self, what_to_write: byte*) -> List:
result = List{}
result.append("")

for p = &what_to_write[0]; *p != '\0'; p++:
if p == &what_to_write[0]:
prev = 'A'
else:
prev = p[-1]

pos1 = self->find_button(prev)
pos2 = self->find_button(*p)

dx = pos2[0] - pos1[0]
dy = pos2[1] - pos1[1]

h: byte[100] = ""
v: byte[100] = ""
if dx < 0:
memset(&h, '<', abs(dx))
else:
memset(&h, '>', dx)
if dy < 0:
memset(&v, '^', abs(dy))
else:
memset(&v, 'v', dy)

result2 = List{}
for i = 0; i < result.length; i++:
# Do horizontal and vertical moves in both possible orders. This
# may affect other robots, because their arms move less if we use
# consecutive presses in the same direction.
assert strlen(result.ptr[i]) + strlen(h) + strlen(v) + strlen("A") < 100

h_then_v: byte[100] = ""
strcat(h_then_v, result.ptr[i])
strcat(h_then_v, h)
strcat(h_then_v, v)
strcat(h_then_v, "A")

v_then_h: byte[100] = ""
strcat(v_then_h, result.ptr[i])
strcat(v_then_h, v)
strcat(v_then_h, h)
strcat(v_then_h, "A")

if not self->goes_to_blank(h_then_v):
result2.append(h_then_v)
if not self->goes_to_blank(v_then_h):
result2.append(v_then_h)

free(result.ptr)
result = result2
result.dedup() # must be done right away so we don't run out of memory

return result

def get_presses_for_each(self, things_we_could_write: List) -> List:
result = List{}
for i = 0; i < things_we_could_write.length; i++:
adding = self->get_presses(things_we_could_write.ptr[i])
for k = 0; k < adding.length; k++:
result.append(adding.ptr[k])
free(adding.ptr)

result.dedup()
return result


def main() -> int:
numeric_keypad = KeyPad{rows = [
['7', '8', '9'],
['4', '5', '6'],
['1', '2', '3'],
[' ', '0', 'A'],
]}

arrow_keypad = KeyPad{rows = [
[' ', '^', 'A'],
['<', 'v', '>'],
[' ', ' ', ' '],
[' ', ' ', ' '],
]}

f = fopen("sampleinput.txt", "r")
assert f != NULL

result = 0

line: byte[20]
while fgets(line, sizeof(line) as int, f) != NULL:
trim_ascii_whitespace(line)

presses = numeric_keypad.get_presses(line)

repeat = 2
while repeat --> 0:
presses2 = arrow_keypad.get_presses_for_each(presses)
free(presses.ptr)
presses = presses2

assert presses.length != 0

shortest_len = strlen(presses.ptr[0]) as int
for i = 1; i < presses.length; i++:
shortest_len = min(shortest_len, strlen(presses.ptr[i]) as int)
free(presses.ptr)

result += shortest_len * atoi(line)

printf("%d\n", result) # Output: 126384

fclose(f)
return 0
Loading

0 comments on commit a34bef6

Please sign in to comment.