const std = @import("std"); fn getSurround(i: usize, width: usize, total: usize) [9]?usize { var result = [_]?usize{null} ** 9; for (0..3) |dx| for (0..3) |dy| { if (dx == 1 and dy == 1) continue; if (dx == 0 and i % width == 0) continue; if (dx == 2 and i % width == width - 1) continue; if (dy == 0 and i < width) continue; if (dy == 2 and i + width >= total) continue; result[dy * 3 + dx] = i + width * dy - width + dx - 1; }; return result; } pub fn main() !void { const allocator = std.heap.smp_allocator; const path: [:0]const u8 = std.mem.span(std.os.argv[1]); var file = try std.fs.cwd().openFile(path, .{}); defer file.close(); var buffer: [256]u8 = undefined; var reader = file.reader(&buffer); var width: usize = 0; var map = std.ArrayList(u3).empty; defer map.deinit(allocator); while (reader.interface.takeDelimiterInclusive('\n')) |line| { width = line.len - 1; for (line[0..width]) |c| { try map.append(allocator, if (c == '@') 1 else 0); } } else |err| switch (err) { error.EndOfStream => {}, else => |e| return e, } for (0..map.items.len) |i| { if (map.items[i] != 0) { var count: usize = 0; for (getSurround(i, width, map.items.len)) |jj| if (jj) |j| { if (map.items[j] != 0) { count += 1; } }; map.items[i] = if (count < 4) 1 else @intCast(count - 2); } } var queue = std.ArrayList(usize).empty; defer queue.deinit(allocator); for (0..map.items.len) |i| { if (map.items[i] == 1) { map.items[i] = 0; try queue.append(allocator, i); } } var cleaned: usize = queue.items.len; std.debug.print("part1: {}\n", .{cleaned}); while (queue.pop()) |i| { for (getSurround(i, width, map.items.len)) |jj| if (jj) |j| { if (map.items[j] == 2) { cleaned += 1; map.items[j] = 0; try queue.append(allocator, j); } else if (map.items[j] > 2) { map.items[j] -= 1; } }; } std.debug.print("part2: {}\n", .{cleaned}); }