aboutsummaryrefslogtreecommitdiffstats
path: root/day17
diff options
context:
space:
mode:
authorOrfeas <38209077+0xfea5@users.noreply.github.com>2023-12-18 19:29:23 +0200
committerOrfeas <38209077+0xfea5@users.noreply.github.com>2025-10-28 23:20:45 +0200
commitf3ae9a6c76a1f2963d2cb7f3fc76f6a18112999d (patch)
treebc25dce8488add1130d42d50587a19e3bfaa7bb3 /day17
parentday16 (diff)
downloadaoc23-f3ae9a6c76a1f2963d2cb7f3fc76f6a18112999d.tar.gz
aoc23-f3ae9a6c76a1f2963d2cb7f3fc76f6a18112999d.zip
day17
Diffstat (limited to 'day17')
-rw-r--r--day17/example1.txt13
-rw-r--r--day17/example2.txt5
-rw-r--r--day17/solution.zig108
3 files changed, 126 insertions, 0 deletions
diff --git a/day17/example1.txt b/day17/example1.txt
new file mode 100644
index 0000000..f400d6e
--- /dev/null
+++ b/day17/example1.txt
@@ -0,0 +1,13 @@
12413432311323
23215453535623
33255245654254
43446585845452
54546657867536
61438598798454
74457876987766
83637877979653
94654967986887
104564679986453
111224686865563
122546548887735
134322674655533
diff --git a/day17/example2.txt b/day17/example2.txt
new file mode 100644
index 0000000..e456899
--- /dev/null
+++ b/day17/example2.txt
@@ -0,0 +1,5 @@
1111111111111
2999999999991
3999999999991
4999999999991
5999999999991
diff --git a/day17/solution.zig b/day17/solution.zig
new file mode 100644
index 0000000..00591ff
--- /dev/null
+++ b/day17/solution.zig
@@ -0,0 +1,108 @@
1const std = @import("std");
2const print = std.debug.print;
3const assert = std.debug.assert;
4const ArrayList = std.ArrayList;
5const HashMap = std.HashMap;
6const mem = std.mem;
7const math = std.math;
8
9const fin = mem.trim(u8, @embedFile("./input.txt"), &std.ascii.whitespace);
10var gpa = std.heap.GeneralPurposeAllocator(.{}){};
11const allocator = gpa.allocator();
12
13const move = [_][2]i64{
14 [_]i64{ -1, 0 },
15 [_]i64{ 0, 1 },
16 [_]i64{ 1, 0 },
17 [_]i64{ 0, -1 },
18};
19
20const Point = struct {
21 i: usize,
22 j: usize,
23 best: [4]u64,
24
25 pub fn Cmp(_: void, lhs: Point, rhs: Point) math.Order {
26 return std.math.order(mem.min(u64, &lhs.best), mem.min(u64, &rhs.best));
27 }
28};
29
30const inf: u64 = math.maxInt(u32);
31const MAXSIZE = 200;
32
33fn evaluate(grid: []const []const u8, comptime min_dist: u64, comptime max_dist: u64) !u64 {
34 var dp = [_][MAXSIZE][4]u64{[_][4]u64{[_]u64{inf} ** 4} ** MAXSIZE} ** MAXSIZE;
35 const w = grid[0].len;
36 const h = grid.len;
37 var pq = std.PriorityQueue(Point, void, Point.Cmp).init(allocator, {});
38
39 dp[0][0] = [_]u64{0} ** 4;
40
41 try pq.add(Point{
42 .i = 0,
43 .j = 0,
44 .best = dp[0][0],
45 });
46
47 while (pq.removeOrNull()) |curr| {
48 for (move, 0..) |m, dirTo| {
49 const dirFrom = dirTo ^ 0b10;
50 const dpbest = res: {
51 var best: u64 = inf;
52
53 for (0..4) |dir| {
54 if (dir != dirFrom and dir != dirTo) {
55 best = @min(best, dp[curr.i][curr.j][dir]);
56 }
57 }
58
59 break :res best;
60 };
61
62 var s: u64 = 0;
63 for (1..max_dist + 1) |dist| {
64 const ni: u64 = @bitCast(@as(i64, @bitCast(curr.i)) + m[0] * @as(i64, @bitCast(dist)));
65 const nj: u64 = @bitCast(@as(i64, @bitCast(curr.j)) + m[1] * @as(i64, @bitCast(dist)));
66
67 if (ni >= h or nj >= w) {
68 break;
69 }
70
71 s += grid[ni][nj] - '0';
72
73 if (dist < min_dist) {
74 continue;
75 }
76
77 if (dp[ni][nj][dirFrom] > dpbest + s) {
78 dp[ni][nj][dirFrom] = dpbest + s;
79 try pq.add(Point{
80 .i = ni,
81 .j = nj,
82 .best = dp[ni][nj],
83 });
84 }
85 }
86 }
87 }
88 return mem.min(u64, &dp[h - 1][w - 1]);
89}
90
91pub fn solve(grid: []const []const u8) !void {
92 const part1 = try evaluate(grid, 1, 3);
93 print("{d}\n", .{part1});
94
95 const part2 = try evaluate(grid, 4, 10);
96 print("{d}\n", .{part2});
97}
98
99pub fn main() !void {
100 var splitLines = mem.splitScalar(u8, fin, '\n');
101 var grid = ArrayList([]const u8).init(allocator);
102
103 while (splitLines.next()) |line| {
104 try grid.append(line);
105 }
106
107 try solve(grid.items);
108}