Watch
1
0
Fork
You've already forked advent-of-code
0

2024 Day 15 Part 2

This commit is contained in:
Jeremy Kaplan 2024-12-15 17:15:24 -08:00
commit 83e5d44f61

View file

@ -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, '.');
}
};