const std = @import("std"); const mecha = @import("mecha"); const print = std.debug.print; pub fn solve(part: []u8, buffer: []u8, allocator: std.mem.Allocator) !void { if (std.mem.eql(u8, part, "1")) { try part1(buffer, allocator); } else { try part2(buffer, allocator); } } fn evaluate(test_value: usize, numbers: []const usize, index: usize) bool { if (index == 0) { return test_value == numbers[0]; } const number = numbers[index]; const division: usize = test_value / number; if (division * number == test_value) { const b = evaluate(division, numbers, index - 1); if (!b and test_value >= number and (test_value - number) % number == 0) return evaluate(test_value - number, numbers, index - 1); return b; } else if (test_value >= number) { return evaluate(test_value - number, numbers, index - 1); } return false; } fn part1(buffer: []const u8, allocator: std.mem.Allocator) !void { const parser = mecha.combine(.{ mecha.int(usize, .{}), mecha.string(": ").discard(), mecha.many(mecha.int(usize, .{}), .{ .separator = mecha.string(" ").discard() }) }); var lines = std.mem.splitScalar(u8, buffer, '\n'); var total: usize = 0; while (lines.next()) |line| { if (line.len == 0) break; const parsed = try parser.parse(allocator, line); const test_value = parsed.value[0]; const numbers: []const usize = parsed.value[1]; if (evaluate(test_value, numbers, numbers.len - 1)) { total += parsed.value[0]; } allocator.free(numbers); } print("{d}\n", .{total}); } //----------------------------------------------PART 2-------------------------------------------------------- fn magnitude(int2: usize) usize { var count: usize = 0; var temp = int2; while (temp > 0) { temp /= 10; count += 1; } return std.math.pow(usize, 10, count); } fn evaluate2(test_value: usize, numbers: []usize, index: usize) bool { if (index == 0) { return test_value == numbers[0]; } const number = numbers[index]; const division: usize = test_value / number; if (division * number == test_value) { const b = evaluate2(division, numbers, index - 1); if (b) { return true; } else if (test_value >= number and (test_value - number) % number == 0 and evaluate2(test_value - number, numbers, index - 1)) return true; } else if (test_value >= number and evaluate2(test_value - number, numbers, index - 1)) { return true; } const base = magnitude(number); if (test_value % base == number) { return evaluate2(test_value / base, numbers, index - 1); } return false; } fn part2(buffer: []const u8, allocator: std.mem.Allocator) !void { const parser = mecha.combine(.{ mecha.int(usize, .{}), mecha.string(": ").discard(), mecha.many(mecha.int(usize, .{}), .{ .separator = mecha.string(" ").discard() }) }); var lines = std.mem.splitScalar(u8, buffer, '\n'); var total: usize = 0; while (lines.next()) |line| { if (line.len == 0) break; const parsed = try parser.parse(allocator, line); const test_value = parsed.value[0]; const numbers: []usize = parsed.value[1]; if (evaluate2(test_value, numbers, numbers.len - 1)) { total += parsed.value[0]; } allocator.free(numbers); } print("{d}\n", .{total}); }