소스 검색

Started solving day12

Aleksei Dorokhov 7 달 전
부모
커밋
246d7ac7a6
4개의 변경된 파일317개의 추가작업 그리고 0개의 파일을 삭제
  1. 3 0
      day12/.gitignore
  2. 23 0
      day12/build.zig
  3. 145 0
      day12/day12a.zig
  4. 146 0
      day12/day12b.zig

+ 3 - 0
day12/.gitignore

@@ -0,0 +1,3 @@
+input.txt
+.zig-cache
+zig-out

+ 23 - 0
day12/build.zig

@@ -0,0 +1,23 @@
+const std = @import("std");
+
+pub fn build(b: *std.Build) void {
+    const exe1 = b.addExecutable(.{
+        .name = "day12a",
+        .root_module = b.createModule(.{
+            .root_source_file = b.path("day12a.zig"),
+            .target = b.graph.host,
+        }),
+    });
+
+    b.installArtifact(exe1);
+
+    const exe2 = b.addExecutable(.{
+        .name = "day12b",
+        .root_module = b.createModule(.{
+            .root_source_file = b.path("day12b.zig"),
+            .target = b.graph.host,
+        }),
+    });
+    
+    b.installArtifact(exe2);
+}

+ 145 - 0
day12/day12a.zig

@@ -0,0 +1,145 @@
+const std = @import("std");
+
+var allocatorBuffer: [100*1024*1024]u8 = undefined;
+
+const Shape = struct {
+    data: [9]u8,
+
+    fn getCell(self: *const Shape, row: u8, col: u8) u8 {
+        return self.data[row*3 + col];
+    }
+
+    fn setCell(self: *Shape, row: u8, col: u8, cell: u8) void {
+        self.data[row*3 + col] = cell;
+    }
+};
+
+const Area = struct {
+    rows: u8,
+    cols: u8,
+    shapesCount: []u8,
+};
+
+const Input = struct {
+    shapes: []Shape,
+    areas: []Area,
+};
+
+pub fn parseShape(shapeText: []const u8) Shape {
+    var it = std.mem.tokenizeScalar(u8, shapeText, '\n');
+    _ = it.next(); // skip header
+    
+    var shape: Shape = .{
+        .data = undefined,
+    };
+    
+    for (0..3) |row| {
+        const rowText = it.next().?;
+        for (0..3) |col| {
+            shape.setCell(@intCast(row), @intCast(col), rowText[col]);
+        }
+    }
+
+    return shape;
+}
+
+pub fn parseArea(allocator: std.mem.Allocator, line: []const u8) !Area {
+    var it = std.mem.tokenizeSequence(u8, line, ": ");
+    const sizeText = it.next().?;
+    const shapesCountText = it.next().?;
+
+    var sizeTextIt = std.mem.tokenizeScalar(u8, sizeText, 'x');
+    const rowsText = sizeTextIt.next().?;
+    const colsText = sizeTextIt.next().?;
+
+    const rows = try std.fmt.parseInt(u8, rowsText, 10);
+    const cols = try std.fmt.parseInt(u8, colsText, 10);
+
+    var shapesCountTextIt = std.mem.tokenizeScalar(u8, shapesCountText, ' ');
+    var shapesCount = std.ArrayList(u8).empty;
+    while (shapesCountTextIt.next()) |shapeCountText| {
+      const shapeCount = try shapesCount.addOne(allocator);
+      shapeCount.* = try std.fmt.parseInt(u8, shapeCountText, 10);
+    }
+    
+    const area: Area = .{
+        .rows = rows,
+        .cols = cols,
+        .shapesCount = shapesCount.items,
+    };
+
+    return area;
+}
+
+pub fn parseInput(allocator: std.mem.Allocator, inputBuffer: []u8) !Input {
+    var shapes = std.ArrayList(Shape).empty;
+    var areas = std.ArrayList(Area).empty;
+
+    var i = std.mem.tokenizeSequence(u8, inputBuffer, "\n\n");
+    while (i.next()) |inputBlock| {
+        if (inputBlock.len >= 2 and inputBlock[1] == ':') {
+            const shape = try shapes.addOne(allocator);
+            shape.* = parseShape(inputBlock);
+        } else {
+            var it = std.mem.tokenizeScalar(u8, inputBlock, '\n');
+            while(it.next()) |line| {
+                const area = try areas.addOne(allocator);
+                area.* = try parseArea(allocator, line);
+            }
+        }
+    }
+
+    const input: Input = .{
+        .shapes = shapes.items,
+        .areas = areas.items,
+    };
+
+    return input;
+}
+
+pub fn readInputIntoString(allocator: std.mem.Allocator, fileName: []const u8) ![]u8 {
+    const inputFile = try std.fs.cwd().openFile(
+        fileName, .{.mode = .read_only,});
+    defer inputFile.close();
+
+    var inputFileReader = inputFile.reader(
+      try allocator.alignedAlloc(u8, null, 1024));
+    const inputFileSize = try inputFileReader.getSize();
+
+    const inputBuffer = try allocator.alignedAlloc(u8, null, inputFileSize);
+    try inputFileReader.interface.readSliceAll(inputBuffer);
+    return inputBuffer;
+}
+
+pub fn main() !void {
+    var fb_alloc = std.heap.FixedBufferAllocator.init(&allocatorBuffer);
+    const allocator = fb_alloc.allocator();
+
+    const inputBuffer = try readInputIntoString(allocator, "input.txt");
+    const input = try parseInput(allocator, inputBuffer);
+    
+    for (input.areas) |area| {
+         try std.fs.File.stdout().writeAll(
+           try std.fmt.allocPrint(allocator, "area: rows={d}, cols={d}, shapes=[ ", .{area.rows, area.cols}));
+         for (area.shapesCount) |shapeCount| {
+             try std.fs.File.stdout().writeAll(
+               try std.fmt.allocPrint(allocator, "{d}, ", .{shapeCount}));
+         }
+         try std.fs.File.stdout().writeAll("]\n");
+    }
+
+    for (input.shapes) |shape| {
+        try std.fs.File.stdout().writeAll("shape:\n");
+        for (0..3) |row| {
+            for (0..3) |col| {
+                const cell = shape.getCell(@intCast(row), @intCast(col));
+                try std.fs.File.stdout().writeAll(
+                  try std.fmt.allocPrint(allocator, "{c}", .{cell}));
+
+            }
+            try std.fs.File.stdout().writeAll("\n");
+        }
+        try std.fs.File.stdout().writeAll("\n");
+    }
+}
+

+ 146 - 0
day12/day12b.zig

@@ -0,0 +1,146 @@
+const std = @import("std");
+
+var printBuffer: [1024]u8 = undefined;
+var allocatorBuffer: [100*1024*1024]u8 = undefined;
+
+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 JunctionIdNode = struct {
+    id: usize = 0,
+    node: std.DoublyLinkedList.Node = .{},
+};
+
+const Circuit = struct {
+    junctions: std.DoublyLinkedList = .{},
+    node: std.DoublyLinkedList.Node = .{},
+};
+
+fn junctionPairCompareLT(junctions: []Junction, left: JunctionPair, right: JunctionPair) bool {
+    return left.distanceSquared(junctions) < right.distanceSquared(junctions);
+}
+
+const Error = error {
+    JunctionIdNotFound,
+};
+
+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;
+        }
+    }
+
+    return Error.JunctionIdNotFound;
+}
+
+pub fn main() !void {
+    var fb_alloc = std.heap.FixedBufferAllocator.init(&allocatorBuffer);
+    var allocator = fb_alloc.allocator();
+
+    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 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| {
+        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 = junctions.items.len;
+    for (0..junctionPairs.items.len) |wire| {
+        const a = junctionPairs.items[wire].a;
+        const b = junctionPairs.items[wire].b;
+
+        const circuitANode = try findCircuitForJunction(circuits, a);
+        const circuitBNode = try findCircuitForJunction(circuits, b);
+        if (circuitANode == circuitBNode) {
+            continue;
+        }
+
+        const circuitA: *Circuit = @fieldParentPtr("node", circuitANode);
+        const circuitB: *Circuit = @fieldParentPtr("node", circuitBNode);
+
+        circuitA.junctions.concatByMoving(&circuitB.junctions);
+        circuits.remove(circuitBNode);
+
+        circuitsCount -= 1;
+        if (circuitsCount == 1) {
+            try std.fs.File.stdout().writeAll(
+              try std.fmt.bufPrint(&printBuffer, "{}\n", .{junctions.items[a].x*junctions.items[b].x}));
+            break;
+        }
+    }
+}
+