From 403a1d5269028c886fed9751085833df5893f416 Mon Sep 17 00:00:00 2001 From: Akuli Date: Tue, 17 Dec 2024 01:17:27 +0200 Subject: [PATCH] i finally undestood dijkstra's algorithm!!! --- examples/aoc2024/day16/part1.jou | 130 +++++++++++++++++++++++++ examples/aoc2024/day16/sampleinput.txt | 15 +++ 2 files changed, 145 insertions(+) create mode 100644 examples/aoc2024/day16/part1.jou create mode 100644 examples/aoc2024/day16/sampleinput.txt diff --git a/examples/aoc2024/day16/part1.jou b/examples/aoc2024/day16/part1.jou new file mode 100644 index 00000000..f2fd8b99 --- /dev/null +++ b/examples/aoc2024/day16/part1.jou @@ -0,0 +1,130 @@ +import "stdlib/io.jou" +import "stdlib/str.jou" +import "stdlib/math.jou" +import "stdlib/mem.jou" +import "../../aoc2023/grid.jou" + + +class State: + place: int[2] + direction: int[2] + score: int + + def next_states(self) -> State[3]: + x = self->place[0] + y = self->place[1] + dx = self->direction[0] + dy = self->direction[1] + + return [ + # Go forward + State{place=[x+dx, y+dy], direction=[dx, dy], score=self->score + 1}, + # Turn both ways + #State{place=[x, y], direction=[-dy, dx], score=self->score + 1000}, + #State{place=[x, y], direction=[dy, -dx], score=self->score + 1000}, + State{place=[x, y], direction=[-dy, dx], score=self->score + 1}, + State{place=[x, y], direction=[dy, -dx], score=self->score + 1}, + ] + + +def direction_to_0123(dir: int[2]) -> int: + if dir[0] == 1 and dir[1] == 0: + return 0 # right + if dir[0] == 0 and dir[1] == 1: + return 1 # down + if dir[0] == -1 and dir[1] == 0: + return 2 # left + if dir[0] == 0 and dir[1] == -1: + return 3 # up + assert False + +declare usleep(x: int) -> int +def main() -> int: + f = fopen("input", "r") + assert f != NULL + grid = read_grid_from_file(f) + fclose(f) + + int_max = 0x7fffffff # TODO: belongs to stdlib + + assert grid.width <= 150 + assert grid.height <= 150 + smallest_scores: int[4][150][150]* = malloc(sizeof(*smallest_scores)) + assert smallest_scores != NULL + + # (*smallest_scores)[x][y][direction as 0123] = shortest path to x,y counting turns + for x = 0; x < grid.width; x++: + for y = 0; y < grid.height; y++: + (*smallest_scores)[x][y] = [int_max, int_max, int_max, int_max] + + todo: State[1000] + todo[0] = State{place = grid.find_first('S'), direction = [1, 0]} + todo_len = 1 + while todo_len > 0: + # Pop from front (fast enough because todo list is short) + state = todo[0] + todo_len-- + memmove(&todo[0], &todo[1], todo_len * sizeof(todo[0])) +# state = todo[--todo_len] + + scoreptr = &(*smallest_scores)[state.place[0]][state.place[1]][direction_to_0123(state.direction)] + + # Ignore states that have ran into walls. + if grid.get(state.place) == '#': + continue + + # Ignore this state if some other todo list item has already reached + # the same place with a better score. That other todo list item will do + # a better job when discovering other paths. + if state.score < *scoreptr: + *scoreptr = state.score + next_states: State[3] = state.next_states() + assert todo_len + 3 <= sizeof(todo)/sizeof(todo[0]) + memcpy(&todo[todo_len], &next_states, sizeof(next_states)) + todo_len += 3 + + for y = 0; y < grid.height; y++: + for x = 0; x < grid.width; x++: + in_todo = False + for i = 0; i < todo_len; i++: + if todo[i].place[0] == x and todo[i].place[1] == y: + in_todo = True + if in_todo: + printf("\x1b[1;44m") # ANSI code for yellow + + if grid.get([x, y]) == '#': + putchar('#') + else: + best = min( + min( + (*smallest_scores)[x][y][0], + (*smallest_scores)[x][y][1], + ), + min( + (*smallest_scores)[x][y][2], + (*smallest_scores)[x][y][3], + ) + ) + s = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz" + if best >= strlen(s): + putchar('.') + else: + putchar(s[best]) + + if in_todo: + printf("\x1b[1;0m") # ANSI code reset + putchar('\n') + + printf("\n\n\n") + fflush(stdout) + usleep(30000) + + pos = grid.find_first('E') + printf("%d %d %d %d\n", + (*smallest_scores)[pos[0]][pos[1]][0], + (*smallest_scores)[pos[0]][pos[1]][1], + (*smallest_scores)[pos[0]][pos[1]][2], + (*smallest_scores)[pos[0]][pos[1]][3], + ) + + return 0 diff --git a/examples/aoc2024/day16/sampleinput.txt b/examples/aoc2024/day16/sampleinput.txt new file mode 100644 index 00000000..2c21676c --- /dev/null +++ b/examples/aoc2024/day16/sampleinput.txt @@ -0,0 +1,15 @@ +############### +#.......#....E# +#.#.###.#.###.# +#.....#.#...#.# +#.###.#####.#.# +#.#.#.......#.# +#.#.#####.###.# +#...........#.# +###.#.#####.#.# +#...#.....#.#.# +#.#.#.###.#.#.# +#.....#...#.#.# +#.###.#.#.#.#.# +#S..#.....#...# +###############