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}