--- /dev/null
+#load "core/std"
+
+use package core
+
+ugh :: struct { x, y: i32; cost: i32; dist: i32; };
+#operator == (u1, u2: ugh) => u1.x == u2.x && u1.y == u2.y;
+
+pos :: struct { x, y: i32; }
+#match hash.to_u32 (p: pos) => p.x * 12462341 + p.y * 1231247823;
+#operator == (p1, p2: pos) => p1.x == p2.x && p1.y == p2.y;
+
+main :: (args) => {
+ for file: os.with_file("./tests/aoc-2021/input/day15.txt") {
+ reader := io.reader_make(file);
+
+ cells: [..] u8;
+ height := 0;
+ while !io.reader_empty(^reader) {
+ line := io.read_line(^reader, consume_newline=false, inplace=true);
+ io.skip_whitespace(^reader);
+
+ for line do cells << it;
+ height += 1;
+ }
+
+ width := cells.count / height;
+
+ to_try: [..] ugh;
+ tried := set.make(pos);
+
+ to_try << .{ 0, 0, 0, 0 };
+
+ minimum := 0;
+ while to_try.count != 0 {
+ try := array.pop(^to_try);
+ // if tried->has(.{try.x,try.y}) do continue;
+
+ // println(try);
+ tried << .{try.x, try.y};
+
+ cell_value := cast(u32) (cells[(try.y % height) * width + (try.x % width)] - #char "0");
+ cell_value = ((cell_value - 1 + (try.y / height) + (try.x / width)) % 9) + 1;
+ cell_value += try.cost;
+
+ if try.x == width * 5 - 1 && try.y == height * 5 - 1 {
+ minimum = cell_value;
+ break;
+ }
+
+ dist := math.abs(try.x - width * 5 + 1) + math.abs(try.y - height * 5 + 1);
+ if try.x > 0 {
+ if !tried->has(.{try.x - 1, try.y}) {
+ if found := array.find_ptr(to_try, .{try.x - 1, try.y, 0, 0}); found != null {
+ found.cost = math.min(cell_value, found.cost);
+ } else {
+ to_try << .{try.x - 1, try.y + 0, cell_value, dist + 1 };
+ }
+ }
+ }
+ if try.x < width * 5 - 1 {
+ if !tried->has(.{try.x + 1, try.y}) {
+ if found := array.find_ptr(to_try, .{try.x + 1, try.y, 0, 0}); found != null {
+ found.cost = math.min(cell_value, found.cost);
+ } else {
+ to_try << .{try.x + 1, try.y + 0, cell_value, dist - 1 };
+ }
+ }
+ }
+ if try.y > 0 {
+ if !tried->has(.{try.x, try.y - 1}) {
+ if found := array.find_ptr(to_try, .{try.x, try.y - 1, 0, 0}); found != null {
+ found.cost = math.min(cell_value, found.cost);
+ } else {
+ to_try << .{try.x, try.y - 1, cell_value, dist + 1 };
+ }
+ }
+ }
+ if try.y < height * 5 - 1 {
+ if !tried->has(.{try.x, try.y + 1}) {
+ if found := array.find_ptr(to_try, .{try.x, try.y + 1, 0, 0}); found != null {
+ found.cost = math.min(cell_value, found.cost);
+ } else {
+ to_try << .{try.x, try.y + 1, cell_value, dist - 1 };
+ }
+ }
+ }
+
+ array.sort(to_try, (y,x) => (x.cost + x.dist) - (y.cost + y.dist));
+ }
+
+ printf("Part 2: {}\n", minimum);// - ~~(cells[0] - #char "0"));
+/*
+ min_paths := array.make(u32, capacity=cells.count*25);
+ min_paths.count = cells.count * 25;
+ memory.set(min_paths.data, 0, sizeof u32 * min_paths.count * 25);
+
+ for y: height * 5 do for x: width * 5 {
+ if y == 0 && x == 0 do continue;
+
+ a, b := 100000, 100000;
+ if y > 0 do a = min_paths[(y - 1) * width * 5 + x];
+ if x > 0 do b = min_paths[y * width * 5 + (x - 1)];
+
+ cell_value := cast(u32) (cells[(y % height) * width + (x % width)] - #char "0");
+ cell_value = ((cell_value - 1 + (y / height) + (x / width)) % 9) + 1;
+
+ min_paths[y * width * 5 + x] = math.min(a, b) + cell_value;
+ }
+
+ result := min_paths[width * height * 25 - 1];
+ printf("Part 2: {}\n", result);
+*/
+ }
+}
\ No newline at end of file