Aleksei Dorokhov 7 месяцев назад
Родитель
Сommit
6e0e22182e
1 измененных файлов с 47 добавлено и 45 удалено
  1. 47 45
      day8/day8b.zig

+ 47 - 45
day8/day8b.zig

@@ -1,8 +1,7 @@
 const std = @import("std");
 
+var printBuffer: [1024]u8 = undefined;
 var allocatorBuffer: [100*1024*1024]u8 = undefined;
-var fb_alloc = std.heap.FixedBufferAllocator.init(&allocatorBuffer);
-var allocator = fb_alloc.allocator();
 
 const Junction = struct {
     x: i64 = 0,
@@ -24,44 +23,41 @@ const JunctionPair = struct {
     }
 };
 
-const Circuit = struct {
-    junctions: std.AutoHashMap(usize,bool),
-    wires: std.AutoHashMap(usize,bool),
-
-    pub fn clear(self: *Circuit) void {
-        self.junctions.clearRetainingCapacity();
-        self.wires.clearRetainingCapacity();
-    }
-
-    pub fn addOtherCircuit(self: *Circuit, other: Circuit) !void {
-        var junctionsIterator = other.junctions.keyIterator();
-        while(junctionsIterator.next()) |junction| {
-            try self.junctions.put(junction.*, true);
-        }
+const JunctionIdNode = struct {
+    id: usize = 0,
+    node: std.DoublyLinkedList.Node = .{},
+};
 
-        var wiresIterator = other.wires.keyIterator();
-        while(wiresIterator.next()) |wire| {
-            try self.wires.put(wire.*, true);
-        }
-    }
+const Circuit = struct {
+    junctions: std.DoublyLinkedList = .{},
+    node: std.DoublyLinkedList.Node = .{},
 };
 
 fn junctionPairCompareLT(junctions: []Junction, left: JunctionPair, right: JunctionPair) bool {
     return left.distanceSquared(junctions) < right.distanceSquared(junctions);
 }
 
-fn circuitPairCompareGT(_: void, left: Circuit, right: Circuit) bool {
-    return left.junctions.count() > right.junctions.count();
-}
-
 const Error = error {
     JunctionIdNotFound,
 };
 
-fn findCircuitForJunction(circuits: std.ArrayList(Circuit), junctionId: usize) !usize {
-    for (0 .. circuits.items.len) |circuitId| {
-        if (circuits.items[circuitId].junctions.contains(junctionId)) {
-            return circuitId;
+fn findCircuitForJunction(circuits: std.DoublyLinkedList, junctionId: usize) !*std.DoublyLinkedList.Node {
+    var circuitIter = circuits.first;
+    while (circuitIter) |circuitNode| : (circuitIter = circuitNode.next) {
+        const circuit: *Circuit = @fieldParentPtr("node", circuitNode);
+
+        var found = false;
+        var junctionIdIter = circuit.junctions.first;
+        while (junctionIdIter) |node| : (junctionIdIter = node.next) {
+            const junctionIdNode: *JunctionIdNode = @fieldParentPtr("node", node);
+            if (junctionIdNode.id == junctionId) {
+                found = true;
+                break;
+            }
+        }
+
+        if (found) {
+            return circuitNode;
         }
     }
 
@@ -69,7 +65,8 @@ fn findCircuitForJunction(circuits: std.ArrayList(Circuit), junctionId: usize) !
 }
 
 pub fn main() !void {
-    var printBuf: [1024]u8 = undefined;
+    var fb_alloc = std.heap.FixedBufferAllocator.init(&allocatorBuffer);
+    var allocator = fb_alloc.allocator();
 
     const inputFile = try std.fs.cwd().openFile(
         "input.txt",
@@ -108,35 +105,40 @@ pub fn main() !void {
     }
     std.sort.block(JunctionPair, junctionPairs.items, junctions.items, junctionPairCompareLT);
 
-
-    var circuits = std.ArrayList(Circuit).empty;
+    var junctionIdNodeStorage = try std.ArrayList(JunctionIdNode).initCapacity(allocator, junctions.items.len);
+    var circuitsStorage = try std.ArrayList(Circuit).initCapacity(allocator, junctions.items.len);
+    var circuits: std.DoublyLinkedList = .{};
     for (0..junctions.items.len) |a| {
-        var newCircuit = try circuits.addOne(allocator);
-        newCircuit.junctions = std.AutoHashMap(usize,bool).init(allocator);
-        newCircuit.wires = std.AutoHashMap(usize,bool).init(allocator);
-        try newCircuit.junctions.put(a, true);
+        var newJunctionIdNode = try junctionIdNodeStorage.addOne(allocator);
+        newJunctionIdNode.id = a;
+
+        var newCircuit = try circuitsStorage.addOne(allocator);
+        newCircuit.junctions = .{};
+        newCircuit.junctions.append(&newJunctionIdNode.node);
+        circuits.append(&newCircuit.node);
     }
 
-    var circuitsCount:usize = circuits.items.len;
+    var circuitsCount:usize = junctions.items.len;
     for (0..junctionPairs.items.len) |wire| {
         const a = junctionPairs.items[wire].a;
         const b = junctionPairs.items[wire].b;
 
-        const circuitA = try findCircuitForJunction(circuits, a);
-        const circuitB = try findCircuitForJunction(circuits, b);
-
-        if (circuitA == circuitB) {
+        const circuitANode = try findCircuitForJunction(circuits, a);
+        const circuitBNode = try findCircuitForJunction(circuits, b);
+        if (circuitANode == circuitBNode) {
             continue;
         }
 
-        try circuits.items[circuitA].addOtherCircuit(circuits.items[circuitB]);
-        try circuits.items[circuitA].wires.put(wire, true);
-        circuits.items[circuitB].clear();
+        const circuitA: *Circuit = @fieldParentPtr("node", circuitANode);
+        const circuitB: *Circuit = @fieldParentPtr("node", circuitBNode);
+
+        circuitA.junctions.concatByMoving(&circuitB.junctions);
+        circuits.remove(circuitBNode);
 
         circuitsCount -= 1;
         if (circuitsCount == 1) {
             try std.fs.File.stdout().writeAll(
-              try std.fmt.bufPrint(&printBuf, "{}\n", .{junctions.items[a].x*junctions.items[b].x}));
+              try std.fmt.bufPrint(&printBuffer, "{}\n", .{junctions.items[a].x*junctions.items[b].x}));
             break;
         }
     }