const std = @import("std"); pub fn parse(_: std.mem.Allocator, data: []const u8) ![]const u8 { return data; } pub fn part1(_: std.mem.Allocator, input: []const u8) !u32 { var state: enum { m, u, l, lp, lhs, rhs } = .m; var lhs: u32 = 0; var rhs: u32 = 0; var sum: u32 = 0; for (input) |c| { if (state == .m and c == 'm') { state = .u; } else if (state == .u and c == 'u') { state = .l; } else if (state == .l and c == 'l') { state = .lp; } else if (state == .lp and c == '(') { state = .lhs; } else if (state == .lhs and '0' <= c and c <= '9') { lhs *= 10; lhs += c - '0'; } else if (state == .lhs and c == ',') { state = .rhs; } else if (state == .rhs and '0' <= c and c <= '9') { rhs *= 10; rhs += c - '0'; } else if (state == .rhs and c == ')') { state = .m; sum += lhs * rhs; lhs = 0; rhs = 0; } else { lhs = 0; rhs = 0; state = .m; } } return sum; } test "part 2" { std.debug.assert(try part2(undefined, "xmul(2,4)&mul[3,7]!^don't()_mul(5,5)+mul(32,64](mul(11,8)undo()?mul(8,5))") == 48); } pub fn part2(_: std.mem.Allocator, input: []const u8) !u32 { var sum: u32 = 0; var i: usize = 0; while (i < input.len) : (i += 1) { const mul = std.mem.indexOfPos(u8, input, i, "mul(") orelse input.len; const dont = std.mem.indexOfPos(u8, input, i, "don't()") orelse input.len; i = @min(mul, dont); if (i == input.len) break; if (i == mul) { i += 4; var lhs: u32 = 0; while ('0' <= input[i] and input[i] <= '9') : (i += 1) { lhs = lhs * 10 + input[i] - '0'; } if (input[i] != ',') continue; i += 1; var rhs: u32 = 0; while ('0' <= input[i] and input[i] <= '9') : (i += 1) { rhs = rhs * 10 + input[i] - '0'; } if (input[i] != ')') continue; std.debug.print("sum += mul({},{})\n", .{ lhs, rhs }); sum += lhs * rhs; } else { std.debug.assert(i == dont); const do = std.mem.indexOfPos(u8, input, i, "do()") orelse break; i = do + 3; } } return sum; }