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 valuetry 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 loopswitch (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' pipefn 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 neighborsconst 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 itemtry 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 visitedmaze.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;