Finish day05, part 2
This commit is contained in:
parent
e82fb0a304
commit
3da92e4f2b
1 changed files with 107 additions and 68 deletions
|
|
@ -3,20 +3,24 @@ const std = @import("std");
|
||||||
pub const title = "Day 05: Cafeteria";
|
pub const title = "Day 05: Cafeteria";
|
||||||
|
|
||||||
pub fn run(allocator: std.mem.Allocator) !void {
|
pub fn run(allocator: std.mem.Allocator) !void {
|
||||||
//const input = @embedFile("./input/day05.txt");
|
const input = @embedFile("./input/day05.txt");
|
||||||
const input =
|
//const input =
|
||||||
\\3-5
|
// \\3-5
|
||||||
\\10-14
|
// \\10-14
|
||||||
\\16-20
|
// \\16-20
|
||||||
\\12-18
|
// \\12-18
|
||||||
\\
|
// \\
|
||||||
\\1
|
// \\1
|
||||||
\\5
|
// \\5
|
||||||
\\8
|
// \\8
|
||||||
\\11
|
// \\11
|
||||||
\\17
|
// \\17
|
||||||
\\32
|
// \\32
|
||||||
;
|
// ;
|
||||||
|
//const input =
|
||||||
|
// \\383043617664892-389277822354893
|
||||||
|
// \\387921155483286-389277822354893
|
||||||
|
// ;
|
||||||
|
|
||||||
var lines = std.mem.tokenizeScalar(u8, input, '\n');
|
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 accumulator: u64 = 0;
|
||||||
|
|
||||||
|
var i: usize = 0;
|
||||||
while (lines.next()) |line| {
|
while (lines.next()) |line| {
|
||||||
var components = std.mem.tokenizeScalar(u8, 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),
|
.end = try std.fmt.parseUnsigned(u64, end_s, 10),
|
||||||
};
|
};
|
||||||
|
|
||||||
const non_overlapping = try processRange(range, ranges.items, &accumulator, allocator);
|
std.debug.print("==> range {d}\n", .{i});
|
||||||
accumulator += (non_overlapping.end + 1) - non_overlapping.start;
|
|
||||||
|
processRange(range, ranges.items, &accumulator, 0);
|
||||||
|
|
||||||
try ranges.append(allocator, range);
|
try ranges.append(allocator, range);
|
||||||
|
|
||||||
|
i += 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
var buffer: [64]u8 = undefined;
|
var buffer: [64]u8 = undefined;
|
||||||
|
|
@ -54,52 +62,64 @@ fn processRange(
|
||||||
range: Range,
|
range: Range,
|
||||||
ranges: []Range,
|
ranges: []Range,
|
||||||
accumulator: *u64,
|
accumulator: *u64,
|
||||||
allocator: std.mem.Allocator,
|
level: usize,
|
||||||
) !Range {
|
) 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});
|
std.debug.print("considering {f}\n", .{range});
|
||||||
|
|
||||||
var overlapped = false;
|
var overlapped = false;
|
||||||
for (ranges) |other| {
|
for (ranges) |other| {
|
||||||
const overlaps = try range.overlaps(allocator, &other);
|
const difference = range.symmetricDifference(other);
|
||||||
if (overlaps) |outside| {
|
if (difference.overlapping) {
|
||||||
defer allocator.free(outside);
|
|
||||||
|
|
||||||
std.debug.assert(outside.len <= 2);
|
|
||||||
|
|
||||||
overlapped = true;
|
overlapped = true;
|
||||||
|
|
||||||
|
if (range.eql(other)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (0..level) |_| std.debug.print("\t", .{});
|
||||||
std.debug.print("- overlaps with {f}\n", .{other});
|
std.debug.print("- overlaps with {f}\n", .{other});
|
||||||
|
|
||||||
if (outside.len == 0) {
|
if (difference.left != null and difference.right != null) {
|
||||||
std.debug.print("- overlap is exactly equal\n", .{});
|
const left = difference.left.?;
|
||||||
return range;
|
const right = difference.right.?;
|
||||||
}
|
for (0..level) |_| std.debug.print("\t", .{});
|
||||||
|
std.debug.print("- left = {f}, right = {f}\n", .{left, right});
|
||||||
var previous_non_overlapping: ?Range = null;
|
if (left.eql(right)) {
|
||||||
for (outside, 0..) |r, i| {
|
return;
|
||||||
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 (previous_non_overlapping) |p| {
|
|
||||||
std.debug.print("+ comparing ({f}) to ({f})\n", .{non_overlapping, p});
|
if (left.start == range.start) {
|
||||||
if (!non_overlapping.eql(&p)) {
|
processRange(left, ranges, accumulator, level + 1);
|
||||||
return non_overlapping;
|
}
|
||||||
}
|
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) {
|
if (!overlapped) {
|
||||||
std.debug.print("- no overlap with other range\n", .{});
|
const n = (range.end + 1) - range.start;
|
||||||
return range;
|
std.debug.print("- no overlap with other range, adding {d}\n", .{n});
|
||||||
|
accumulator.* += n;
|
||||||
}
|
}
|
||||||
|
|
||||||
unreachable;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const Range = struct {
|
const Range = struct {
|
||||||
|
|
@ -108,36 +128,55 @@ const Range = struct {
|
||||||
|
|
||||||
const Self = @This();
|
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 {
|
pub fn format(self: Range, w: *std.io.Writer) std.io.Writer.Error!void {
|
||||||
try w.print("{d} to {d}", .{self.start, self.end});
|
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;
|
return self.start == other.start and self.end == other.end;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn overlaps(self: *const Self, allocator: std.mem.Allocator, other: *const Self) !?[]Self {
|
pub fn symmetricDifference(self: Self, other: Self) SymmetricDifference {
|
||||||
if (self.start <= other.end and self.end >= other.start) {
|
const overlapping = self.start <= other.end and self.end >= other.start;
|
||||||
var l: std.ArrayList(Self) = try .initCapacity(allocator, 2);
|
if (!overlapping) {
|
||||||
defer l.deinit(allocator);
|
const left, const right = if (self.end < other.start) .{ self, other } else .{ other, self };
|
||||||
|
return .{
|
||||||
if (self.start < other.start) {
|
.left = left,
|
||||||
try l.append(allocator, Range{ .start = self.start, .end = other.start - 1 });
|
.right = right,
|
||||||
}
|
.overlapping = overlapping,
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue