From 082af016abcc2642d1c092b18a6d474266d62932 Mon Sep 17 00:00:00 2001 From: Kienan Stewart Date: Sun, 13 Dec 2020 12:53:10 -0500 Subject: [PATCH] Finish day 11 --- day11/build.zig | 27 +++ day11/input | 98 +++++++++ day11/src/main.zig | 482 +++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 607 insertions(+) create mode 100644 day11/build.zig create mode 100644 day11/input create mode 100644 day11/src/main.zig diff --git a/day11/build.zig b/day11/build.zig new file mode 100644 index 0000000..9731217 --- /dev/null +++ b/day11/build.zig @@ -0,0 +1,27 @@ +const Builder = @import("std").build.Builder; + +pub fn build(b: *Builder) 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 release options allow the person running `zig build` to select + // between Debug, ReleaseSafe, ReleaseFast, and ReleaseSmall. + const mode = b.standardReleaseOptions(); + + const exe = b.addExecutable("day11", "src/main.zig"); + exe.setTarget(target); + exe.setBuildMode(mode); + exe.install(); + + const run_cmd = exe.run(); + run_cmd.step.dependOn(b.getInstallStep()); + if (b.args) |args| { + run_cmd.addArgs(args); + } + + const run_step = b.step("run", "Run the app"); + run_step.dependOn(&run_cmd.step); +} diff --git a/day11/input b/day11/input new file mode 100644 index 0000000..6a466bd --- /dev/null +++ b/day11/input @@ -0,0 +1,98 @@ +LLLLL.LLLLLLLLLLLLLLLLLLLLLLLLLL.LLLLLLL.LLLLLLLLLL.LLLLLLLLLLL.LLLLLLLLLLLLLL.LLLL.LLLL.LLLLLL +LLLLL.LLLLLLLLLLLLLLLL.LLLLL.LLL.LLLLLLL.LLLLL.LLLL.LLLL.LLLLLLLLLLLLLLLL.LLLL.LLLL.LLLL.LLLLLL +LLLLL.LLLL.LLLL.LLLLLL.LLLLLLLLL.LLLLLLL.LLLLLLLLLLLLLLLLLLLLLL.LLLLLLLLL.LLLLLLLLL.LLLLLLLLLLL +LLLLL.LLLL.LLLL.LLLLLLLLLLLLLLLL.LLLLLLL.LLLLL.LLLLLLLLL.LLLLLLLLLLLLLLLL.LLLLLLLLL.LLLL.LLLLLL +LLLLL.LLLL.LLLL.LLLLLL.LLLLLLLLL.LLLLLLL.LLLLL.LLLLLLLLLLLLLLLL.LLLLLLLLLLLLLL.LLLL.LLLL.LLLLLL +LLLLL.LLLL.LLLLLLLLLLL.LLLLLLLLL.LLLLLLL.LLLLL.LLLLLLLLLLLLLLLL.LLLLLLLLLLLLLLLLLLL.LLLL.LLLLLL +LLLLLLLLLL.LLLLLLLLLLL.LLLLLLLLL.LLLLLLLLLLLLL.LLLL.LLLL.LLLLLLLLLLLLLLLL.LLLL.LLLL.LLLL.LLLLLL +LLLLLLLLLL.LLLLLLLLLLL.LLLLLLLLLLLLLLLLLLLLLLL.LLLLLLLLLLLLLLLL.LLLLLLLLL.LLLL.LLLL.LLLL.LLLLLL +L.L...L...LL.LL.......LL...LL.L...LL..LL..L.......LLLLL.....LL..LLLL.L....L..L...L.LL....LL...L +LLLLL.LLLLL.LLLLLLLLLL.LLLLLLLLL.LLLLLLL.LLLLL.LLLL.LLLL.LLLLLLLLLLLLLLLL.LLLL.LLLL.LLLL.LLLLLL +LLLLLLLLLLLLLLL.LLLLLLLLLLLLLLLL.LLLLLLLLLLLLL.LLLLLLLLLLLLL.LL.LLLLLLLLL.LLLL.LLLL.LLLLLLLLLLL +LLLLL.LLLL.LLLL.LLLLLL.LLLLLLLLL.LL.LLLLLLLLLL.LLLL.LLLLLLLLLLLLLLLL.LLLL.LLLL.LLLLLLLLL.LLLLLL +LLLLLLLLLL.LLLLLLLLLLL.LLLLLLLLL.LLLLLLLLLLLLL.LLLLLLLLL.LLL.LL.LLLLLLLLL.LLLL.LLLL.LLLL.L.LLLL +LLLLL.LLLL.LLLL.LLL.LLLLLLLLLLLLLLLLLLLL.LLLLLLLLLL.LLLLLLLLLLL.LLLLLLLLL.LLLL.LLLL.LLLLLLLLLLL +LLLLLLLLLL.LLLLLLLLLLLLLLLLLLLLLLLLLLLLL.LLLLLLLLLL.LLLL.LLL.LL.LLLLLLLLLLLLLLLLLLL.LLLL.LLLLLL +.L.....L.LL..LLL.L..L...L.LLL.L...L.L.L.L.....L..L.......L.LLL...L.......L.LLLL......L.L.L...LL +LLLLLLLLLL.LLLL.LLLLLLLLLLLLLLLLLLLLLLLL.LLLLLLLLLLLLLL..LLLLLL.LLLL.LLLL.L.LL.LLLLLLLLL.LLLLLL +LLLLLLLLLL.LLLL.LLLLLL.LLLLLLLLL.LLLLLLLLLLLLL.LLLL.LLLL.LLLLLLLLLLLLLLLL.LLLLLLLLL.LLLLLLLLLLL +LLLLL.LLLL.LLLLLLLLLLL.LLLLLLLLL.LLLLLLLLLLLLL.LL.LLLLLLLLLLLLL.LLLLLLLLLLLLLL.LLLL.LLLL.LLLLLL +LLLLL.LLLL.LLLL.LLLLLL.LLLLLLLLLLLLLLLLL.LLLLL.LLLL.LLLL.LLLLLL.LLLLLLLLLLLLLL.LLLL.LLLL.LLLLLL +.L..LLL.L...LL.....LL......LL...L...LL...L.L..L....L.L.L.LL.L........L....LL......L..LL..LL.... +LLLLL.LLLL.LLLL.LLLLLLLLLLLLLLLL.LLLLLLL.LLLLL.LLLL.LLLL.LLLLLLLLLLLLLLLLLLLLL.LLLL.LLLLLLLLLLL +LLLLLLLLLL.LLLLLLLLLLL.LLLLLLLLL.LLLLLLLLLLLLLLLLLLLLLLL.LLLLLL.LLLLLLLLL.LLLLLLLLL.LLLL.LLLLLL +LLLLL.LLLLLLLLL.LLLLLL.LLLLLLLLLLLLLLLLL.LLLLL.LLL..LLLL.LLLLLL.LLLLLLLLLLL.LL.LLLL.LLLLLLLLLLL +LLLLL.LLLL.LLLLLLLLLLLLLLLLLLLLL.LLLLLLL.LLLLL.LLLL.LLLL..L.LLL.LLLLLLLLL.LLLL.LLLLLLLLLLLLLLLL +LLLLLLLLLL.LLLL.LLLLLL.LLLLLL.LLLLLLLLLL.LLLLL.LLLL.LLLLLLLLLLL.LLLLLLLLLLLLLL.LLLL.LLLLLLLLLLL +L.LLL.LLLLLLLLL.LLLLLL.LLLLLLLLL.LLLLLLL.LLLLL.LLLLLLLLL.LLLLLL.LLLLLLLLL.LLLLLLLLLLLLLLLLLLLLL +LLLL....L.......L..LLL...........L..L...LL..L.L.LLL...L.....LL..LL..L....L....L..LL..LL.L....L. +LLLLL.LLLL.LLLL.LLLLLLLLLLLLLLLL.LLLLLLLLLLLLL.LLLL.LLLL.LLLLLLLLLLLLLLLL.L.LLLLLLLLLLLL.LLLLLL +LLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLL.LLL.LLLLL.LLLL.LLLL.LLLLLLLLLLLLLLLLLLLLLLLLLL.LLLL.LLLLLL +LLLLLLLLLLLLLLL.LLLLLL.LLLLLLLLL.LLLLLLL.LLLLL.LLLL.LLLL.LLLLLLLLLLLLLLLL.LLLL.LLLLL.LLLLLLLLLL +LLLLLLLLLL.LLLL.LLLLLL.LLLLLLLLL.LLLLLLLLLLLLL.LLLL.LLLL.LLLLLL..LLL.LLLL.LLLL.LLLL.LLLLLLLLLLL +LLLLL.LLLLLLLLLLLLLLLLLLLLLLLLLL.LLLLLLL.LLL.L.LLLL.LL.L.LL.LLLLLLLLLLLLL.LLLL.LLLL.LLLL.LLLLLL +.LL........L.....L.L.L.......LL.L.L.......LLL.........L....LL........L.L..L......L.LL......L..L +LLLLL.LLLL.LLLL.LLLLLLLLLLLLLLLLLLLLLLLLLLLLLL.LLLL.LLLL.LLLLLLLLLLLLLLLL.LLLL.LLLL.LLLL.LLLLLL +LLLLL.LLLLLLLLL.LLLLLL.LLLLLLLLL.LLLLLLLLLLLLL.LLLL.LLLL.LLLLLL.LLLLLLLLLLLLLL.L.LLLLLLLLLLLLLL +LLLLLLLLLLLLLLL.LLLLLLLLLLLLLLLLLLLLLLLL.LLLLLLLLLL.LLLLLLLLLLLL.LLLLLLLLLLLLL.LLLLLLLLLLLLLLLL +LLLLL.LLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLL.L.LLLL.LLLLLL.LLLLLLLLL.LLLL.LLLLLLLLL.LLLLLL +LLLLL.LLLLLLLLLLLLLLLL.LLLLLLLLL.LLLLLLLLLLLLLLLLLL.LLL..LLLLLL.LLLLLLLLL.LLLLLLLLL.LLLL.LLLLLL +LLLLL.LLLL.LLLL.LLLLLL.LLLLLLLLL.LLLLLLLLLLLLLLLLLL.LL.L.LLLLLLLLLLLLLLLL.LLLL.LLLLLLLLL.LLLLLL +.L..L...L........L.......L.L.LL.LLLL...LLL.L.L..L.L....L.................L.L.L.L....L...L...L.. +LLLLL.LLLLLLLLLLLLLLLL.LLLLLLLLL.LLLLLLLLLLLLLLLLLL.LLLL.LLLLLL.LLLLLLLLLLLLLL.LLLL.LLLL.LLLLLL +LLLLLLLLLL.LLLL.LLLLLL.LLLLLLLLLLLLLLLLLLLLLLL.LLLL.LLLL.LLLLLL.LLLLLLLLLLLLLL.LLLL.LLLL.LLLLLL +LLLLL.LLLL.LLLL.LLLLLL.LLLLLLLLL.LLLLLLL.LLLLL.LLLL.LLLL.LLLLLLLLLLLLLLLLLLLLL.LLLL.LLLL.LLLLLL +LLLLL.LLLL.LLLL.LLLLLL.LLLLLLLLL.LLLLLLL.LLLLLLLLLLLLLLL.LLLLLLLLLLLLLLLL.LLLL.LLLL.LLLLLL.LLLL +LLLLL.LL.LLLLLLL.LLLLLLLLLLLLLLL.LLLLLLLLLLLLLLLLLL.LLLL.LLLLLLLLLLLLLLLL.LLLL.LLLLLLLLL.LLLLLL +LLLLL.LLLLLLLLL.LLLLLL.LLLLLLLLL.LLLLLLLLLLLLL.LLLL.LLLLLLLLLLL.LLLLLLLLLLLLLL.LLLL.LLLL.LLLLLL +LLLL...LLL.......LL..L.L.L.L...L........LL..............L.L......L.......L..LL....L....LL...LL. +LLLLL.LLLL.LLLL.LLLLLL.LLLLLLLLL.LLLLLLLLLLLLLLLLLL.LLLL.LLLLLL.L.LLLLLLL.LLLLLLLLL.LLLLLLLLLLL +LLLLL.LLLL.LLLL.LLLLLL..LLLLLLLL.LLLLLLLLLLLLLLLLLL.LLLL.LLLLLL.LLLLLLLLL.LLLLLLL.L.LLLL.LLLLLL +LLLLL.LLLL.LLLLLLLLLLL.LLLLLLLLL.LLLLLLL.LLLLL.LLLLLLLLL.LLLLLLLLLLLLLLLLLLLLL.LLLL.LLLLLLLLLLL +LLLLL.LLLL.LLLL.LLLLLL.LLLLLLLLLLLLLLLLL.LLLLL.LLLLLLLLLLLLLLLL.LLLLLLLLLLLLLL.LLLLLLLLL.LLLLLL +LLLLLLLLLL.LLLL.LLLLLL.LLLLLLLLL.LLLLLLLLLLLLL.LLLL.LLLL.LLLLLLLLLLLLLLLLLLLLLLLLLL.LLLL.LLLLLL +LLLLL.LLLL.LLLL.LLLLLL.LLLLLLLLLLLLLLLLL.LLLLL.LLLL.L.LL.LLLLLL.LLLLLLLLLLL.LL.LLLLLLLLL.LLL.LL +LLLLL.LLLL.LLLLLLLLLLLLLLLLLLLLL.LLLLLLL.LLLLLLLLLL.LLLLLLLLLLL.LLLLLLLLL.LLLL.LLLLLLLLLLLLLLLL +LLLLLLLLLL.LLLL.LLLLLL.LLLLLLLLLLLLLLLLLLLLLLL.LLLL.LLLLLLLLLLL.LLLLLLLLL.LLLL.LLLL.LLLL.LLLLLL +LL.LL.LLLLLLLLL.LLLLLLLLLLLLLLLL.LLLLLLLLLLLLL.LLLL.LLLL.LLLLLLLLLLLLLLLL.LLLLLLLLL.LLLL.LLLLLL +LLLL.L...LL.......LL..L.....L.LL..L....L.L..L.......L..L......LLLLL..L.L..L......L...L.L...L.L. +LLLLL.LLL..LLLL.LLLLLL.LLLLL.LLL.LLLLL.L.LLLLL.LLLLLLLLL.LLLLLL.LLLLLLLLLLLLLL.LLLLLLLL..LLLLLL +LLLLL.LLLLLLLLL.LLLLLLLLLLLLLLLL.LLLLLLL.LLLLL.LLLLLLLLL.LLLLLL.LLLLLLLLL.LLLLLLLLL.LLLL.LLLLLL +LLLLL.LLLL.LLLLLLLLLLL.LLLLLLLLL.LLLLLL.LLLLLL.LLLL.LLLLLLLLLLLLLLLLLLLLL.LLLL.LLLL.LLLLLLLLLLL +LLLLLLLLLL.LLLLLLLLLLL.LLLLLLLLLLLLLLLLLLLLLLL.LLLL.LLLL.LLLLLL.LLLLLLLLLLLLLL.LLLL.LLLL.LLLLLL +LLLLLLLLLLLLLLL.LLLLLLLLLLLLLLLLLLLLLLLL.LLLLL.LLLL.LLLLLLLLLLLL.LLLLLLLL.LLLL.LLLL.LLLL.LLLLLL +L.L...............L..L.LLLL...L..L...LLL.......LLL.LL........L..LL..L..L...L.L.L.LL..LLLL.L.LL. +LLLLLLLL.L.LLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLL.LLLL.LLLL.LLLLLLLLLLLLLLLL.LLLL.LLLLLLLLL.LLLLLL +LLLLL.LLLL.LLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLL.LLLLLL.LLLLLLLLLLLLLLLLLLL.LLLLLLLLLLL +LLLLLLLLLLLLLLL.LLLLLL.LLLLLLLLL.LLLLLLL.LLLLLLLLLLLLLLLLLLLLLL.LLLLLLLLLLLLLL.LLLL.LLLLLLLLLLL +LLLLLLL.LLLLLLLLLLLLLLLLLLLLLLLL.LLLLLLLLLLLLLLLLLL.LLLLLLLLLLL.LLLLLLLLLLLLLLLLLLLLLLLL.LLLLLL +LLLLL.LLLLLLLLL.LLLLLL.LLLLLLLLL.LLLLLLL.LLLLL.LLLL.LLLL.LLLLLL.LLLLLLLLL.LLLL.LLLLLLLLLLLLLLLL +L.LLL.LLLL.LLLLLLLLLLLLLLLLLLLLL.LLLLLLL.LLLLL.LLLL.LLLL.LLLLLLLLLLLLLLLL.LLLL.LLLL.LLLLLLLLLLL +LLLLL.LLLL.LLLL.LLLLLL.LLLLLLLLL.LLLLLLL.LLLLL.LLLLLLLLLLLLLLLLLLLLLLLLLLLLLLL.LLLL.LLLL.LLLLLL +LLLLL.LLLLLLLLL.LLLLLLLLLLLLLLLL.LLLLLLLLLLLLL.LLLL.LLLL.LLLLLLLLLLLLL.LLLLLLL.LLLL.LLLL.LLLLLL +.L..LL.L.L..L...L....L......LLL......L.LL..L....L.LLLL.LL.....L.L.LL.L.....L......L.LL......... +LLLLL.LLLLLLLLL.LLLLLL.LLLLLLLLLLLLLLLLL.LLLL..LLLL.LLLL.LLLLLL.LLLLLLLLL.LLLL.LLLLLLLLL.LLLLLL +LLLLL.LLLL.LLLL.LLLLLL.LLLLLLLLL.LLLLLLL.LLLLL.LLLL.LLLLLLLLLLL.LLLLLLLLLLLLLL.LLLLLLLLL.LLLLLL +LLLLL.LLLL.LLLL.LLLLLLLLLLLLLLLL.LLLLLLLLLLLLL.LLLL.LLLL.LLLLLLLLLLLLLLLLLLLLLLLLLL.LLLLLLLLLLL +LLLLL.LLL..LLLL.LLLLLL.LLLLLLLLL.LLLLLLL.LLLLL.LLLL.LLLLLLLLLLL.LLLLLLLLL..LLL.LLLLLLLLLLLLLLLL +.LLL......L.L.L......L.....LL......L.LLL.LLL..LL...L.L.......L..L.......L....L.....L.......LL.. +LLLLL.LLLL.LLLL.LLLLLL.LLLLLLLLL.LLLLLLL.LLLLL.LLLL.LLLL.LLLLLLLLLLLLLLLL.LLLL.LLLLLLLLL.LLLLLL +LLLLL.LLLL.LLLLLLLLLLLLLLLLLLLLL.LLLLLLL.LLLLL.LLLL.LLLL.LLLLLL.LLLLLLLLL.LLLL.LLLL.LLLL.LLLLLL +LLLLLLLLLL.LLLL.LLLLLL.LLLLLLLLL.LLLLLLL.LLLLLLLLLLLLLLL.LLLLLL.LLLLLLLLL.LLLL.LLLL.LLLL.LLLLLL +LLLLL.LLLLLLLLLLLLLLLL.LLLLLLLLLLLLLLLLLLLLLLL.LLLLLLLLL.LLLLLL.LLLLLLLLL.LLLLLLLLLLLLLL.LLLLLL +LLLLL.LLLLLLLLL.LLLLLL.LLLLLLLLLLLLLLLLLLLLLLL.LLLL.LLLL.LLLLLLLLLLLLLLLL.LLLL.LLLL.LLLL.LLLLLL +LL...L...........L...L..L......LL...........L...L.LL..LL....L....LLL.LLLL....LLL...LL..L..L...L +LLLLLLLLLLLLLLL.LLLLLL.LLLLLLLLL.LLLLLLLLLLLLL.LLLL.LLLL.LLLLLL.LLLLLLLLL.LLLL.LLLL.LLLL.LLLLLL +LLLLL.LLLL.LLLLLLLLLLLLLLLLLLLLL.LLLLLLL.LLLLLLLLLL.LLLL.LLLLLL.LLLLLLLLL.LLLL.LLLL.LLLLLLLLLLL +LLLLLLLLLL.LLLL.LLLLLL.LLL.LLLLLLLLLLLLL.LLLLLLLLLL.LLLLLLLLLLLLLLLLLLLLL.LLLL.LLLL.LLLLLLLLLLL +.LLLL.LLLLLLLLLLLLLLLLLLLLLLLLLL.LLLLLLL.LLLLLLLLLLLLLLL.LLLLLL.LLLLLLLLLLLLLLLLLLL.LLLL.LLLLLL +LLLLL.LLLL.LLLLLLLLLLLLLLLLLLLLLLLLLLLLL.LLLLL.LLLLLLLLLLLLLLLL.LLLLLLLLL.LLLL.LLLL.LLLL.LLLLLL +LLLLL.LLLLLLLLL.LLLLLL.LLLLLLLLLLLLLLLLLLLLLLL.LLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLL.LLLLLL +LLLLL.LL.LLLLLLLLLLLLL.LLLLLLLLL.LLLLLLL.LLLLLLLLLL.LLLLLLLLLLL.LLLLLLLL..LLLL.LLL..LLLLLLLLLLL +.......L...LL.L.....L.L.....LLL.L.......L.....LL.......L..LLL.....L.LL.L..........LL........... +LLLLL.LLLLLLLLL.LLLLLL.LLLLLLLLL.LLLLLLLLLLLLL.LLLLLL.LL.LL.LLL.LLLLLLLLLLLLLL.LLLL.LLLLLLLLLLL +LLLLLLLLLL.LLLL.LLLLLL.LLLLLLLLL.LLLLLLL.LLLLL.LLLLLLLLLLLLLLLL.LLLLLLLLL.LLLL.LLLL.LLLL.LLLLLL +LLLLL.LLLL.LLLLLLLLLLL.LLLLLLLLLLLLLLLLL.LLLLLLLLLL.LLLL.LLLLLL.LLLLLLLL..LLLLLLLLL.LLLL.LLLLLL +LLLLL.LLLL.LLLL.LLLLLL.LLLLLLLLL.LLLLLLLLLLLLL.LLLLLLLLLLLLLLLLLLLLLLLLLLLLLLL.LLLL.LLLL.LLLLLL +LLLLL.LLLL.LLLL.LLLLLL.LLLLLLLLL.LLLLLLL.LLLLL.LLLL.LLLL.LLLLLLLLLLLLLLLL.LLLL.LLLL.LLLL.LLLLLL +LLLLL.LLLLLLLLLLLLLLLL.LLLLLLLLL.LLLLLLL.LLLLL.LLLLLLLLLLLLLLLLLLLLLLLLLLLLLLL.LLLLLLLLL.LLLLLL diff --git a/day11/src/main.zig b/day11/src/main.zig new file mode 100644 index 0000000..3da8f89 --- /dev/null +++ b/day11/src/main.zig @@ -0,0 +1,482 @@ +const std = @import("std"); + +pub fn main() anyerror!void { + var arena = std.heap.ArenaAllocator.init(std.heap.page_allocator); + var gpa = &arena.allocator; + + var f = try std.fs.cwd().openFile("input", .{}); + var contents = try f.readToEndAlloc(gpa, std.math.maxInt(u32)); + + var seatmap = try SeatMap.init(gpa); + var it = std.mem.tokenize(contents, "\n"); + while (it.next()) |line| { + try seatmap.add_line(line); + } + + var changed : usize = 0; + changed = try seatmap.process_round(); + while (changed != 0) { + //changed = try seatmap.process_round(); + changed = try seatmap.process_round_part2(); + } + std.log.info("{} occupied seats", .{seatmap.count_occupied()}); +} + +const NeighbourState = struct { + count: usize = 0, + occupied: usize = 0, + free: usize = 0, +}; + +const SeatMap = struct { + allocator: *std.mem.Allocator, + data: std.ArrayList(u8), + width: usize = 0, + height: usize = 0, + + pub fn init(a: *std.mem.Allocator) !*SeatMap { + var self = try a.create(SeatMap); + errdefer a.destroy(self); + + // if we use self.* = .{}; then we don't forget + // obligatory fields + // also, when using self.* = .{} the fields with + // defaults are properly initialized!!! it is + // an error to not use it. + self.* = .{ + .allocator = a, + .data = std.ArrayList(u8).init(a), + }; + return self; + } + + pub fn deinit(self: *SeatMap) void { + self.data.deinit(); + self.allocator.destroy(self); + } + + pub fn count_occupied(self: *SeatMap) u64 { + var c: u64 = 0; + for (self.data.items) |i| { + if (i == '#') { + c += 1; + } + } + return c; + } + + pub fn print(self: *SeatMap) !void { + var stdout = std.io.getStdOut(); + var i : usize = 0; + while (i < self.height) : (i += 1) { + _ = try stdout.write(self.get_row(i)); + _ = try stdout.write("\n"); + } + } + + pub fn get_row(self: *SeatMap, row: usize) []u8 { + return self.data.items[self.width*row..(self.width*row)+self.width]; + } + + pub fn add_line(self: *SeatMap, line: []const u8) !void { + if (self.width != 0) { + std.debug.assert(line.len == self.width); + } + else { + self.width = line.len; + } + try self.data.appendSlice(line[0..]); + self.height += 1; + } + + // returns the number of seats changed + pub fn process_round(self: *SeatMap) !u64 { + // First, since operations happen concurrently, + // we mark all of our changes to a temporary buffer + var buffer = try self.allocator.alloc(u8, self.data.items.len); + defer self.allocator.free(buffer); + + // Iterate above (row, col) pairs + var row : usize = 0; + var n_changed : u64 = 0; + while (row < self.height) : (row += 1) { + var col : usize = 0; + while (col < self.width) : (col += 1) { + if (self.index_of(row, col)) |i| { + buffer[i] = self.get_new_seat_state(row, col, i); + if (buffer[i] != self.data.items[i]) { + n_changed += 1; + } + } + } + } + + // Copy buffer to self.data.items + std.mem.copy(u8, self.data.items, buffer); + return n_changed; + } + + pub fn get_new_seat_state(self: *SeatMap, row: usize, col: usize, index: usize) u8 { + // Floor remains unchanged + var c = self.data.items[index]; + var new_c : u8 = undefined; + if (c == '.') { + new_c = '.'; + } + + // this gives us a struct w/ .count, .occupied, .free + var neighbour_state = self.get_neighbour_state(row, col); + if (c == 'L') { + if (neighbour_state.occupied == 0) { + new_c = '#'; + } + else { + new_c = c; + } + } + if (c == '#') { + if (neighbour_state.occupied >= 4) { + new_c = 'L'; + } + else { + new_c = c; + } + } + //std.log.debug("({},{}) was '{c}' and will be '{c}'. {} neighbors, {} occupied", + // .{row, col, c, new_c, neighbour_state.count, neighbour_state.occupied}); + return new_c; + } + + pub fn get_neighbour_state(self: *SeatMap, row: usize, col: usize) NeighbourState { + var r: usize = switch(row) { + 0 => row, + else => row - 1, + }; + var count: usize = 0; + var free: usize = 0; + var occupied: usize = 0; + while (r <= row+1) : (r += 1) { + var c: usize = switch(col) { + 0 => col, + else => col - 1, + }; + while (c <= col+1) : (c += 1) { + if (row == r and col == c) { + continue; + } + if (self.index_of(r, c)) |i| { + if (self.data.items[i] == '.') { + // Floor spots don't contribute to neighbour, + // free, or occupied counts. + continue; + } + count += 1; + if (self.data.items[i] == '#') { + occupied += 1; + } + else { + free += 1; + } + } + } + } + return NeighbourState { + .count = count, + .free = free, + .occupied = occupied, + }; + } + + // returns the number of seats changed + pub fn process_round_part2(self: *SeatMap) !u64 { + // First, since operations happen concurrently, + // we mark all of our changes to a temporary buffer + var buffer = try self.allocator.alloc(u8, self.data.items.len); + defer self.allocator.free(buffer); + + // Iterate above (row, col) pairs + var row : usize = 0; + var n_changed : u64 = 0; + while (row < self.height) : (row += 1) { + var col : usize = 0; + while (col < self.width) : (col += 1) { + if (self.index_of(row, col)) |i| { + buffer[i] = self.get_new_seat_state_round2(row, col, i); + if (buffer[i] != self.data.items[i]) { + n_changed += 1; + } + } + } + } + + // Copy buffer to self.data.items + std.mem.copy(u8, self.data.items, buffer); + return n_changed; + } + + pub fn get_new_seat_state_round2(self: *SeatMap, row: usize, col: usize, index: usize) u8 { + // Floor remains unchanged + var c = self.data.items[index]; + var new_c : u8 = undefined; + if (c == '.') { + new_c = '.'; + } + + // this gives us a struct w/ .count, .occupied, .free + var neighbour_state = self.get_neighbour_state_round2(row, col); + if (c == 'L') { + if (neighbour_state.occupied == 0) { + new_c = '#'; + } + else { + new_c = c; + } + } + if (c == '#') { + if (neighbour_state.occupied >= 5) { + new_c = 'L'; + } + else { + new_c = c; + } + } + //std.log.debug("({},{}) was '{c}' and will be '{c}'. {} neighbors, {} occupied", + // .{row, col, c, new_c, neighbour_state.count, neighbour_state.occupied}); + return new_c; + } + + pub fn get_neighbour_state_round2(self: *SeatMap, row: usize, col: usize) NeighbourState { + var count: usize = 0; + var free: usize = 0; + var occupied: usize = 0; + var direction_vectors = [_][2]i64 { + [_]i64{-1, -1}, // up and left, + [_]i64{-1, 0}, // left + [_]i64{-1, 1}, // down and left, + [_]i64{0, 1}, // down + [_]i64{1, 1}, // right and down + [_]i64{1, 0}, // right + [_]i64{1, -1}, // right and up, + [_]i64{0, -1}, // up + }; + var row_signed = @intCast(i64, row); + var col_signed = @intCast(i64, col); + for (direction_vectors) |dv| { + var space_count : i64 = 0; + var has_neighbour: bool = false; + var last_neighbour_was_occupied = false; + while (true) { + space_count += 1; + var r : i64 = row_signed + (dv[0]*space_count); + var c : i64 = col_signed + (dv[1]*space_count); + if (r < 0 or c < 0) { + // invalid spot with negative indices + break; + } + if(self.index_of(@intCast(usize, r), @intCast(usize, c))) |index| { + if (self.data.items[index] == '.') { + // We see through floor spaces + continue; + } + else { + has_neighbour = true; + if (self.data.items[index] == '#') { + last_neighbour_was_occupied = true; + } + break; + } + } + else { + // The index was not valid, so we're out of bounds in some way + break; + } + } + if (has_neighbour) { + count += 1; + if (last_neighbour_was_occupied) { + occupied += 1; + } + else { + free += 1; + } + } + } + return NeighbourState { + .count = count, + .free = free, + .occupied = occupied, + }; + } + + pub fn index_of(self: *SeatMap, row: usize, col: usize) ?usize { + if (col >= self.width) { + return null; + } + if (row >= self.height) { + return null; + } + var i = (row*self.width) + col; + if (i < 0 or i >= self.data.items.len) { + return null; + } + return i; + } +}; + +test "part_one" { + var d = [_][]const u8 { + "L.LL.LL.LL", + "LLLLLLL.LL", + "L.L.L..L..", + "LLLL.LL.LL", + "L.LL.LL.LL", + "L.LLLLL.LL", + "..L.L.....", + "LLLLLLLLLL", + "L.LLLLLL.L", + "L.LLLLL.LL", + }; + + var print = true; + var stdout = std.io.getStdOut(); + + var sm = try SeatMap.init(std.testing.allocator); + defer sm.deinit(); + for (d) |l| { + try sm.add_line(l[0..]); + } + + var states = [_][]const u8 { + // 0 + "L.LL.LL.LLLLLLLLL.LLL.L.L..L..LLLL.LL.LLL.LL.LL.LLL.LLLLL.LL..L.L.....LLLLLLLLLLL.LLLLLL.LL.LLLLL.LL", + // 1 + "#.##.##.#########.###.#.#..#..####.##.###.##.##.###.#####.##..#.#.....###########.######.##.#####.##", + // 2 + "#.LL.L#.###LLLLLL.L#L.L.L..L..#LLL.LL.L##.LL.LL.LL#.LLLL#.##..L.L.....#LLLLLLLL##.LLLLLL.L#.#LLLL.##", + // 3 + "#.##.L#.###L###LL.L#L.#.#..#..#L##.##.L##.##.LL.LL#.###L#.##..#.#.....#L######L##.LL###L.L#.#L###.##", + // 4 + "#.#L.L#.###LLL#LL.L#L.L.L..#..#LLL.##.L##.LL.LL.LL#.LL#L#.##..L.L.....#L#LLLL#L##.LLLLLL.L#.#L#L#.##", + // 5 + "#.#L.L#.###LLL#LL.L#L.#.L..#..#L##.##.L##.#L.LL.LL#.#L#L#.##..L.L.....#L#L##L#L##.LLLLLL.L#.#L#L#.##" + }; + // Confirm that initial map is correct + std.testing.expect(std.mem.eql(u8, sm.data.items, states[0])); + + if (print) { + _ = try stdout.write("\nInitial map:\n"); + try sm.print(); + _ = try stdout.write("\n"); + } + + var round: u64 = 0; + var changed = try sm.process_round(); + while (changed != 0) { + round += 1; + var matches = std.mem.eql(u8, sm.data.items, states[round]); + //std.log.warn("Round {} matches expected state: {}", .{round, matches}); + //std.log.warn("len {}: {}", .{sm.data.items.len, sm.data.items}); + //std.log.warn("len {}: {}", .{states[round].len, states[round]}); + //std.log.warn("index of first diff {}", + // .{std.mem.indexOfDiff(u8, sm.data.items, states[round])}); + std.testing.expect(matches); + if (print) { + var title = try std.fmt.allocPrint(std.testing.allocator, "\nRound {}:\n", + .{round}); + _ = try stdout.write(title); + std.testing.allocator.free(title); + try sm.print(); + _ = try stdout.write("\n"); + } + changed = try sm.process_round(); + } + if (print) { + _ = try stdout.write("Final state: \n"); + try sm.print(); + _ = try stdout.write("\n"); + } + std.testing.expect(std.mem.eql(u8, sm.data.items, states[round])); + + var n_occupied = sm.count_occupied(); + std.testing.expectEqual(n_occupied, 37); +} + +test "part two" { + var d = [_][]const u8 { + "L.LL.LL.LL", + "LLLLLLL.LL", + "L.L.L..L..", + "LLLL.LL.LL", + "L.LL.LL.LL", + "L.LLLLL.LL", + "..L.L.....", + "LLLLLLLLLL", + "L.LLLLLL.L", + "L.LLLLL.LL", + }; + + var print = true; + var stdout = std.io.getStdOut(); + + var sm = try SeatMap.init(std.testing.allocator); + defer sm.deinit(); + for (d) |l| { + try sm.add_line(l[0..]); + } + + var states = [_][]const u8 { + // 0 + "L.LL.LL.LLLLLLLLL.LLL.L.L..L..LLLL.LL.LLL.LL.LL.LLL.LLLLL.LL..L.L.....LLLLLLLLLLL.LLLLLL.LL.LLLLL.LL", + // 1 + "#.##.##.#########.###.#.#..#..####.##.###.##.##.###.#####.##..#.#.....###########.######.##.#####.##", + // 2 + "#.LL.LL.L##LLLLLL.LLL.L.L..L..LLLL.LL.LLL.LL.LL.LLL.LLLLL.LL..L.L.....LLLLLLLLL##.LLLLLL.L#.LLLLL.L#", + // 3 + "#.L#.##.L##L#####.LLL.#.#..#..##L#.##.###.##.#L.###.#####.#L..#.#.....LLL####LL##.L#####.L#.L####.L#", + // 4 + "#.L#.L#.L##LLLLLL.LLL.L.L..#..##LL.LL.L#L.LL.LL.L##.LLLLL.LL..L.L.....LLLLLLLLL##.LLLLL#.L#.L#LL#.L#", + // 5 + "#.L#.L#.L##LLLLLL.LLL.L.L..#..##L#.#L.L#L.L#.#L.L##.L####.LL..#.#.....LLL###LLL##.LLLLL#.L#.L#LL#.L#", + // 6 + "#.L#.L#.L##LLLLLL.LLL.L.L..#..##L#.#L.L#L.L#.LL.L##.LLLL#.LL..#.L.....LLL###LLL##.LLLLL#.L#.L#LL#.L#", + }; + // Confirm that initial map is correct + std.testing.expect(std.mem.eql(u8, sm.data.items, states[0])); + + if (print) { + _ = try stdout.write("\nInitial map:\n"); + try sm.print(); + _ = try stdout.write("\n"); + } + + var round: u64 = 0; + var changed = try sm.process_round(); + while (changed != 0) { + round += 1; + var matches = std.mem.eql(u8, sm.data.items, states[round]); + //std.log.warn("Round {} matches expected state: {}", .{round, matches}); + //std.log.warn("len {}: {}", .{sm.data.items.len, sm.data.items}); + //std.log.warn("len {}: {}", .{states[round].len, states[round]}); + //std.log.warn("index of first diff {}", + // .{std.mem.indexOfDiff(u8, sm.data.items, states[round])}); + std.testing.expect(matches); + if (print) { + var title = try std.fmt.allocPrint(std.testing.allocator, "\nRound {}:\n", + .{round}); + _ = try stdout.write(title); + std.testing.allocator.free(title); + try sm.print(); + _ = try stdout.write("\n"); + } + changed = try sm.process_round_part2(); + } + if (print) { + _ = try stdout.write("Final state: \n"); + try sm.print(); + _ = try stdout.write("\n"); + } + std.testing.expect(std.mem.eql(u8, sm.data.items, states[round])); + + var n_occupied = sm.count_occupied(); + std.testing.expectEqual(n_occupied, 26); +}