diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/day07.zig | 109 |
1 files changed, 109 insertions, 0 deletions
diff --git a/src/day07.zig b/src/day07.zig new file mode 100644 index 0000000..f06e08d --- /dev/null +++ b/src/day07.zig @@ -0,0 +1,109 @@ +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}); +} |