|
@@ -1,8 +1,7 @@
|
|
|
const std = @import("std");
|
|
const std = @import("std");
|
|
|
|
|
|
|
|
|
|
+var printBuffer: [1024]u8 = undefined;
|
|
|
var allocatorBuffer: [100*1024*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 {
|
|
const Junction = struct {
|
|
|
x: i64 = 0,
|
|
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 {
|
|
fn junctionPairCompareLT(junctions: []Junction, left: JunctionPair, right: JunctionPair) bool {
|
|
|
return left.distanceSquared(junctions) < right.distanceSquared(junctions);
|
|
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 {
|
|
const Error = error {
|
|
|
JunctionIdNotFound,
|
|
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 {
|
|
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(
|
|
const inputFile = try std.fs.cwd().openFile(
|
|
|
"input.txt",
|
|
"input.txt",
|
|
@@ -108,35 +105,40 @@ pub fn main() !void {
|
|
|
}
|
|
}
|
|
|
std.sort.block(JunctionPair, junctionPairs.items, junctions.items, junctionPairCompareLT);
|
|
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| {
|
|
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| {
|
|
for (0..junctionPairs.items.len) |wire| {
|
|
|
const a = junctionPairs.items[wire].a;
|
|
const a = junctionPairs.items[wire].a;
|
|
|
const b = junctionPairs.items[wire].b;
|
|
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;
|
|
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;
|
|
circuitsCount -= 1;
|
|
|
if (circuitsCount == 1) {
|
|
if (circuitsCount == 1) {
|
|
|
try std.fs.File.stdout().writeAll(
|
|
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;
|
|
break;
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|