diff options
| author | Orfeas <38209077+0xfea5@users.noreply.github.com> | 2023-12-16 11:20:06 +0200 |
|---|---|---|
| committer | Orfeas <38209077+0xfea5@users.noreply.github.com> | 2025-10-28 23:20:45 +0200 |
| commit | 6fb83d92c250a9208148af283255ec5e0e9e9175 (patch) | |
| tree | 9cf2e2416bcb0dbd6603fd190c4b55f3fb3f3907 /day16 | |
| parent | day15 (diff) | |
| download | aoc23-6fb83d92c250a9208148af283255ec5e0e9e9175.tar.gz aoc23-6fb83d92c250a9208148af283255ec5e0e9e9175.zip | |
day16
Diffstat (limited to 'day16')
| -rw-r--r-- | day16/example.txt | 10 | ||||
| -rw-r--r-- | day16/solution.zig | 158 |
2 files changed, 168 insertions, 0 deletions
diff --git a/day16/example.txt b/day16/example.txt new file mode 100644 index 0000000..d6805ce --- /dev/null +++ b/day16/example.txt | |||
| @@ -0,0 +1,10 @@ | |||
| 1 | .|...\.... | ||
| 2 | |.-.\..... | ||
| 3 | .....|-... | ||
| 4 | ........|. | ||
| 5 | .......... | ||
| 6 | .........\ | ||
| 7 | ..../.\\.. | ||
| 8 | .-.-/..|.. | ||
| 9 | .|....-|.\ | ||
| 10 | ..//.|.... | ||
diff --git a/day16/solution.zig b/day16/solution.zig new file mode 100644 index 0000000..70da969 --- /dev/null +++ b/day16/solution.zig | |||
| @@ -0,0 +1,158 @@ | |||
| 1 | const std = @import("std"); | ||
| 2 | const print = std.debug.print; | ||
| 3 | const assert = std.debug.assert; | ||
| 4 | const ArrayList = std.ArrayList; | ||
| 5 | const HashMap = std.HashMap; | ||
| 6 | const mem = std.mem; | ||
| 7 | |||
| 8 | const fin = mem.trim(u8, @embedFile("./input.txt"), &std.ascii.whitespace); | ||
| 9 | var gpa = std.heap.GeneralPurposeAllocator(.{}){}; | ||
| 10 | const allocator = gpa.allocator(); | ||
| 11 | |||
| 12 | const step = [_][2]i64{ | ||
| 13 | [2]i64{ -1, 0 }, | ||
| 14 | [2]i64{ 0, 1 }, | ||
| 15 | [2]i64{ 1, 0 }, | ||
| 16 | [2]i64{ 0, -1 }, | ||
| 17 | }; | ||
| 18 | |||
| 19 | const Beam = struct { | ||
| 20 | i: isize, | ||
| 21 | j: isize, | ||
| 22 | d: usize, | ||
| 23 | |||
| 24 | pub inline fn next(self: @This()) Beam { | ||
| 25 | return self.nextd(self.d); | ||
| 26 | } | ||
| 27 | |||
| 28 | pub inline fn prev(self: @This()) Beam { | ||
| 29 | return Beam{ | ||
| 30 | .i = self.i - step[self.d][0], | ||
| 31 | .j = self.j - step[self.d][1], | ||
| 32 | .d = self.d, | ||
| 33 | }; | ||
| 34 | } | ||
| 35 | |||
| 36 | pub inline fn nextd(self: @This(), d: usize) Beam { | ||
| 37 | return Beam{ | ||
| 38 | .i = self.i + step[d][0], | ||
| 39 | .j = self.j + step[d][1], | ||
| 40 | .d = d, | ||
| 41 | }; | ||
| 42 | } | ||
| 43 | |||
| 44 | pub const Ctx = struct { | ||
| 45 | pub fn hash(_: @This(), b: Beam) u64 { | ||
| 46 | return @bitCast(b.i << 16 | b.j << 8 | @as(isize, @bitCast(b.d))); | ||
| 47 | } | ||
| 48 | |||
| 49 | pub fn eql(_: @This(), lhs: Beam, rhs: Beam) bool { | ||
| 50 | return lhs.i == rhs.i and lhs.j == rhs.j and lhs.d == rhs.d; | ||
| 51 | } | ||
| 52 | }; | ||
| 53 | |||
| 54 | // ignore direction when comparing beams | ||
| 55 | pub const Ctx2 = struct { | ||
| 56 | pub fn hash(_: @This(), b: Beam) u64 { | ||
| 57 | return @bitCast(b.i << 8 | b.j); | ||
| 58 | } | ||
| 59 | |||
| 60 | pub fn eql(_: @This(), lhs: Beam, rhs: Beam) bool { | ||
| 61 | const res = lhs.i == rhs.i and lhs.j == rhs.j; | ||
| 62 | return res; | ||
| 63 | } | ||
| 64 | }; | ||
| 65 | }; | ||
| 66 | |||
| 67 | var edgesVisited = HashMap(Beam, void, Beam.Ctx2, 80).init(allocator); | ||
| 68 | |||
| 69 | fn dfs(grid: []const []const u8, start: Beam) !u64 { | ||
| 70 | if (edgesVisited.get(start) != null) { | ||
| 71 | return 0; | ||
| 72 | } | ||
| 73 | const w = grid[0].len; | ||
| 74 | const h = grid.len; | ||
| 75 | var beams = ArrayList(Beam).init(allocator); | ||
| 76 | var visited = HashMap(Beam, void, Beam.Ctx, 80).init(allocator); | ||
| 77 | var uniq = HashMap(Beam, void, Beam.Ctx2, 80).init(allocator); | ||
| 78 | defer { | ||
| 79 | beams.deinit(); | ||
| 80 | uniq.deinit(); | ||
| 81 | visited.deinit(); | ||
| 82 | } | ||
| 83 | |||
| 84 | try beams.append(start); | ||
| 85 | |||
| 86 | while (beams.items.len > 0) { | ||
| 87 | var curr = beams.pop(); | ||
| 88 | while (0 <= curr.i and curr.i < h and 0 <= curr.j and curr.j < w) { | ||
| 89 | if ((try visited.getOrPut(curr)).found_existing) { | ||
| 90 | break; | ||
| 91 | } | ||
| 92 | const c = grid[@bitCast(curr.i)][@bitCast(curr.j)]; | ||
| 93 | switch (c) { | ||
| 94 | '|' => { | ||
| 95 | try beams.append(curr.nextd(2)); | ||
| 96 | curr = curr.nextd(0); | ||
| 97 | }, | ||
| 98 | '-' => { | ||
| 99 | try beams.append(curr.nextd(3)); | ||
| 100 | curr = curr.nextd(1); | ||
| 101 | }, | ||
| 102 | '\\' => { | ||
| 103 | const d = (curr.d + if (curr.d & 1 != 0) @as(usize, 1) else @as(usize, 3)) % 4; | ||
| 104 | curr = curr.nextd(d); | ||
| 105 | }, | ||
| 106 | '/' => { | ||
| 107 | const d = (curr.d + if (curr.d & 1 != 0) @as(usize, 3) else @as(usize, 1)) % 4; | ||
| 108 | curr = curr.nextd(d); | ||
| 109 | }, | ||
| 110 | '.' => { | ||
| 111 | curr = curr.next(); | ||
| 112 | }, | ||
| 113 | else => unreachable, | ||
| 114 | } | ||
| 115 | } else { // finished by hitting an edge | ||
| 116 | try edgesVisited.put(curr.prev(), {}); | ||
| 117 | } | ||
| 118 | } | ||
| 119 | |||
| 120 | var it = visited.keyIterator(); | ||
| 121 | while (it.next()) |k| { | ||
| 122 | try uniq.put(k.*, {}); | ||
| 123 | } | ||
| 124 | |||
| 125 | return uniq.count(); | ||
| 126 | } | ||
| 127 | |||
| 128 | pub fn solve(grid: []const []const u8) !void { | ||
| 129 | const h = grid.len; | ||
| 130 | const w = grid[0].len; | ||
| 131 | const part1 = try dfs(grid, Beam{ .i = 0, .j = 0, .d = 1 }); | ||
| 132 | |||
| 133 | print("{d}\n", .{part1}); | ||
| 134 | |||
| 135 | var part2: u64 = 0; | ||
| 136 | for (0..h) |i_| { | ||
| 137 | const i: i64 = @bitCast(i_); | ||
| 138 | part2 = @max(part2, try dfs(grid, .{ .i = i, .j = 0, .d = 1 })); | ||
| 139 | part2 = @max(part2, try dfs(grid, .{ .i = i, .j = @bitCast(w - 1), .d = 3 })); | ||
| 140 | } | ||
| 141 | for (0..w) |j_| { | ||
| 142 | const j: i64 = @bitCast(j_); | ||
| 143 | part2 = @max(part2, try dfs(grid, .{ .i = 0, .j = j, .d = 2 })); | ||
| 144 | part2 = @max(part2, try dfs(grid, .{ .i = @bitCast(h - 1), .j = j, .d = 0 })); | ||
| 145 | } | ||
| 146 | |||
| 147 | print("{d}\n", .{part2}); | ||
| 148 | } | ||
| 149 | |||
| 150 | pub fn main() !void { | ||
| 151 | var splitLines = mem.splitScalar(u8, fin, '\n'); | ||
| 152 | var grid = ArrayList([]const u8).init(allocator); | ||
| 153 | |||
| 154 | while (splitLines.next()) |line| { | ||
| 155 | try grid.append(line); | ||
| 156 | } | ||
| 157 | try solve(grid.items); | ||
| 158 | } | ||
