2024 Day 15 Part 2
This commit is contained in:
parent
f39ff98bf3
commit
83e5d44f61
1 changed files with 181 additions and 0 deletions
|
|
@ -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, '.');
|
||||
}
|
||||
};
|
||||
|
|
|
|||
Loading…
Reference in a new issue