| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156 |
- 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}));
- }
|