diff --git a/src/day05.zig b/src/day05.zig index fd17bbc..9828ab6 100644 --- a/src/day05.zig +++ b/src/day05.zig @@ -30,60 +30,89 @@ const Component = struct { value: usize, }; +const UsizeSet = std.AutoHashMap(usize, void); + fn solve(alloc: mem.Allocator, input: []const u8) !Solution { var it = util.splitLines(input); const seed_line = it.next().?; const seeds = try util.parseIntsScalar(usize, alloc, seed_line[mem.indexOfScalar(u8, seed_line, ':').? + 1 ..], .{}); defer alloc.free(seeds); - var last_components = try std.ArrayList(Component).initCapacity(alloc, seeds.len); - defer last_components.deinit(); + + var last_values = UsizeSet.init(alloc); + var working_values = UsizeSet.init(alloc); + defer last_values.deinit(); + defer working_values.deinit(); + + var low_loc: usize = std.math.maxInt(usize); var seeds_index: usize = 0; while (seeds_index < seeds.len) : (seeds_index += 2) { + last_values.clearRetainingCapacity(); + working_values.clearRetainingCapacity(); + + std.debug.print("= seeding {d}/{d} =\n", .{ seeds_index, seeds.len }); const start = seeds[seeds_index]; const range = seeds[seeds_index + 1]; for (start..start + range) |seed| { - try last_components.append(.{ .name = "seed", .value = seed }); + // std.debug.print("seed {d}\n", .{seed}); + try working_values.put(seed, {}); } - } - var current_component: []const u8 = undefined; - while (it.next()) |line| { - if (line.len == 0) { - for (last_components.items, 0..) |comp, index| { - if (!mem.eql(u8, comp.name, current_component)) { - last_components.items[index] = .{ .name = current_component, .value = comp.value }; + // Reset parse input. + it = util.splitLines(input); + _ = it.next().?; + var current_component: []const u8 = undefined; + while (it.next()) |line| { + if (line.len == 0) { + std.debug.print("== swap ==\n", .{}); + // Copy all remaining + var lv_it = last_values.iterator(); + while (lv_it.next()) |entry| { + try working_values.put(entry.key_ptr.*, {}); } - } - } else if (mem.endsWith(u8, line, "map:")) { - var t_it = util.split(line, ' '); - var comp_it = util.split(t_it.next().?, '-'); - _ = comp_it.next(); // A - _ = comp_it.next(); // to - current_component = comp_it.next().?; // B - } else { - const map = try util.parseIntsScalar(usize, alloc, line, .{}); - defer alloc.free(map); - // map values - map_blk: for (last_components.items, 0..) |comp, index| { - if (mem.eql(u8, comp.name, current_component)) { - std.debug.print("{d} already mapped\n", .{index}); - continue :map_blk; + // Swap working sets + mem.swap(UsizeSet, &last_values, &working_values); + working_values.clearRetainingCapacity(); + } else if (mem.endsWith(u8, line, "map:")) { + var t_it = util.split(line, ' '); + var comp_it = util.split(t_it.next().?, '-'); + _ = comp_it.next(); // A + _ = comp_it.next(); // to + current_component = comp_it.next().?; // B + } else { + std.debug.print("== {s} {d}/{d}\n", .{ current_component, working_values.count(), last_values.count() }); + const map = try util.parseIntsScalar(usize, alloc, line, .{}); + defer alloc.free(map); + + var to_delete = UsizeSet.init(alloc); + defer to_delete.deinit(); + var lv_it = last_values.iterator(); + while (lv_it.next()) |entry| { + // if (transitioned[index]) { + // std.debug.print("{d} already mapped\n", .{index}); + // continue :map_blk; + // } + const item = entry.key_ptr.*; + if (map[1] <= item and item <= map[1] + map[2]) { + const offset = @as(isize, @intCast(map[0])) - @as(isize, @intCast(map[1])); + const res: usize = @intCast(@as(isize, @intCast(item)) + offset); + // std.debug.print("{d} => {d}\n", .{ item, res }); + try working_values.put(res, {}); + try to_delete.put(item, {}); + } } - if (map[1] <= comp.value and comp.value <= map[1] + map[2]) { - const offset = @as(isize, @intCast(map[0])) - @as(isize, @intCast(map[1])); - const res: usize = @intCast(@as(isize, @intCast(comp.value)) + offset); - std.debug.print("{d} {d} => {d}\n", .{ index, comp.value, res }); - last_components.items[index] = .{ .name = current_component, .value = res }; + var td_it = to_delete.iterator(); + while (td_it.next()) |entry| { + // std.debug.print("pop {d}\n", .{entry.key_ptr.*}); + _ = last_values.remove(entry.key_ptr.*); } } } - } - var low_loc: usize = std.math.maxInt(usize); - for (last_components.items) |comp| { - std.debug.print("{s} ", .{comp.name}); - low_loc = @min(low_loc, comp.value); + var lv_it = last_values.iterator(); + while (lv_it.next()) |value| { + low_loc = @min(low_loc, value.key_ptr.*); + } } return .{ .a = low_loc, .b = 0 };