This commit is contained in:
		| @@ -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 }; | ||||
|   | ||||
		Reference in New Issue
	
	Block a user