const std = @import("std"); const mem = std.mem; const math = std.math; pub fn main() !void { const input: []const u8 = @embedFile("input.txt"); const part1, const part2 = try problem(input); std.debug.print("Part 1: {}\n", .{part1}); std.debug.print("Part 2: {}\n", .{part2}); } fn problem(input: []const u8) !struct { u64, u64 } { var lines: mem.TokenIterator(u8, .scalar) = mem.tokenizeScalar(u8, input[0..input.len - 1], ','); var part1: u64 = 0; var part2: u64 = 0; part2 += 0; while (lines.next()) |line| { var from: u64, const to = try parseline(line); while (from <= to) : (from += 1) { if (try invalidate(from)) part1 += from; if (try invalidate2(from)) part2 += from; } } return .{ part1, part2 }; } fn invalidate2(num: u64) !bool { var multiplier: u64 = 10; var buf: [64]u8 = undefined; var num1 = @divTrunc(num, multiplier); var num2 = @rem(num, multiplier); const len = (try std.fmt.bufPrint(&buf, "{d}", .{num})).len; while (num1 > 0) : ({multiplier *= 10; num1 = @divTrunc(num, multiplier); num2 = @rem(num, multiplier);}) { const len1 = (try std.fmt.bufPrint(&buf, "{d}", .{num1})).len; const len2 = (try std.fmt.bufPrint(&buf, "{d}", .{num2})).len; if (len1 + len2 != len) continue; if (num1 < num2) continue; if (num2 == 0) continue; const diff = @divTrunc(num1 - num2, len2); std.debug.print("num1 = {d}\ndiff = {d}\n", .{num1, diff}); if (@rem(diff, multiplier) == num2) return true; if (num1 == num2) return true; } return false; } fn invalidate(num: u64) !bool { var multiplier: u64 = 10; var buf: [64]u8 = undefined; const len = (try std.fmt.bufPrint(&buf, "{d}", .{num})).len; while (@divTrunc(num, multiplier) > 0) : (multiplier *= 10) { const len1 = (try std.fmt.bufPrint(&buf, "{d}", .{@divTrunc(num, multiplier)})).len; const len2 = (try std.fmt.bufPrint(&buf, "{d}", .{@rem(num, multiplier)})).len; if (len1 + len2 != len) continue; if (@divTrunc(num, multiplier) == @rem(num, multiplier)) return true; } return false; } fn parseline(l: []const u8) !struct { u64, u64 } { var split = mem.splitScalar(u8, l, '-'); const from = try std.fmt.parseInt(u64, split.next().?, 10); const to = try std.fmt.parseInt(u64, split.next().?, 10); return .{ from, to }; } test "Sample Input" { const input: []const u8 = @embedFile("input_sample.txt"); const part1, const part2 = try problem(input); std.debug.print("Part 1: {}\n", .{part1}); std.debug.print("Part 2: {}\n", .{part2}); try std.testing.expectEqual(1227775554, part1); try std.testing.expectEqual(4174379265, part2); }