|
|
@@ -0,0 +1,156 @@
|
|
|
+const std = @import("std");
|
|
|
+
|
|
|
+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,
|
|
|
+ y: i64 = 0,
|
|
|
+ z: i64 = 0,
|
|
|
+};
|
|
|
+
|
|
|
+const JunctionPair = struct {
|
|
|
+ a: usize = 0,
|
|
|
+ b: usize = 0,
|
|
|
+
|
|
|
+ pub fn distanceSquared(self: JunctionPair, junctions: []Junction) i64 {
|
|
|
+ const ja = &junctions[self.a];
|
|
|
+ const jb = &junctions[self.b];
|
|
|
+ const dx = ja.x - jb.x;
|
|
|
+ const dy = ja.y - jb.y;
|
|
|
+ const dz = ja.z - jb.z;
|
|
|
+ return dx * dx + dy * dy + dz * dz;
|
|
|
+ }
|
|
|
+};
|
|
|
+
|
|
|
+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);
|
|
|
+ }
|
|
|
+
|
|
|
+ var wiresIterator = other.wires.keyIterator();
|
|
|
+ while(wiresIterator.next()) |wire| {
|
|
|
+ try self.wires.put(wire.*, true);
|
|
|
+ }
|
|
|
+ }
|
|
|
+};
|
|
|
+
|
|
|
+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;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ return Error.JunctionIdNotFound;
|
|
|
+}
|
|
|
+
|
|
|
+pub fn main() !void {
|
|
|
+ var printBuf: [1024]u8 = undefined;
|
|
|
+
|
|
|
+ const inputFile = try std.fs.cwd().openFile(
|
|
|
+ "input.txt",
|
|
|
+ .{
|
|
|
+ .mode = .read_only,
|
|
|
+ },
|
|
|
+ );
|
|
|
+ defer inputFile.close();
|
|
|
+
|
|
|
+ var inputFileBuffer: [1024]u8 = undefined;
|
|
|
+ var inputFileReader = inputFile.reader(&inputFileBuffer);
|
|
|
+ const inputFileSize = try inputFileReader.getSize();
|
|
|
+
|
|
|
+ const inputBuffer = try allocator.alloc(u8, inputFileSize);
|
|
|
+ try inputFileReader.interface.readSliceAll(inputBuffer);
|
|
|
+
|
|
|
+ var junctions = std.ArrayList(Junction).empty;
|
|
|
+
|
|
|
+ var i = std.mem.tokenizeScalar(u8, inputBuffer, '\n');
|
|
|
+ while (i.next()) |newJunctionText| {
|
|
|
+ var j = std.mem.tokenizeAny(u8, newJunctionText, ",\n");
|
|
|
+
|
|
|
+ var newJunction = try junctions.addOne(allocator);
|
|
|
+ newJunction.x = try std.fmt.parseInt(i64, j.next().?, 10);
|
|
|
+ newJunction.y = try std.fmt.parseInt(i64, j.next().?, 10);
|
|
|
+ newJunction.z = try std.fmt.parseInt(i64, j.next().?, 10);
|
|
|
+ }
|
|
|
+
|
|
|
+ var junctionPairs = std.ArrayList(JunctionPair).empty;
|
|
|
+ for (0..junctions.items.len) |a| {
|
|
|
+ for (a+1..junctions.items.len) |b| {
|
|
|
+ var newJunctionPair = try junctionPairs.addOne(allocator);
|
|
|
+ newJunctionPair.a = a;
|
|
|
+ newJunctionPair.b = b;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ std.sort.block(JunctionPair, junctionPairs.items, junctions.items, junctionPairCompareLT);
|
|
|
+
|
|
|
+
|
|
|
+ var circuits = std.ArrayList(Circuit).empty;
|
|
|
+ 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 wiresCount:usize = 0;
|
|
|
+ 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) {
|
|
|
+ try circuits.items[circuitA].addOtherCircuit(circuits.items[circuitB]);
|
|
|
+ try circuits.items[circuitA].wires.put(wire, true);
|
|
|
+ circuits.items[circuitB].clear();
|
|
|
+ }
|
|
|
+
|
|
|
+ wiresCount += 1;
|
|
|
+ if (wiresCount >= 1000) {
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ std.sort.block(Circuit, circuits.items, {}, circuitPairCompareGT);
|
|
|
+ for (0..circuits.items.len) |circuitIndex| {
|
|
|
+ try std.fs.File.stdout().writeAll(
|
|
|
+ try std.fmt.bufPrint(&printBuf, "circuit: {}\n", .{circuits.items[circuitIndex].junctions.count()}));
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ var count: usize = 1;
|
|
|
+ for (0..3) |circuitIndex| {
|
|
|
+ count *= circuits.items[circuitIndex].junctions.count();
|
|
|
+ }
|
|
|
+
|
|
|
+ try std.fs.File.stdout().writeAll(
|
|
|
+ try std.fmt.bufPrint(&printBuf, "count = {}\n", .{count}));
|
|
|
+
|
|
|
+}
|
|
|
+
|