TD4SGIRCNYDNS236UXIX45QYRWQ7RXUDNFZYBBQT2ZBHX2DXQDZQC
var cost_grid = [_][GRID_COLS]CostType{[_]CostType{std.math.maxInt(CostType)} ** GRID_COLS} ** GRID_ROWS;
cost_grid[pipes.start[0]][pipes.start[1]] = 0;
const start_pipe = try detectStart(maze);
maze.grid[maze.start[0]][maze.start[1]] = start_pipe; // set proper S value
return 1;
var cost_grid = [_][COST_COLS]CostType{[_]CostType{std.math.maxInt(CostType)} ** COST_COLS} ** COST_ROWS;
cost_grid[maze.start[0]][maze.start[1]] = 0;
const start_pipe = try detectStart(maze);
maze.grid[maze.start[0]][maze.start[1]] = start_pipe; // set proper S value
try dijkstra(allocator, &maze, &cost_grid);
var enclosed: usize = 0;
for (cost_grid, 0..) |line, row| {
for (line, 0..) |_, col| {
if (maze.visited[row][col]) {
// std.debug.print("{c}", .{maze.grid[row][col]});
continue; // only check items _NOT_ in the main loop
}
var cuts: usize = 0;
for (0..col) |c| {
if (!maze.visited[row][c]) continue; // only count cuts with the main loop
switch (maze.grid[row][c]) {
'|', 'J', 'L' => cuts += 1,
else => {},
}
}
if (cuts % 2 == 1) {
enclosed += 1;
// std.debug.print("{c}", .{'%'});
} else {
// std.debug.print("{c}", .{maze.grid[row][col]});
}
}
// std.debug.print("{c}", .{'\n'});
}
return enclosed;
const QueueType = struct {
state: [2]usize,
cost: usize,
/// Determines the true shape of the 'S' pipe
fn detectStart(maze: Maze) !u8 {
const Pipes = enum {
north_south,
east_west,
north_east,
north_west,
south_east,
south_west,
fn char(self: @This()) u8 {
return switch (self) {
.north_south => '|',
.east_west => '-',
.north_east => 'J',
.north_west => 'L',
.south_east => '7',
.south_west => 'F',
};
}
};
var options = std.EnumSet(Pipes).initFull();
const start_directions = enum { north, south, west, east };
for (std.enums.values(start_directions)) |dir| {
const d: [2]i2 = switch (dir) {
.north => .{ -1, 0 },
.south => .{ 1, 0 },
.west => .{ 0, -1 },
.east => .{ 0, 1 },
};
const diffrow = @as(isize, @intCast(maze.start[0])) + d[0];
if (diffrow < 0 or diffrow >= GRID_ROWS) continue;
const dr = @as(usize, @intCast(diffrow));
const diffcol = @as(isize, @intCast(maze.start[1])) + d[1];
if (diffcol < 0 or diffcol >= GRID_COLS) continue;
const dc = @as(usize, @intCast(diffcol));
const next = maze.grid[dr][dc];
fn lessThan(context: void, a: @This(), b: @This()) std.math.Order {
_ = context;
if (a.cost < b.cost) return .lt else if (a.cost == b.cost) return .eq else return .gt;
switch (dir) {
.north => {
switch (next) {
'|', '7', 'F' => {
options.remove(.east_west);
options.remove(.south_east);
options.remove(.south_west);
},
else => {},
}
},
.south => {
switch (next) {
'|', 'L', 'J' => {
options.remove(.east_west);
options.remove(.north_east);
options.remove(.north_west);
},
else => {},
}
},
.east => {
switch (next) {
'-', 'L', 'F' => {
options.remove(.north_south);
options.remove(.south_west);
options.remove(.north_west);
},
else => {},
}
},
.west => {
switch (next) {
'-', '7', 'J' => {
options.remove(.north_south);
options.remove(.south_east);
options.remove(.north_east);
},
else => {},
}
},
}
{ // Handle start position and its neighbors
const start_directions = enum { north, south, west, east };
for (std.enums.values(start_directions)) |dir| {
const d: [2]i2 = switch (dir) {
.north => .{ -1, 0 },
.south => .{ 1, 0 },
.west => .{ 0, -1 },
.east => .{ 0, 1 },
};
// Add start item
try queue.add(.{ .state = .{ maze.start[0], maze.start[1] }, .cost = 0 });
const diffrow = @as(isize, @intCast(pipes.start[0])) + d[0];
if (diffrow < 0 or diffrow >= GRID_ROWS) continue;
const dr = @as(usize, @intCast(diffrow));
while (queue.removeOrNull()) |curr| {
// mark this grid item visited
maze.visited[curr.state[0]][curr.state[1]] = true;
const diffcol = @as(isize, @intCast(pipes.start[1])) + d[1];
if (diffcol < 0 or diffcol >= GRID_COLS) continue;
const dc = @as(usize, @intCast(diffcol));
switch (dir) {
.north => {
switch (pipes.grid[dr][dc]) {
'|', '7', 'F' => {},
'.', '-', 'L', 'J' => continue,
else => unreachable,
}
},
.south => {
switch (pipes.grid[dr][dc]) {
'|', 'L', 'J' => {},
'.', '-', '7', 'F' => continue,
else => unreachable,
}
},
.west => {
switch (pipes.grid[dr][dc]) {
'-', 'L', 'F' => {},
'.', '|', 'J', '7' => continue,
else => unreachable,
}
},
.east => {
switch (pipes.grid[dr][dc]) {
'-', 'J', '7' => {},
'.', '|', 'L', 'F' => continue,
else => unreachable,
}
},
}
cost_grid[dr][dc] = 1;
try queue.add(.{ .state = .{ dr, dc }, .cost = 1 });
}
}
// Dijkstra...
while (queue.removeOrNull()) |curr| {
const test_input3 =
\\.F----7F7F7F7F-7....
\\.|F--7||||||||FJ....
\\.||.FJ||||||||L7....
\\FJL7L7LJLJ||LJ.L-7..
\\L--J.L7...LJS7F-7L7.
\\....F-J..F7FJ|L7L7L7
\\....L7.F7||L7|.L7L7|
\\.....|FJLJ|FJ|F7|.LJ
\\....FJL-7.||.||||...
\\....L---J.LJ.LJLJ...
;
const test_input4 =
\\FF7FSF7F7F7F7F7F---7
\\L|LJ||||||||||||F--J
\\FL-7LJLJ||||||LJL-77
\\F--JF--7||LJLJ7F7FJ-
\\L---JF-JLJ.||-FJLJJ7
\\|F|F-JF---7F7-L7L|7|
\\|FFJF7L7F-JF7|JL---7
\\7-L-JL7||F7|L7F-7F7|
\\L.L7LFJ|||||FJL7||LJ
\\L7JLJL-JLJLJL--JLJ.L
;