aoc2025 @ master

  1const std = @import("std");
  2const Allocator = std.mem.Allocator;
  3
  4pub fn pt1(alloc: Allocator, input: []const u8) !u64 {
  5    var counter: u64 = 0;
  6
  7    var lines = std.mem.splitScalar(u8, input, '\n');
  8    var ranges = std.ArrayList(Range).empty;
  9    defer ranges.deinit(alloc);
 10
 11    while (lines.next()) |l| {
 12        if (l.len == 0) {
 13            break;
 14        }
 15
 16        var range_iter = std.mem.splitScalar(u8, l, '-');
 17        const range: Range = .{
 18            .from = std.fmt.parseInt(u64, range_iter.next().?, 10) catch unreachable,
 19            .to = std.fmt.parseInt(u64, range_iter.next().?, 10) catch unreachable,
 20        };
 21        try ranges.append(alloc, range);
 22    }
 23
 24    while (lines.next()) |l| {
 25        if (l.len == 0) {
 26            return counter;
 27        }
 28
 29        const id = std.fmt.parseInt(u64, l, 10) catch unreachable;
 30        for (ranges.items) |r| {
 31            if (r.from <= id and id <= r.to) {
 32                counter += 1;
 33                break;
 34            }
 35        }
 36    }
 37
 38    return counter;
 39}
 40
 41pub fn pt2(alloc: Allocator, input: []const u8) !u64 {
 42    var lines = std.mem.splitScalar(u8, input, '\n');
 43    var ranges = std.ArrayList(Range).empty;
 44    defer ranges.deinit(alloc);
 45
 46    while (lines.next()) |l| {
 47        if (l.len == 0) {
 48            break;
 49        }
 50
 51        var range_iter = std.mem.splitScalar(u8, l, '-');
 52        const range: Range = .{
 53            .from = std.fmt.parseInt(u64, range_iter.next().?, 10) catch unreachable,
 54            .to = std.fmt.parseInt(u64, range_iter.next().?, 10) catch unreachable,
 55        };
 56        try ranges.append(alloc, range);
 57    }
 58
 59    std.mem.sort(Range, ranges.items, {}, struct {
 60        fn lessThan(_: void, a: Range, b: Range) bool {
 61            return a.from < b.from;
 62        }
 63    }.lessThan);
 64
 65    var merged = std.ArrayList(Range).empty;
 66    defer merged.deinit(alloc);
 67
 68    var current = ranges.items[0];
 69
 70    for (ranges.items[1..]) |range| {
 71        if (current.to + 1 >= range.from) {
 72            if (range.to > current.to) {
 73                current.to = range.to;
 74            }
 75        } else {
 76            try merged.append(alloc, current);
 77            current = range;
 78        }
 79    }
 80
 81    try merged.append(alloc, current);
 82
 83    var total: u64 = 0;
 84    for (merged.items) |range| {
 85        total += (range.to - range.from) + 1;
 86    }
 87
 88    return total;
 89}
 90
 91const Range = struct {
 92    from: u64,
 93    to: u64,
 94};
 95
 96test "Day 5 part 1" {
 97    const res = pt1(std.testing.allocator, @embedFile("./input/day5"));
 98    try std.testing.expect(res == 652);
 99}
100
101test "Day 5 part 2" {
102    const res = pt2(std.testing.allocator, @embedFile("./input/day5"));
103    try std.testing.expect(res == 341753674214273);
104}