day8b.zig 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144
  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 circuitsCount:usize = circuits.items.len;
  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. continue;
  104. }
  105. try circuits.items[circuitA].addOtherCircuit(circuits.items[circuitB]);
  106. try circuits.items[circuitA].wires.put(wire, true);
  107. circuits.items[circuitB].clear();
  108. circuitsCount -= 1;
  109. if (circuitsCount == 1) {
  110. try std.fs.File.stdout().writeAll(
  111. try std.fmt.bufPrint(&printBuf, "{}\n", .{junctions.items[a].x*junctions.items[b].x}));
  112. break;
  113. }
  114. }
  115. }