const std = @import("std"); const Error = error{IndexError}; fn splitOnce(s: []u8, sep: u8) ![2][]u8 { const i = std.mem.indexOfScalar(u8, s, sep) orelse return Error.IndexError; return .{ s[0..i], s[i + 1 ..] }; } fn intersect(range1: [2]usize, range2: [2]usize) bool { return range1[1] >= range2[0] and range2[1] >= range1[0]; } fn insertRange( allocator: std.mem.Allocator, ranges: *std.array_list.Aligned([2]usize, null), range: [2]usize, ) !void { const i: usize = for (ranges.items, 0..) |r, j| { if (r[1] + 1 >= range[0]) { break j; } } else ranges.items.len; try ranges.insert(allocator, i, range); while (i + 1 < ranges.items.len and intersect(range, ranges.items[i + 1])) { const start, const end = ranges.orderedRemove(i + 1); ranges.items[i] = .{ @min(ranges.items[i][0], start), @max(ranges.items[i][1], end), }; } } pub fn main() !void { const allocator = std.heap.smp_allocator; const path: [:0]const u8 = std.mem.span(std.os.argv[1]); var file = try std.fs.cwd().openFile(path, .{}); defer file.close(); var buffer: [256]u8 = undefined; var reader = file.reader(&buffer); var ranges = std.ArrayList([2]usize).empty; defer ranges.deinit(allocator); while (reader.interface.takeDelimiterInclusive('\n')) |line| { if (line.len == 1) { break; } const s1, const s2 = try splitOnce(line[0 .. line.len - 1], '-'); const start = try std.fmt.parseInt(usize, s1, 10); const end = try std.fmt.parseInt(usize, s2, 10); try insertRange(allocator, &ranges, .{ start, end + 1 }); // std.debug.print("ranges: {any} {}\n", .{ranges, ranges.items.len}); } else |err| return err; var part1: usize = 0; while (reader.interface.takeDelimiterInclusive('\n')) |line| { const value = try std.fmt.parseInt(usize, line[0 .. line.len - 1], 10); for (ranges.items) |range| { if (value >= range[0] and value < range[1]) { part1 += 1; break; } } } else |err| switch (err) { error.EndOfStream => {}, else => |e| return e, } std.debug.print("part1: {}\n", .{part1}); var part2: usize = 0; for (ranges.items) |range| { part2 += range[1] - range[0]; } std.debug.print("part2: {}\n", .{part2}); }