const std = @import("std"); const lib = @import("lib.zig"); const Number = struct { row: usize, col: usize, length: usize, value: u32 }; pub fn main() !void { const content = @embedFile("data.txt"); const grid = try lib.splitArrayIntoArrayList(content, "\n"); defer grid.deinit(); const numbers = try parseNumbers(grid); defer numbers.deinit(); var total1: u128 = 0; for (numbers.items) |n| { if (numberTouchesSymbol(n, grid)) { total1 += n.value; } } std.debug.print("total1 {d}\n", .{total1}); var total2: u128 = 0; for (grid.items, 0..) |line, row| { for (line, 0..) |val, col| { if (val == '*') { total2 += try findGearRatio(row, col, numbers); } } } std.debug.print("total2 {d}\n", .{total2}); } fn findGearRatio(row: usize, col: usize, numbers: std.ArrayList(Number)) !u32 { const touching = try findNumbersTouchingCell(row, col, numbers); if (touching.items.len != 2) { return 0; } return touching.items[0].value * touching.items[1].value; } fn findNumbersTouchingCell(row: usize, col: usize, numbers: std.ArrayList(Number)) !std.ArrayList(Number) { const allocator = std.heap.page_allocator; var touching = std.ArrayList(Number).init(allocator); for (numbers.items) |n| { // itreate over each digit in the number for (0..n.length) |i| { // TODO: upgrade to Zig .12 to get @abs // if (@abs(n.row - row) < 1 and @abs(n.col + i - col) < 1) { if ((n.row == row or n.row + 1 == row or n.row == row + 1) and (n.col + i == col or n.col + 1 + i == col or n.col + i == col + 1)) { try touching.append(n); break; } } } return touching; } fn numberTouchesSymbol(n: Number, grid: std.ArrayList([]const u8)) bool { const items = grid.items; const width = items[0].len; const height = items.len - 1; // TODO: fix extra crap when i read files.. // itreate over each digit in the number for (0..n.length) |i| { // over the 3 nearest rows for (0..3) |r| { // and the 3 nearest columns for (0..3) |c| { const outOfBounds = (r == 0 and n.row == 0) or (c == 0 and n.col + i == 0) or (r == 2 and n.row + 1 == height) or (c == 2 and n.col + i + 1 == width); if (!outOfBounds) { const row = n.row + r - 1; const col = n.col + c + i - 1; const val = items[row][col]; if (!std.ascii.isDigit(val) and val != '.') { return true; } } } } } return false; } fn parseNumbers(grid: std.ArrayList([]const u8)) !std.ArrayList(Number) { const allocator = std.heap.page_allocator; var numbers = std.ArrayList(Number).init(allocator); for (grid.items, 0..) |line, row| { var numList = std.ArrayList(u8).init(allocator); defer numList.deinit(); for (line, 0..) |val, col| { if (std.ascii.isDigit(val)) { try numList.append(val); } // if we have a number started, and we've encountered a non-digit (or the end of the grid) if (numList.items.len != 0 and (!std.ascii.isDigit(val) or col == line.len - 1)) { const parsed = try std.fmt.parseInt(u32, numList.items, 10); const length = numList.items.len; try numbers.append(Number{ .row = row, .col = col - length, .length = length, .value = parsed }); numList.items.len = 0; } } } return numbers; }