From 83e5d44f615dfe5113b8cb06dfad11c81a0748a2 Mon Sep 17 00:00:00 2001 From: Jeremy Kaplan Date: Sun, 15 Dec 2024 17:15:24 -0800 Subject: [PATCH] 2024 Day 15 Part 2 --- 2024/src/day15.zig | 181 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 181 insertions(+) diff --git a/2024/src/day15.zig b/2024/src/day15.zig index abedb75..e583206 100644 --- a/2024/src/day15.zig +++ b/2024/src/day15.zig @@ -26,6 +26,7 @@ pub fn main() !void { const stdout = bw.writer(); try stdout.print("{d}\n", .{try part1(grid, moves.items)}); + try stdout.print("{d}\n", .{try part2(grid, moves.items)}); try bw.flush(); } @@ -67,6 +68,88 @@ fn part1(start: Grid, moves: []const Direction) !i64 { return score; } +fn part2(original: Grid, moves: []const Direction) !i64 { + var start: Pos = undefined; + + var grid = v: { + var map = Map(Pos, u8).init(original.allocator); + + var it = original.iterator(); + while (it.next()) |entry| { + const pos = entry.key_ptr.*; + const char = entry.value_ptr.*; + + const left, const right = .{ + Pos.new(pos.r, 2 * pos.c), + Pos.new(pos.r, 2 * pos.c + 1), + }; + + if (char == '#') { + try map.put(left, '#'); + try map.put(right, '#'); + } + if (char == 'O') { + try map.put(left, '['); + try map.put(right, ']'); + } + if (char == '.') { + try map.put(left, '.'); + try map.put(right, '.'); + } + if (char == '@') { + try map.put(left, '@'); + try map.put(right, '.'); + start = left; + } + } + + break :v Grid{ + .allocator = original.allocator, + .map = map, + .max = Pos.new(original.max.r, 2 * original.max.c + 1), + }; + }; + defer grid.deinit(); + + var pos = v: { + var it = grid.iterator(); + while (it.next()) |entry| { + const pos = entry.key_ptr.*; + const char = entry.value_ptr.*; + + if (char == '@') { + break :v pos; + } + } + unreachable; + }; + + for (moves) |dir| { + if (grid.can_move2(pos, dir)) { + var moved = Set(Pos).init(grid.allocator); + defer moved.deinit(); + + try grid.do_move2(pos, dir, &moved); + pos = pos.add(dir.delta()); + } + } + + var score: i64 = 0; + var it = grid.iterator(); + while (it.next()) |entry| { + const box = entry.key_ptr.*; + const char = entry.value_ptr.*; + + if (char != '[') { + continue; + } + + score += 100 * box.r + box.c; + } + + return score; +} + const Pos = struct { r: i32, c: i32, @@ -201,6 +284,22 @@ const Grid = struct { 0 <= pos.c and pos.c <= self.max.c; } + pub fn format( + self: Grid, + comptime _: []const u8, + _: std.fmt.FormatOptions, + writer: anytype, + ) !void { + var r: i32 = 0; + while (r <= self.max.r) : (r += 1) { + var c: i32 = 0; + while (c <= self.max.c) : (c += 1) { + try writer.print("{c}", .{self.get(Pos.new(r, c)).?}); + } + try writer.print("\n", .{}); + } + } + fn move(self: *Grid, robot: Pos, dir: Direction) !Pos { var stack = List(Pos).init(self.allocator); defer stack.deinit(); @@ -223,4 +322,86 @@ const Grid = struct { return robot.add(delta); } + + fn can_move2(self: *Grid, pos: Pos, dir: Direction) bool { + const delta = dir.delta(); + const next = pos.add(delta); + + switch (self.get(next).?) { + '#' => return false, + '.' => return true, + '@' => return self.can_move2(next, dir), + + '[' => switch (dir) { + .n, .s => { + const left = self.can_move2(next, dir); + const right = self.can_move2(next.add(Direction.e.delta()), dir); + return left and right; + }, + .e => return self.can_move2(next.add(Direction.e.delta()), dir), + .w => return self.can_move2(next, dir), + }, + ']' => switch (dir) { + .n, .s => { + const left = self.can_move2(next, dir); + const right = self.can_move2(next.add(Direction.w.delta()), dir); + return left and right; + }, + .w => return self.can_move2(next.add(Direction.w.delta()), dir), + .e => return self.can_move2(next, dir), + }, + else => unreachable, + } + } + + fn do_move2(self: *Grid, pos: Pos, dir: Direction, moved: *Set(Pos)) !void { + if (moved.contains(pos)) { + return; + } + try moved.put(pos); + + const delta = dir.delta(); + const next = pos.add(delta); + + const content = self.get(pos).?; + + switch (content) { + '#' => unreachable, + '.' => return, + '@' => try self.do_move2(next, dir, moved), + + '[' => { + const pair = pos.add(Direction.e.delta()); + switch (dir) { + .n, .s => { + try self.do_move2(next, dir, moved); + try self.do_move2(pair, dir, moved); + }, + .e => { + try self.do_move2(pair, dir, moved); + try self.do_move2(next, dir, moved); + }, + .w => try self.do_move2(next, dir, moved), + } + }, + ']' => { + const pair = pos.add(Direction.w.delta()); + switch (dir) { + .n, .s => { + try self.do_move2(pair, dir, moved); + try self.do_move2(next, dir, moved); + }, + .w => { + try self.do_move2(pair, dir, moved); + try self.do_move2(next, dir, moved); + }, + .e => try self.do_move2(next, dir, moved), + } + }, + else => unreachable, + } + + try self.map.put(next, content); + try self.map.put(pos, '.'); + } };