const std = @import("std"); pub const title = "Day 07: Laboratories"; pub fn run(allocator: std.mem.Allocator) !void { const input = @embedFile("./input/day07.txt"); //const input = // \\.......S....... // \\............... // \\.......^....... // \\............... // \\......^.^...... // \\............... // \\.....^.^.^..... // \\............... // \\....^.^...^.... // \\............... // \\...^.^...^.^... // \\............... // \\..^...^.....^.. // \\............... // \\.^.^.^.^.^...^. // \\............... // ; var lines = std.mem.tokenizeScalar(u8, input, '\n'); const first_line = lines.next() orelse unreachable; const starting_position = for (first_line, 0..) |c, i| { if (c == 'S') break i; } else unreachable; const line_len = first_line.len; std.debug.print("starting_position = {d}\n", .{starting_position}); std.debug.print("{s}\n", .{first_line}); const previous_line = try allocator.alloc(Cell, line_len); defer allocator.free(previous_line); var i: usize = 0; while (lines.next()) |line| { defer i += 1; const current_line = try allocator.alloc(Cell, line_len); defer allocator.free(current_line); for (line, 0..) |c, ci| { switch (c) { '.' => current_line[ci] = .empty, '^' => current_line[ci] = .splitter, else => unreachable, // There shouldn't be beams on this line yet! } } defer @memcpy(previous_line, current_line); defer { for (current_line) |cell| { std.debug.print("{f}", .{cell}); } std.debug.print("\n", .{}); } if (i == 0) { std.debug.assert(current_line[starting_position] == .empty); current_line[starting_position] = .{ .beam = .{ .timelines = 1 } }; continue; } for (current_line, 0..) |cell, celli| { const previous_cell = previous_line[celli]; if (previous_cell == .beam) { if (cell == .empty) { current_line[celli] = .{ .beam = .{ .timelines = previous_cell.beam.timelines } }; } else if (cell == .splitter) { if (celli != 0) { const left = current_line[celli - 1]; if (left == .empty) { current_line[celli - 1] = .{ .beam = .{ .timelines = previous_cell.beam.timelines } }; } else if (left == .beam) { current_line[celli - 1] = .{ .beam = .{ .timelines = left.beam.timelines + previous_cell.beam.timelines } }; } } if (celli != line_len - 1) { const right = current_line[celli + 1]; if (right == .empty) { current_line[celli + 1] = .{ .beam = .{ .timelines = previous_cell.beam.timelines } }; } else if (right == .beam) { current_line[celli + 1] = .{ .beam = .{ .timelines = right.beam.timelines + previous_cell.beam.timelines } }; } } } else if (cell == .beam and previous_cell == .beam) { current_line[celli] = .{ .beam = .{ .timelines = cell.beam.timelines + previous_cell.beam.timelines } }; } } } } var accumulator: usize = 0; for (previous_line) |cell| { accumulator += switch (cell) { .empty, .splitter => 0, .beam => |beam| beam.timelines, }; } var buffer: [8]u8 = undefined; var stdout_writer = std.fs.File.stdout().writer(&buffer); const stdout = &stdout_writer.interface; try stdout.print("{d}\n", .{accumulator}); try stdout.flush(); } const Cell = union(enum) { empty: void, splitter: void, beam: struct { timelines: usize, }, const Self = @This(); pub fn format(self: Cell, w: *std.io.Writer) std.io.Writer.Error!void { switch (self) { .empty => try w.print(".", .{}), .splitter => try w.print("^", .{}), .beam => |beam| try w.print("{d}", .{beam.timelines}), } } };