const std = @import("std"); const builtin = @import("builtin"); fn readInputFile(allocator: std.mem.Allocator, filename: []const u8) ![]u32 { var result = std.ArrayList(u32).init(allocator); const file = try std.fs.cwd().openFile(filename, .{ .read = true }); defer file.close(); const reader = file.reader(); while (true) { var line: []u8 = undefined; if (builtin.os.tag == .windows) { // NOTE: Read another byte on windows due to two-byte eol. line = reader.readUntilDelimiterAlloc(allocator, '\r', 512) catch break; _ = try reader.readByte(); } else { line = reader.readUntilDelimiterAlloc(allocator, '\n', 512) catch break; } defer allocator.free(line); for (line) |char| { try result.append(@as(u32, char - 48)); } } return result.items; } pub fn drawGrid(width: u32, height: u32, grid: []u32) void { var y: u32 = 0; while (y < height) : (y += 1) { std.log.debug("{any}", .{grid[(y * width)..((y + 1) * width)]}); } } fn flash(x: u32, y: u32, width: u32, height: u32, squid: []u32) void { var yy: i32 = -1; while (yy < 2) : (yy += 1) { if (yy + @intCast(i32, y) < 0 or yy + @intCast(i32, y) >= @intCast(i32, height)) { continue; } var i = @intCast(u32, yy + @intCast(i32, y)) * width; var xx: i32 = -1; while (xx < 2) : (xx += 1) { if (xx + @intCast(i32, x) < 0 or xx + @intCast(i32, x) >= @intCast(i32, width)) { continue; } if (!(xx == 0 and yy == 0)) { squid[i + @intCast(u32, xx + @intCast(i32, x))] += 1; } } } } pub fn iterateEnergy(width: u32, height: u32, squid: []u32) u32 { var result: u32 = 0; var y: u32 = 0; while (y < height) : (y += 1) { var i = y * width; var x: u32 = 0; while (x < width) : (x += 1) { squid[i + x] += 1; } } while (true) { var did_flash: bool = false; y = 0; while (y < height) : (y += 1) { var i = y * width; var x: u32 = 0; while (x < width) : (x += 1) { if (squid[i + x] > 9 and squid[i + x] < 99) { squid[i + x] = 99; flash(x, y, width, height, squid); did_flash = true; } } } if (!did_flash) { break; } } y = 0; while (y < height) : (y += 1) { var i = y * width; var x: u32 = 0; while (x < width) : (x += 1) { if (squid[i + x] > 9) { squid[i + x] = 0; result += 1; } } } return result; } pub fn task1(width: u32, height: u32, input: []u32) u32 { var result: u32 = 0; //std.log.debug("\ninitial", .{}); //drawGrid(width, height, input); var i: u32 = 0; while (i < 100) : (i += 1) { result += iterateEnergy(width, height, input); //std.log.debug("\nafter {} step", .{i + 1}); //drawGrid(width, height, input); } return result; } pub fn task2(width: u32, height: u32, input: []u32) u32 { var result: u32 = 1; while (true) : (result += 1) { if (iterateEnergy(width, height, input) == width * height) { //std.log.debug("\nafter {} steps", .{result}); //drawGrid(width, height, input); break; } } return result; } pub fn main() !void { var buffer: [2000000]u8 = undefined; var fixed_buffer = std.heap.FixedBufferAllocator.init(&buffer); const allocator = fixed_buffer.allocator(); const input = try readInputFile(allocator, "input.txt"); var input_copy = std.ArrayList(u32).init(allocator); try input_copy.appendSlice(input); const task_1_result = task1(10, 10, input_copy.items); std.log.info("Task 1 result: {}", .{task_1_result}); input_copy.clearAndFree(); try input_copy.appendSlice(input); const task_2_result = task2(10, 10, input_copy.items); std.log.info("Task 2 result: {}", .{task_2_result}); input_copy.clearAndFree(); }