From 3da92e4f2b6f0b8ca8d2895b48b8cb5dd32c6602 Mon Sep 17 00:00:00 2001 From: ktkk Date: Fri, 5 Dec 2025 20:09:09 +0000 Subject: [PATCH] Finish day05, part 2 --- src/days/day05.zig | 175 +++++++++++++++++++++++++++------------------ 1 file changed, 107 insertions(+), 68 deletions(-) diff --git a/src/days/day05.zig b/src/days/day05.zig index 9a3ebf6..27b185e 100644 --- a/src/days/day05.zig +++ b/src/days/day05.zig @@ -3,20 +3,24 @@ const std = @import("std"); pub const title = "Day 05: Cafeteria"; pub fn run(allocator: std.mem.Allocator) !void { - //const input = @embedFile("./input/day05.txt"); - const input = - \\3-5 - \\10-14 - \\16-20 - \\12-18 - \\ - \\1 - \\5 - \\8 - \\11 - \\17 - \\32 - ; + const input = @embedFile("./input/day05.txt"); + //const input = + // \\3-5 + // \\10-14 + // \\16-20 + // \\12-18 + // \\ + // \\1 + // \\5 + // \\8 + // \\11 + // \\17 + // \\32 + // ; + //const input = + // \\383043617664892-389277822354893 + // \\387921155483286-389277822354893 + // ; var lines = std.mem.tokenizeScalar(u8, input, '\n'); @@ -25,6 +29,7 @@ pub fn run(allocator: std.mem.Allocator) !void { var accumulator: u64 = 0; + var i: usize = 0; while (lines.next()) |line| { var components = std.mem.tokenizeScalar(u8, line, '-'); @@ -35,10 +40,13 @@ pub fn run(allocator: std.mem.Allocator) !void { .end = try std.fmt.parseUnsigned(u64, end_s, 10), }; - const non_overlapping = try processRange(range, ranges.items, &accumulator, allocator); - accumulator += (non_overlapping.end + 1) - non_overlapping.start; + std.debug.print("==> range {d}\n", .{i}); + + processRange(range, ranges.items, &accumulator, 0); try ranges.append(allocator, range); + + i += 1; } var buffer: [64]u8 = undefined; @@ -54,52 +62,64 @@ fn processRange( range: Range, ranges: []Range, accumulator: *u64, - allocator: std.mem.Allocator, -) !Range { + level: usize, +) void { + for (0..level) |_| std.debug.print("\t", .{}); + std.debug.print("recursion level = {d}\n", .{level}); + + for (0..level) |_| std.debug.print("\t", .{}); std.debug.print("considering {f}\n", .{range}); var overlapped = false; for (ranges) |other| { - const overlaps = try range.overlaps(allocator, &other); - if (overlaps) |outside| { - defer allocator.free(outside); - - std.debug.assert(outside.len <= 2); - + const difference = range.symmetricDifference(other); + if (difference.overlapping) { overlapped = true; + if (range.eql(other)) { + return; + } + + for (0..level) |_| std.debug.print("\t", .{}); std.debug.print("- overlaps with {f}\n", .{other}); - if (outside.len == 0) { - std.debug.print("- overlap is exactly equal\n", .{}); - return range; - } - - var previous_non_overlapping: ?Range = null; - for (outside, 0..) |r, i| { - std.debug.print("\t+ ({d}) {f} falls outside\n", .{i, r}); - - const non_overlapping = try processRange(r, ranges, accumulator, allocator); - if ((i + 1) == outside.len) { - return non_overlapping; + if (difference.left != null and difference.right != null) { + const left = difference.left.?; + const right = difference.right.?; + for (0..level) |_| std.debug.print("\t", .{}); + std.debug.print("- left = {f}, right = {f}\n", .{left, right}); + if (left.eql(right)) { + return; } - if (previous_non_overlapping) |p| { - std.debug.print("+ comparing ({f}) to ({f})\n", .{non_overlapping, p}); - if (!non_overlapping.eql(&p)) { - return non_overlapping; - } + + if (left.start == range.start) { + processRange(left, ranges, accumulator, level + 1); + } + if (right.end == range.end) { + processRange(right, ranges, accumulator, level + 1); + } + } else if (difference.left) |left| { + for (0..level) |_| std.debug.print("\t", .{}); + std.debug.print("- left = {f}\n", .{left}); + if (left.start == range.start) { + processRange(left, ranges, accumulator, level + 1); + } + } else if (difference.right) |right| { + for (0..level) |_| std.debug.print("\t", .{}); + std.debug.print("- right = {f}\n", .{right}); + if (right.end == range.end) { + processRange(right, ranges, accumulator, level + 1); } - previous_non_overlapping = non_overlapping; } + return; } } if (!overlapped) { - std.debug.print("- no overlap with other range\n", .{}); - return range; + const n = (range.end + 1) - range.start; + std.debug.print("- no overlap with other range, adding {d}\n", .{n}); + accumulator.* += n; } - - unreachable; } const Range = struct { @@ -108,36 +128,55 @@ const Range = struct { const Self = @This(); + pub const SymmetricDifference = struct { + left: ?Self = null, + right: ?Self = null, + overlapping: bool, + }; + pub fn format(self: Range, w: *std.io.Writer) std.io.Writer.Error!void { try w.print("{d} to {d}", .{self.start, self.end}); } - pub fn eql(self: *const Self, other: *const Self) bool { + pub fn eql(self: Self, other: Self) bool { return self.start == other.start and self.end == other.end; } - pub fn overlaps(self: *const Self, allocator: std.mem.Allocator, other: *const Self) !?[]Self { - if (self.start <= other.end and self.end >= other.start) { - var l: std.ArrayList(Self) = try .initCapacity(allocator, 2); - defer l.deinit(allocator); - - if (self.start < other.start) { - try l.append(allocator, Range{ .start = self.start, .end = other.start - 1 }); - } - if (self.end > other.end) { - try l.append(allocator, Range{ .start = other.end + 1, .end = self.end }); - } - if (other.start < self.start) { - try l.append(allocator, Range{ .start = other.start, .end = self.start - 1 }); - } - if (other.end > self.end) { - try l.append(allocator, Range{ .start = self.end + 1, .end = other.end }); - } - - return try l.toOwnedSlice(allocator); - } else { - return null; + pub fn symmetricDifference(self: Self, other: Self) SymmetricDifference { + const overlapping = self.start <= other.end and self.end >= other.start; + if (!overlapping) { + const left, const right = if (self.end < other.start) .{ self, other } else .{ other, self }; + return .{ + .left = left, + .right = right, + .overlapping = overlapping, + }; } + + var difference: SymmetricDifference = .{ .overlapping = overlapping }; + if (self.start < other.start) { + difference.left = .{ + .start = self.start, + .end = other.start - 1, + }; + } else if (other.start < self.start) { + difference.left = .{ + .start = other.start, + .end = self.start - 1, + }; + } + if (self.end > other.end) { + difference.right = .{ + .start = other.end + 1, + .end = self.end, + }; + } else if (other.end > self.end) { + difference.right = .{ + .start = self.end + 1, + .end = other.end, + }; + } + return difference; } };