WIP: implement part 2
This commit is contained in:
parent
9dd5b41fe5
commit
e82fb0a304
1 changed files with 113 additions and 29 deletions
|
|
@ -3,44 +3,42 @@ 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
|
||||
;
|
||||
|
||||
var lines = std.mem.tokenizeScalar(u8, input, '\n');
|
||||
|
||||
var ranges: std.ArrayList(Range) = .empty;
|
||||
defer ranges.deinit(allocator);
|
||||
|
||||
var accumulator: u32 = 0;
|
||||
var accumulator: u64 = 0;
|
||||
|
||||
outer: while (lines.next()) |line| {
|
||||
while (lines.next()) |line| {
|
||||
var components = std.mem.tokenizeScalar(u8, line, '-');
|
||||
|
||||
const id_or_start_s = components.next() orelse continue;
|
||||
const id_or_start = try std.fmt.parseUnsigned(u64, id_or_start_s, 10);
|
||||
if (components.next()) |end_s| {
|
||||
const end = try std.fmt.parseUnsigned(u64, end_s, 10);
|
||||
try ranges.append(allocator, Range{ .start = id_or_start, .end = end });
|
||||
} else {
|
||||
for (ranges.items) |range| {
|
||||
if (id_or_start >= range.start and id_or_start <= range.end) {
|
||||
accumulator += 1;
|
||||
continue :outer;
|
||||
}
|
||||
}
|
||||
}
|
||||
const start_s = components.next() orelse continue;
|
||||
const end_s = components.next() orelse break;
|
||||
const range = Range{
|
||||
.start = try std.fmt.parseUnsigned(u64, start_s, 10),
|
||||
.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;
|
||||
|
||||
try ranges.append(allocator, range);
|
||||
}
|
||||
|
||||
var buffer: [64]u8 = undefined;
|
||||
|
|
@ -52,8 +50,94 @@ pub fn run(allocator: std.mem.Allocator) !void {
|
|||
try stdout.flush();
|
||||
}
|
||||
|
||||
fn processRange(
|
||||
range: Range,
|
||||
ranges: []Range,
|
||||
accumulator: *u64,
|
||||
allocator: std.mem.Allocator,
|
||||
) !Range {
|
||||
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);
|
||||
|
||||
overlapped = true;
|
||||
|
||||
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 (previous_non_overlapping) |p| {
|
||||
std.debug.print("+ comparing ({f}) to ({f})\n", .{non_overlapping, p});
|
||||
if (!non_overlapping.eql(&p)) {
|
||||
return non_overlapping;
|
||||
}
|
||||
}
|
||||
previous_non_overlapping = non_overlapping;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!overlapped) {
|
||||
std.debug.print("- no overlap with other range\n", .{});
|
||||
return range;
|
||||
}
|
||||
|
||||
unreachable;
|
||||
}
|
||||
|
||||
const Range = struct {
|
||||
start: u64,
|
||||
end: u64,
|
||||
|
||||
const Self = @This();
|
||||
|
||||
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 {
|
||||
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;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue