const std = @import("std"); const Allocator = std.mem.Allocator; const StringTokenIterator = std.mem.TokenIterator(u8, .scalar); const MAX_WIDTH = 137; const Grid = struct { data: [MAX_WIDTH][]u8, maxX: usize, maxY: usize, pub fn isRoll(self: *const Grid, x: isize, y: isize) bool { if (x < 0 or x >= self.maxX) { return false; } if (y < 0 or y >= self.maxY) { return false; } return self.data[@intCast(x)][@intCast(y)] == '@'; } }; fn newGrid(lines: *StringTokenIterator) !Grid { const line_len = lines.peek().?.len; var grid: [MAX_WIDTH][]u8 = undefined; var i: usize = 0; while (lines.next()) |line| : (i += 1) { grid[i] = @constCast(line); } return .{ .data = grid, .maxX = line_len, .maxY = i }; } pub fn run(_: Allocator, input: []u8) !struct { u64, u64 } { var lines = std.mem.tokenizeScalar(u8, input, '\n'); const grid = try newGrid(&lines); var answer1: u64 = 0; var answer2: u64 = 0; // Need to figure out how to not make this ugly, but too tired for (0..grid.maxX) |i| { for (0..grid.maxY) |j| { if (grid.isRoll(@as(isize, @intCast(i)), @as(isize, @intCast(j)))) { var adjacent_count: usize = 0; adjacent_count += @intFromBool(grid.isRoll(@as(isize, @intCast(i)) - 1, @as(isize, @intCast(j)) - 1)); adjacent_count += @intFromBool(grid.isRoll(@as(isize, @intCast(i)) - 1, @as(isize, @intCast(j)))); adjacent_count += @intFromBool(grid.isRoll(@as(isize, @intCast(i)), @as(isize, @intCast(j)) - 1)); adjacent_count += @intFromBool(grid.isRoll(@as(isize, @intCast(i)) + 1, @as(isize, @intCast(j)) - 1)); adjacent_count += @intFromBool(grid.isRoll(@as(isize, @intCast(i)) - 1, @as(isize, @intCast(j)) + 1)); adjacent_count += @intFromBool(grid.isRoll(@as(isize, @intCast(i)) + 1, @as(isize, @intCast(j)) + 1)); adjacent_count += @intFromBool(grid.isRoll(@as(isize, @intCast(i)) + 1, @as(isize, @intCast(j)))); adjacent_count += @intFromBool(grid.isRoll(@as(isize, @intCast(i)), @as(isize, @intCast(j)) + 1)); if (adjacent_count < 4) { answer1 += 1; } } } } var removed = true; while (removed) { removed = false; for (0..grid.maxX) |i| { for (0..grid.maxY) |j| { if (grid.isRoll(@as(isize, @intCast(i)), @as(isize, @intCast(j)))) { var adjacent_count: usize = 0; adjacent_count += @intFromBool(grid.isRoll(@as(isize, @intCast(i)) - 1, @as(isize, @intCast(j)) - 1)); adjacent_count += @intFromBool(grid.isRoll(@as(isize, @intCast(i)) - 1, @as(isize, @intCast(j)))); adjacent_count += @intFromBool(grid.isRoll(@as(isize, @intCast(i)), @as(isize, @intCast(j)) - 1)); adjacent_count += @intFromBool(grid.isRoll(@as(isize, @intCast(i)) + 1, @as(isize, @intCast(j)) - 1)); adjacent_count += @intFromBool(grid.isRoll(@as(isize, @intCast(i)) - 1, @as(isize, @intCast(j)) + 1)); adjacent_count += @intFromBool(grid.isRoll(@as(isize, @intCast(i)) + 1, @as(isize, @intCast(j)) + 1)); adjacent_count += @intFromBool(grid.isRoll(@as(isize, @intCast(i)) + 1, @as(isize, @intCast(j)))); adjacent_count += @intFromBool(grid.isRoll(@as(isize, @intCast(i)), @as(isize, @intCast(j)) + 1)); if (adjacent_count < 4) { answer2 += 1; grid.data[i][j] = '.'; removed = true; } } } } } return .{ answer1, answer2 }; }