1
0

wash day05

This commit is contained in:
xeals 2023-12-06 11:19:55 +11:00
parent 0f2044b762
commit 0ab1fa186d
Signed by: xeals
SSH Key Fingerprint: SHA256:pRv+8swQDA+/LuZ7NHj9m006BbKexlNK62OUA01ZZBc

View File

@ -20,7 +20,6 @@ fn Range(comptime T: type) type {
pub fn intersect(self: Self, other: Self) ?Self { pub fn intersect(self: Self, other: Self) ?Self {
const a = if (self.start < other.start) self else other; const a = if (self.start < other.start) self else other;
const b = if (self.start < other.start) other else self; const b = if (self.start < other.start) other else self;
// std.debug.print("{any}/{any}\n", .{ a, b });
if (a.start == a.end or b.start == b.end) return null; // Points don't intersect. if (a.start == a.end or b.start == b.end) return null; // Points don't intersect.
@ -32,29 +31,12 @@ fn Range(comptime T: type) type {
/// Returns the union of two ranges. /// Returns the union of two ranges.
pub fn join(self: Self, other: Self) ?Self { pub fn join(self: Self, other: Self) ?Self {
if (self.intersect(other) == null) return null; // Can't union disjoint ranges. if (self.intersect(other) == null) return null; // Can't union disjoint ranges.
// std.debug.print("merge {any}+{any}\n", .{ self, other });
// Now guaranteed that they overlap. // Now guaranteed that they overlap.
const merged = Self{ .start = @min(self.start, other.start), .end = @max(self.end, other.end) }; return .{ .start = @min(self.start, other.start), .end = @max(self.end, other.end) };
std.debug.print("= {any}\n", .{merged});
return merged;
} }
}; };
} }
test "range intersect" {
const R = Range(usize);
const e = .{ .start = 2, .end = 5 };
// Superset
try std.testing.expectEqual(e, (R{ .start = 0, .end = 6 }).intersect(.{ .start = 2, .end = 5 }));
try std.testing.expectEqual(e, (R{ .start = 2, .end = 5 }).intersect(.{ .start = 0, .end = 6 }));
// A < B
try std.testing.expectEqual(e, (R{ .start = 0, .end = 5 }).intersect(.{ .start = 2, .end = 6 }));
// B < A
try std.testing.expectEqual(e, (R{ .start = 2, .end = 6 }).intersect(.{ .start = 0, .end = 5 }));
// No intersect
try std.testing.expect(null == (R{ .start = 0, .end = 3 }).intersect(.{ .start = 4, .end = 6 }));
}
const Map = struct { const Map = struct {
offset: isize, offset: isize,
source: Range(usize), source: Range(usize),
@ -84,17 +66,6 @@ fn mergeRanges(ranges: *std.ArrayList(Component)) void {
} }
} }
test "mergeRanges" {
var ranges = std.ArrayList(Component).init(std.testing.allocator);
defer ranges.deinit();
try ranges.append(.{ .stage = 0, .range = .{ .start = 79, .end = 93 } });
try ranges.append(.{ .stage = 0, .range = .{ .start = 55, .end = 66 } });
try ranges.append(.{ .stage = 0, .range = .{ .start = 70, .end = 10 } });
mergeRanges(&ranges);
try std.testing.expectEqual(.{ .start = 70, .end = 93 }, ranges.items[0].range);
try std.testing.expectEqual(.{ .start = 55, .end = 66 }, ranges.items[1].range);
}
fn solve(alloc: mem.Allocator, input: []const u8) !usize { fn solve(alloc: mem.Allocator, input: []const u8) !usize {
var it = util.splitLines(input); var it = util.splitLines(input);
const seed_line = it.next().?; const seed_line = it.next().?;
@ -103,10 +74,8 @@ fn solve(alloc: mem.Allocator, input: []const u8) !usize {
var ranges = std.ArrayList(Component).init(alloc); var ranges = std.ArrayList(Component).init(alloc);
defer ranges.deinit(); defer ranges.deinit();
var lowest_location: usize = std.math.maxInt(usize);
{ {
std.debug.print("= seeding {d} =\n", .{seeds.len});
var index: usize = 0; var index: usize = 0;
while (index < seeds.len) : (index += 2) { while (index < seeds.len) : (index += 2) {
try ranges.append(.{ try ranges.append(.{
@ -122,7 +91,6 @@ fn solve(alloc: mem.Allocator, input: []const u8) !usize {
var current_stage: usize = 0; var current_stage: usize = 0;
while (it.next()) |line| { while (it.next()) |line| {
if (line.len == 0) { if (line.len == 0) {
std.debug.print("== finalise ==\n", .{});
for (ranges.items, 0..) |item, index| { for (ranges.items, 0..) |item, index| {
if (item.stage != current_stage) { if (item.stage != current_stage) {
ranges.items[index] = .{ .stage = current_stage, .range = item.range }; ranges.items[index] = .{ .stage = current_stage, .range = item.range };
@ -132,7 +100,6 @@ fn solve(alloc: mem.Allocator, input: []const u8) !usize {
} else if (mem.endsWith(u8, line, "map:")) { } else if (mem.endsWith(u8, line, "map:")) {
current_stage += 1; current_stage += 1;
} else { } else {
std.debug.print("== stage {d} map {s} ==\n", .{ current_stage, line });
const map_line = try util.parseIntsScalar(usize, alloc, line, .{}); const map_line = try util.parseIntsScalar(usize, alloc, line, .{});
defer alloc.free(map_line); defer alloc.free(map_line);
const map = Map{ const map = Map{
@ -144,40 +111,34 @@ fn solve(alloc: mem.Allocator, input: []const u8) !usize {
while (i != 0) : (i -= 1) { while (i != 0) : (i -= 1) {
if (ranges.items[i - 1].stage == current_stage) continue; if (ranges.items[i - 1].stage == current_stage) continue;
const item = ranges.swapRemove(i - 1); const item = ranges.swapRemove(i - 1);
std.debug.print("item {d}/{d} {d}..{d}\n", .{ i, ranges.items.len + 1, item.range.start, item.range.end });
if (item.range.intersect(.{ .start = 0, .end = map.source.start })) |section| { if (item.range.intersect(.{ .start = 0, .end = map.source.start })) |section| {
// Non-transitioning section. // Non-transitioning section.
std.debug.print("=> s {d}..{d}\n", .{ section.start, section.end });
try ranges.append(.{ .stage = item.stage, .range = section }); try ranges.append(.{ .stage = item.stage, .range = section });
} }
if (item.range.intersect(map.source)) |section| { if (item.range.intersect(map.source)) |section| {
// Transitioning section. // Transitioning section.
const range = Range(usize){
.start = @intCast(@as(isize, @intCast(section.start)) + map.offset),
.end = @intCast(@as(isize, @intCast(section.end)) + map.offset),
};
std.debug.print("=> m {d}..{d}\n", .{ range.start, range.end });
try ranges.append(.{ try ranges.append(.{
.stage = current_stage, .stage = current_stage,
.range = range, .range = .{
.start = @intCast(@as(isize, @intCast(section.start)) + map.offset),
.end = @intCast(@as(isize, @intCast(section.end)) + map.offset),
},
}); });
} }
if (item.range.intersect(.{ .start = map.source.end, .end = std.math.maxInt(usize) })) |section| { if (item.range.intersect(.{ .start = map.source.end, .end = std.math.maxInt(usize) })) |section| {
// Non-transitioning section. // Non-transitioning section.
std.debug.print("=> e {d}..{d}\n", .{ section.start, section.end });
try ranges.append(.{ .stage = item.stage, .range = section }); try ranges.append(.{ .stage = item.stage, .range = section });
} }
} }
} }
} }
var min_loc: usize = std.math.maxInt(usize);
for (ranges.items) |item| { for (ranges.items) |item| {
std.debug.print("{any}\n", .{item.range}); min_loc = @min(min_loc, item.range.start);
lowest_location = @min(lowest_location, item.range.start);
} }
return min_loc;
return lowest_location;
} }
test "silver" { test "silver" {