summaryrefslogtreecommitdiff
path: root/day2/zig/src/main.zig
blob: 3f684919f1ec0afce2eb45f7766c054fcf8c8233 (plain)
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);
}