1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
|
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);
}
|