day8a.zig 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156
  1. const std = @import("std");
  2. var allocatorBuffer: [100*1024*1024]u8 = undefined;
  3. var fb_alloc = std.heap.FixedBufferAllocator.init(&allocatorBuffer);
  4. var allocator = fb_alloc.allocator();
  5. const Junction = struct {
  6. x: i64 = 0,
  7. y: i64 = 0,
  8. z: i64 = 0,
  9. };
  10. const JunctionPair = struct {
  11. a: usize = 0,
  12. b: usize = 0,
  13. pub fn distanceSquared(self: JunctionPair, junctions: []Junction) i64 {
  14. const ja = &junctions[self.a];
  15. const jb = &junctions[self.b];
  16. const dx = ja.x - jb.x;
  17. const dy = ja.y - jb.y;
  18. const dz = ja.z - jb.z;
  19. return dx * dx + dy * dy + dz * dz;
  20. }
  21. };
  22. const Circuit = struct {
  23. junctions: std.AutoHashMap(usize,bool),
  24. wires: std.AutoHashMap(usize,bool),
  25. pub fn clear(self: *Circuit) void {
  26. self.junctions.clearRetainingCapacity();
  27. self.wires.clearRetainingCapacity();
  28. }
  29. pub fn addOtherCircuit(self: *Circuit, other: Circuit) !void {
  30. var junctionsIterator = other.junctions.keyIterator();
  31. while(junctionsIterator.next()) |junction| {
  32. try self.junctions.put(junction.*, true);
  33. }
  34. var wiresIterator = other.wires.keyIterator();
  35. while(wiresIterator.next()) |wire| {
  36. try self.wires.put(wire.*, true);
  37. }
  38. }
  39. };
  40. fn junctionPairCompareLT(junctions: []Junction, left: JunctionPair, right: JunctionPair) bool {
  41. return left.distanceSquared(junctions) < right.distanceSquared(junctions);
  42. }
  43. fn circuitPairCompareGT(_: void, left: Circuit, right: Circuit) bool {
  44. return left.junctions.count() > right.junctions.count();
  45. }
  46. const Error = error {
  47. JunctionIdNotFound,
  48. };
  49. fn findCircuitForJunction(circuits: std.ArrayList(Circuit), junctionId: usize) !usize {
  50. for (0 .. circuits.items.len) |circuitId| {
  51. if (circuits.items[circuitId].junctions.contains(junctionId)) {
  52. return circuitId;
  53. }
  54. }
  55. return Error.JunctionIdNotFound;
  56. }
  57. pub fn main() !void {
  58. var printBuf: [1024]u8 = undefined;
  59. const inputFile = try std.fs.cwd().openFile(
  60. "input.txt",
  61. .{
  62. .mode = .read_only,
  63. },
  64. );
  65. defer inputFile.close();
  66. var inputFileBuffer: [1024]u8 = undefined;
  67. var inputFileReader = inputFile.reader(&inputFileBuffer);
  68. const inputFileSize = try inputFileReader.getSize();
  69. const inputBuffer = try allocator.alloc(u8, inputFileSize);
  70. try inputFileReader.interface.readSliceAll(inputBuffer);
  71. var junctions = std.ArrayList(Junction).empty;
  72. var i = std.mem.tokenizeScalar(u8, inputBuffer, '\n');
  73. while (i.next()) |newJunctionText| {
  74. var j = std.mem.tokenizeAny(u8, newJunctionText, ",\n");
  75. var newJunction = try junctions.addOne(allocator);
  76. newJunction.x = try std.fmt.parseInt(i64, j.next().?, 10);
  77. newJunction.y = try std.fmt.parseInt(i64, j.next().?, 10);
  78. newJunction.z = try std.fmt.parseInt(i64, j.next().?, 10);
  79. }
  80. var junctionPairs = std.ArrayList(JunctionPair).empty;
  81. for (0..junctions.items.len) |a| {
  82. for (a+1..junctions.items.len) |b| {
  83. var newJunctionPair = try junctionPairs.addOne(allocator);
  84. newJunctionPair.a = a;
  85. newJunctionPair.b = b;
  86. }
  87. }
  88. std.sort.block(JunctionPair, junctionPairs.items, junctions.items, junctionPairCompareLT);
  89. var circuits = std.ArrayList(Circuit).empty;
  90. for (0..junctions.items.len) |a| {
  91. var newCircuit = try circuits.addOne(allocator);
  92. newCircuit.junctions = std.AutoHashMap(usize,bool).init(allocator);
  93. newCircuit.wires = std.AutoHashMap(usize,bool).init(allocator);
  94. try newCircuit.junctions.put(a, true);
  95. }
  96. var wiresCount:usize = 0;
  97. for (0..junctionPairs.items.len) |wire| {
  98. const a = junctionPairs.items[wire].a;
  99. const b = junctionPairs.items[wire].b;
  100. const circuitA = try findCircuitForJunction(circuits, a);
  101. const circuitB = try findCircuitForJunction(circuits, b);
  102. if (circuitA != circuitB) {
  103. try circuits.items[circuitA].addOtherCircuit(circuits.items[circuitB]);
  104. try circuits.items[circuitA].wires.put(wire, true);
  105. circuits.items[circuitB].clear();
  106. }
  107. wiresCount += 1;
  108. if (wiresCount >= 1000) {
  109. break;
  110. }
  111. }
  112. std.sort.block(Circuit, circuits.items, {}, circuitPairCompareGT);
  113. for (0..circuits.items.len) |circuitIndex| {
  114. try std.fs.File.stdout().writeAll(
  115. try std.fmt.bufPrint(&printBuf, "circuit: {}\n", .{circuits.items[circuitIndex].junctions.count()}));
  116. }
  117. var count: usize = 1;
  118. for (0..3) |circuitIndex| {
  119. count *= circuits.items[circuitIndex].junctions.count();
  120. }
  121. try std.fs.File.stdout().writeAll(
  122. try std.fmt.bufPrint(&printBuf, "count = {}\n", .{count}));
  123. }