diff --git a/day16-hard/build.zig b/day16-hard/build.zig new file mode 100644 index 0000000..86863aa --- /dev/null +++ b/day16-hard/build.zig @@ -0,0 +1,70 @@ +const std = @import("std"); + +// Although this function looks imperative, note that its job is to +// declaratively construct a build graph that will be executed by an external +// runner. +pub fn build(b: *std.Build) void { + // Standard target options allows the person running `zig build` to choose + // what target to build for. Here we do not override the defaults, which + // means any target is allowed, and the default is native. Other options + // for restricting supported target set are available. + const target = b.standardTargetOptions(.{}); + + // Standard optimization options allow the person running `zig build` to select + // between Debug, ReleaseSafe, ReleaseFast, and ReleaseSmall. Here we do not + // set a preferred release mode, allowing the user to decide how to optimize. + const optimize = b.standardOptimizeOption(.{}); + + const exe = b.addExecutable(.{ + .name = "day16-hard", + // In this case the main source file is merely a path, however, in more + // complicated build scripts, this could be a generated file. + .root_source_file = .{ .path = "src/main.zig" }, + .target = target, + .optimize = optimize, + }); + + // This declares intent for the executable to be installed into the + // standard location when the user invokes the "install" step (the default + // step when running `zig build`). + b.installArtifact(exe); + + // This *creates* a Run step in the build graph, to be executed when another + // step is evaluated that depends on it. The next line below will establish + // such a dependency. + const run_cmd = b.addRunArtifact(exe); + + // By making the run step depend on the install step, it will be run from the + // installation directory rather than directly from within the cache directory. + // This is not necessary, however, if the application depends on other installed + // files, this ensures they will be present and in the expected location. + run_cmd.step.dependOn(b.getInstallStep()); + + // This allows the user to pass arguments to the application in the build + // command itself, like this: `zig build run -- arg1 arg2 etc` + if (b.args) |args| { + run_cmd.addArgs(args); + } + + // This creates a build step. It will be visible in the `zig build --help` menu, + // and can be selected like this: `zig build run` + // This will evaluate the `run` step rather than the default, which is "install". + const run_step = b.step("run", "Run the app"); + run_step.dependOn(&run_cmd.step); + + // Creates a step for unit testing. This only builds the test executable + // but does not run it. + const unit_tests = b.addTest(.{ + .root_source_file = .{ .path = "src/main.zig" }, + .target = target, + .optimize = optimize, + }); + + const run_unit_tests = b.addRunArtifact(unit_tests); + + // Similar to creating the run step earlier, this exposes a `test` step to + // the `zig build --help` menu, providing a way for the user to request + // running the unit tests. + const test_step = b.step("test", "Run unit tests"); + test_step.dependOn(&run_unit_tests.step); +} diff --git a/day16-hard/hard.in b/day16-hard/hard.in new file mode 100644 index 0000000..9ede16f --- /dev/null +++ b/day16-hard/hard.in @@ -0,0 +1,110 @@ +\...|.........\........./.................\...\.../.\/../|....\................./..../........-\..-.\-..../... +...|....\................../.............../-....--..........-......-......\....-........../-..............|.. +..............\....../.........../...................|.........\.................|.-................../....... +.........................\........../..-........./.../..........|....................-....\./.........|....... +.-.......\......-.-................|......................................-..............\......./............ +............|...|..|.|............................../-..........\..\.......................................\-. +...|.|.\........./......|....|......./............/...\......../.../.........../.../............/.-...-.|..... +..................../.....-.........\......-....|.......................\.....-............................... +../............|.|.-....-.........../|........-..|....|.....................-.-.....\...-.......|............. +..-./..............-.............-......................./............/.......|.....-..........|.........../.. +......|.........-|.|/..........-......................\.|./.....\....-..........................|./-./........ +.|...-.............-.....-.............|.../..............|-........................\........\...|./.......... +............/.........\.......-..........|........../.....\......\....|...............|....................... +|...||....\.......|..........|.....|................./.......-...................|............/............... +.......-.....\-.....................\...|................................|..........|......\..\.........-/.... +............../.............................\.........................\|............-......................... +.......-..|........./..........|...-......././......./...../..........................|...../............/.... +.-/......-.............../../........................\............\.....|.//.......-.................|.......\ +........-......|.....-.............\............\...................-...\...............-............|........ +...-.......................-...................\....|.......-.............|./..\....|.....................|... +.......-..\...|/.\........\...........-.....................\.../.....|.|........../.........-................ +....|..../..........\/..........-..................-............|......./.......-......\.....||....../.....-.. +|.-........................-....\...../......\.......|\......-...........-......\............................. +\.....\........\........\......................-....................\...........-.../......................... +..-...|.|.........--.........-.|......\........-.................\...................................|.......| +-..|.....-.......-.......|......|./........../...........-......|..................-.......................... +...................||..\........|............\..|............\............-..-.......|........................ +..........-..........-..|........./....|..-......./..-|...|.....\......./...-|../.../......./..|.............. +....\|..................|......................................................../.....|.....|....||../....... +.......................-.../..|.............-.|..........|.......................-....-......-................ +.......|./.............-........./...........\..........|-........\.....-....|....|........-.......\....\..... +../........./.......................|................/.....-...................|...............\.../.....\.... +........................|...........................|.................................................../..... +|\.....|....................-..................-.........................\......\...-..............-.......... +..................................|.....\..\-|........................................................-....... +.../....-...../|-.|.....\.../............/|......................./.....-............|.\.......-../........... +.\......|.......................\..-\.........|.....-........./............\.......|....|...|...././....\....- +.\......\..........................\......-.......|.\.............../...\/.....-........|....|................ +\...-.......|\..|............../.../...........|.............-.................-.......................\./.|.. +....-......................../.......................\..../................\.............\................/..| +...-...|......../.-...........-.........................................../\.|....-|........-\................ +\-.../........|.......................-.....................|......./........................|...........\.\-. +......\.-......./............\.................-...|..............|./../....\.-............-./.......|........ +........./...........|.....|../........./....................|.\..\-..|........\......|\..................../. +-..........\......-.............................\....|......\..........|.................-.................... +.......................|.....|....................................-..\...................................../.. +......../.\........./.../....\.../..||.\|......................................|........................../... +..\..................|....../.........\.........-....-|........-.....................-........\...../..|...... +...|.........|...|.....|.....\..-.../...../.........-.....|............../.................................... +.......\.........\......-...-........./.............../........./......|../.............../........-....-..... +..........|..........................\.-...\.........../..../..\................|.........../.....\........... +.........\....../.....................................................-.............|.-....................... +......-..........|..-......-.................\................/........../............-.|....|.|\......-...... +....\............|..../..................|......|..-.-....\......|./.........|...........|....//.|..-......... +|........................||...../-.........../...../.-..................................|..........-.........- +....-\...............|.............................\.-..../......................./....\..............\../.|.. +......\.|................/../..|............-.....|...\..............................|.............|.........- +...................\.....|...............|..\.-......\........../.\........................................... +........|....................-..\\....................-/...../......../.|...........\......-.|........-....... +............\...-./........./.....................................................-........................... +\...|.....\...\......................-......./..../../...............\......./../......................-.....- +.........../.......\..../..................................-......|.../.............././.....................\ +.....................|......\........-......................../.|....................|...................../.- +.....\./....\..../\..|...........|.-.....|..............\..............-.\............../..................... +.......-.....|...........\.|\....\..|......|.......././............/...-...|-.-../......||...\................ +...................../...\....|../..|................-.......\...............................\................ +.......-.....\\......\....\...|....|......\...........\.\..../.....\.......................|.../.............. +........-......................../.\............................./................|.....|..................... +......\-...../.|.........\..........\...\/..-......................//.....................|..................\ +...............|/.........../.......................-....|..................\........-...\-...\...........\... +...-/..................................................|.........................-.......\.-.............|.... +|/......................../.........../........../....|...../............-.........\....-..................... +.............-/....|../.............|.............-.-.\.\......./\............../.....\...|................|.. +|......-.........../...|........\........../........................................./.................-...... +....|......../..-|....-..........|-..................\.\..\.................\.-..|............./.......-...... +...............-.........-........../....................||.-........................-.....-.\................ +...............|........\.......|./.../...........-...../...\....-./....|.....................\...\........... +........../................................./.\........./......./.....|.../....|./...../...........\...|.\.-.. +.../..../........................|....-..........................-..|.\-..............|.....\.........-....... +......|..|........../.................|.........|..../..............././............\-.-...............-.....- +......\../|.|......../........................\..\.......|........................\./........./............... +...../......../........\.|.................|............................-........................|....\....... +|.-|........|.|./.-...........-\...-../../.../..|..........................\.....|.........../................ +..\...././............././...../...............|./.../..../..........-........-../...-....................\... +.....\....................../..|.........................\.....-/................-......................../... +...........|............................../....|.......................-........|......................./..... +../..|............-..............\.................//..................../\.|......-.//........./............. +........|....................../|...........|...../......|......-....\................/.............-......||. +\....-..............\..............-../.....-.....................-.../............/............../.\...-..... +./....\...............|..................|..../.....\..........-|......../...........-.\./.................... +/..-....../........................../.\....\....\-............................../....-........\.............. +..............-.\..............-..............\-|....|............../..-..././..............\..|.............. +......................\-..............|........-....-........-....................../......\.................. +................\.|./.......|....../...-.........-..................\............-........./.|................ +...................-............................................-...|...../....\........../...-.../........... +.....\....................-...................\../....................................|..........-............ +..../.......\/-.\...-........./......./........|....................................-......................... +....|....................................-.........|\..................\.......-..\.....-...\-......|......... +................................./.................................../.-../...|.\...............|.....\....... +..|..........-.-\...........................|................-.........../...\..............-\/............-.- +....|......./-.........|.................|............|...|.........................-.....................\... +.-.|.........-...|.............................\......../.\............|..............-...\........\|./...|./. +..../\...........\............-.../..\...................././....-..........|.........|..|.............|...... +....................-..................................-...........\|....................|...\...|............ +...-.|......................./.-...................-.../......|.........................../................... +...........................\....|\........\.......\.|...../.............-.|../.......................-........ +...........................................|...-............\......................../.............-.......... +..........|.|..........\.../.........|.....-.........-....|............-........../....../......./..-........| +.../.....\.................\........\.................................../....|...-......./..........\.....|/.. +.......|....\.....|...............|........-|.........../............/../.\...\......................\........ \ No newline at end of file diff --git a/day16-hard/sample.in b/day16-hard/sample.in new file mode 100644 index 0000000..c78b2e7 --- /dev/null +++ b/day16-hard/sample.in @@ -0,0 +1,10 @@ +.|...\.... +|.-.\..... +.....|-... +........|. +.......... +.........\ +..../.\\.. +.-.-/..|.. +.|....-|.\ +..//.|.... \ No newline at end of file diff --git a/day16-hard/src/main.zig b/day16-hard/src/main.zig new file mode 100644 index 0000000..f083fb6 --- /dev/null +++ b/day16-hard/src/main.zig @@ -0,0 +1,297 @@ +const std = @import("std"); + +fn StackList(comptime T: type, comptime capacity_type: type, comptime capacity: capacity_type) type { + return struct { + const Self = @This(); + mem: [capacity]T, + length: capacity_type, + + fn add(self: *Self, value: T) void { + self.mem[self.length] = value; + self.length += 1; + } + + fn addIfNotNull(self: *Self, nullable_value: ?T) void { + if (nullable_value) |value| { + self.add(value); + } + } + + fn has(self: *Self, needle: T) bool { + for (0..self.length) |i| { + if (self.mem[i] == needle) { + return true; + } + } + + return false; + } + + fn getMutableSlice(self: *Self) []T { + return (&self.mem)[0..self.length]; + } + + fn getSlice(self: *const Self) []const T { + return self.mem[0..self.length]; + } + + fn init() Self { + return Self{ + .mem = undefined, + .length = 0, + }; + } + }; +} + +const CellStatus = packed struct(u8) { + left: bool = false, + right: bool = false, + up: bool = false, + down: bool = false, + _padding: u4 = 0, +}; + +const Task = packed struct(u32) { + x: u12, + y: u12, + status: CellStatus, +}; + +const Queue = StackList(Task, usize, 65534); + +fn getUpTask(original_task: Task) ?Task { + if (original_task.x == 0) { + return null; + } + + return .{ + .x = original_task.x - 1, + .y = original_task.y, + .status = .{ .up = true }, + }; +} + +fn getDownTask(original_task: Task, lines: []const []const u8) ?Task { + if (original_task.x + 1 >= lines.len) { + return null; + } + + return .{ + .x = original_task.x + 1, + .y = original_task.y, + .status = .{ .down = true }, + }; +} + +fn getLeftTask(original_task: Task) ?Task { + if (original_task.y == 0) { + return null; + } + + return .{ + .x = original_task.x, + .y = original_task.y - 1, + .status = .{ .left = true }, + }; +} + +fn getRightTask(original_task: Task, lines: []const []const u8) ?Task { + if (original_task.y + 1 >= lines[original_task.x].len) { + return null; + } + + return .{ + .x = original_task.x, + .y = original_task.y + 1, + .status = .{ .right = true }, + }; +} + +fn solveForStart(lines: []const []const u8, firstTask: Task) usize { + var state = std.mem.zeroes([128][128]CellStatus); + var tasks = Queue.init(); + + tasks.add(firstTask); + + var step: usize = 0; + while (step < tasks.length) : (step += 1) { + const task = tasks.mem[step]; + var cell_state = &state[task.x][task.y]; + var cell_value = lines[task.x][task.y]; + + if (task.status.left and !cell_state.*.left) { + cell_state.*.left = true; + + switch (cell_value) { + '.', '-' => { + tasks.addIfNotNull(getLeftTask(task)); + }, + '\\' => { + tasks.addIfNotNull(getUpTask(task)); + }, + '/' => { + tasks.addIfNotNull(getDownTask(task, lines)); + }, + '|' => { + tasks.addIfNotNull(getUpTask(task)); + tasks.addIfNotNull(getDownTask(task, lines)); + }, + else => unreachable, + } + } + + if (task.status.right and !cell_state.*.right) { + cell_state.*.right = true; + + switch (cell_value) { + '.', '-' => { + tasks.addIfNotNull(getRightTask(task, lines)); + }, + '/' => { + tasks.addIfNotNull(getUpTask(task)); + }, + '\\' => { + tasks.addIfNotNull(getDownTask(task, lines)); + }, + '|' => { + tasks.addIfNotNull(getUpTask(task)); + tasks.addIfNotNull(getDownTask(task, lines)); + }, + else => unreachable, + } + } + + if (task.status.up and !cell_state.*.up) { + cell_state.*.up = true; + + switch (cell_value) { + '.', '|' => { + tasks.addIfNotNull(getUpTask(task)); + }, + '\\' => { + tasks.addIfNotNull(getLeftTask(task)); + }, + '/' => { + tasks.addIfNotNull(getRightTask(task, lines)); + }, + '-' => { + tasks.addIfNotNull(getLeftTask(task)); + tasks.addIfNotNull(getRightTask(task, lines)); + }, + else => unreachable, + } + } + + if (task.status.down and !cell_state.*.down) { + cell_state.*.down = true; + + switch (cell_value) { + '.', '|' => { + tasks.addIfNotNull(getDownTask(task, lines)); + }, + '/' => { + tasks.addIfNotNull(getLeftTask(task)); + }, + '\\' => { + tasks.addIfNotNull(getRightTask(task, lines)); + }, + '-' => { + tasks.addIfNotNull(getLeftTask(task)); + tasks.addIfNotNull(getRightTask(task, lines)); + }, + else => unreachable, + } + } + } + + var result: usize = 0; + for (0..state.len) |i| { + for (0..state[i].len) |j| { + if (@as(u8, @bitCast(state[i][j])) != 0) { + //std.debug.print("#", .{}); + result += 1; + } else { + //std.debug.print(".", .{}); + } + } + //std.debug.print("\n", .{}); + } + return result; +} + +fn solveLines(lines: []const []const u8) usize { + var result: usize = 0; + for (0..lines.len) |i| { + result = @max(result, solveForStart(lines, .{ + .x = @intCast(i), + .y = 0, + .status = .{ + .right = true, + }, + })); + result = @max(result, solveForStart(lines, .{ + .x = @intCast(i), + .y = @intCast(lines[i].len - 1), + .status = .{ + .left = true, + }, + })); + } + + for (0..lines[0].len) |j| { + result = @max(result, solveForStart(lines, .{ + .x = 0, + .y = @intCast(j), + .status = .{ + .down = true, + }, + })); + result = @max(result, solveForStart(lines, .{ + .x = @intCast(lines.len - 1), + .y = @intCast(j), + .status = .{ + .up = true, + }, + })); + } + + return result; +} + +pub fn solveAll(reader: anytype) !usize { + var result: usize = 0; + while (true) { + var allocator_buffer: [20000]u8 = undefined; + var fba = std.heap.FixedBufferAllocator.init(&allocator_buffer); + var allocator = fba.allocator(); + + var lines = StackList([]u8, usize, 150).init(); + var empty_line_reached = false; + + var line_buffer: [1000]u8 = undefined; + while (try reader.readUntilDelimiterOrEof(&line_buffer, '\n')) |line| { + if (line.len == 0) { + empty_line_reached = true; + break; + } + lines.add(try allocator.dupe(u8, line)); + } + + result += solveLines(lines.getMutableSlice()); + + if (!empty_line_reached) { + return result; + } + } +} + +pub fn main() !void { + const stdout = std.io.getStdOut().writer(); + + const raw_in = std.io.getStdIn(); + var buffered_reader = std.io.bufferedReader(raw_in.reader()); + var reader = buffered_reader.reader(); + const result = try solveAll(&reader); + try stdout.print("{d}\n", .{result}); +}