فهرست منبع

Solved day10 part 1

Aleksei Dorokhov 6 ماه پیش
والد
کامیت
aeac240b0a
6فایلهای تغییر یافته به همراه404 افزوده شده و 0 حذف شده
  1. 4 0
      day10/.gitignore
  2. 23 0
      day10/build.zig
  3. 59 0
      day10/day10a.zig
  4. 146 0
      day10/day10b.zig
  5. 77 0
      day10/indicators.zig
  6. 95 0
      day10/input.zig

+ 4 - 0
day10/.gitignore

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

+ 23 - 0
day10/build.zig

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

+ 59 - 0
day10/day10a.zig

@@ -0,0 +1,59 @@
+const std = @import("std");
+
+const inputModule = @import("input.zig");
+const indicatorsModule = @import("indicators.zig");
+
+const MachineScheme = inputModule.MachineScheme;
+const readInput = inputModule.readInput;
+const Indicators = indicatorsModule.Indicators;
+const IndicatorSet = indicatorsModule.IndicatorSet;
+const createIndicators = indicatorsModule.createIndicators;
+
+const print = std.debug.print;
+const readInputIntoString = inputModule.readInputIntoString;
+const readMachineScheme = inputModule.readMachineScheme;
+
+
+pub fn main() !void {
+    var gpa = std.heap.GeneralPurposeAllocator(.{}){};
+    const allocator = gpa.allocator();
+
+    var totalButtonPresses: i32 = 0;
+
+    const machineSchemes =  try readInput(allocator, "input.txt");
+    for (machineSchemes) |machineScheme| {
+        var initialIndicators = try createIndicators(allocator, machineScheme);
+
+        if (initialIndicators.isComplete()) {
+            continue;
+        }
+
+        var buttonPresses: i32 = 1;
+        var indicatorsSet = IndicatorSet.init(allocator);
+        try initialIndicators.applyAllButtons(allocator, &indicatorsSet);
+
+        outer: while(true) {
+            var it = indicatorsSet.keyIterator();
+            while (it.next()) |indicators| {
+                if (indicators.isComplete()) {
+                    break :outer;
+                }
+            }
+
+            buttonPresses += 1;
+            
+            var nextIndicatorsSet = IndicatorSet.init(allocator);
+            it = indicatorsSet.keyIterator();
+            while (it.next()) |indicators| {
+                try indicators.applyAllButtons(allocator, &nextIndicatorsSet);
+            }
+
+            indicatorsSet = nextIndicatorsSet;
+        }
+        
+        totalButtonPresses += buttonPresses;
+    }
+
+    print("total: {d}\n", .{totalButtonPresses});
+}
+

+ 146 - 0
day10/day10b.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;
+        }
+    }
+}
+

+ 77 - 0
day10/indicators.zig

@@ -0,0 +1,77 @@
+const std = @import("std");
+
+const inputModule = @import("input.zig");
+
+const MachineScheme = inputModule.MachineScheme;
+
+
+pub const Indicators = struct {
+    lights: []bool,
+    scheme: MachineScheme,
+
+    pub fn isComplete(self: Indicators) bool {
+        for (0..self.lights.len) |i|  {
+            if (self.lights[i] != self.scheme.indicatorDiagram[i]) {
+                return false;
+            }
+        }
+        
+        return true;
+    }
+
+    pub fn applyButton(self: *Indicators, buttonIndex: usize) void {
+        for (self.scheme.buttons[buttonIndex].indicatorsConnected) |toggleIndicator| {
+            self.lights[toggleIndicator] = !self.lights[toggleIndicator];
+        }
+    }
+
+    pub fn applyAllButtons(self: Indicators, allocator: std.mem.Allocator,
+                           nextIndicators: *IndicatorSet) !void {
+        for (0..self.scheme.buttons.len) |buttonIndex| {
+            var newIndicators = try createIndicators(allocator, self.scheme);
+            @memcpy(newIndicators.lights, self.lights);
+            newIndicators.applyButton(buttonIndex);
+            try nextIndicators.put(newIndicators, true);
+        }
+    }
+};
+
+pub fn createIndicators(allocator: std.mem.Allocator, scheme: MachineScheme) !Indicators {
+    const lights = try allocator.alloc(bool, scheme.indicatorDiagram.len);
+    for (lights) |*light| {
+        light.* = false;
+    }
+
+    const indicators: Indicators = .{
+        .lights = lights,
+        .scheme = scheme,
+    };
+
+    return indicators;
+}
+
+const IndicatorsContext = struct {
+    pub fn hash(ctx: IndicatorsContext, key: Indicators) u64 {
+        _ = ctx;
+        
+        var hasher = std.hash.Wyhash.init(0);
+        for (key.lights)  |*light| {
+            hasher.update(std.mem.asBytes(light));
+        }
+        return hasher.final();
+    }
+
+    pub fn eql(ctx: IndicatorsContext, a: Indicators, b: Indicators) bool {
+        _ = ctx;
+        
+        for (0..a.lights.len)  |i| {
+            if (a.lights[i] != b.lights[i]) {
+                return false;
+            }
+        }
+        return true;
+    }
+};
+
+
+pub const IndicatorSet = std.HashMap(Indicators, bool, IndicatorsContext, std.hash_map.default_max_load_percentage);

+ 95 - 0
day10/input.zig

@@ -0,0 +1,95 @@
+const std = @import("std");
+const print = std.debug.print;
+
+pub const Button = struct {
+    indicatorsConnected: []usize,
+};
+
+pub const MachineScheme = struct {
+    indicatorDiagram: []bool,
+    buttons: []Button,
+    joltages: []i32,
+};
+
+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;
+}
+
+fn parseIndicatorDiagram(allocator: std.mem.Allocator, text: []const u8) ![]bool {
+    var indicators = std.ArrayList(bool).empty;
+
+    for (text) |c| {
+        const newIndicator = try indicators.addOne(allocator);
+        if (c == '#') {
+            newIndicator.* = true;
+        } else {
+            newIndicator.* = false;
+        }
+    }
+
+    return indicators.items;
+}
+
+fn parseButton(allocator: std.mem.Allocator, text: []const u8) !Button {
+    var indicators = std.ArrayList(usize).empty;
+    var tokens = std.mem.tokenizeScalar(u8, text, ',');
+    while (tokens.next()) |newIndicatorText| {
+        const newIndicator = try indicators.addOne(allocator);
+        newIndicator.* = try std.fmt.parseInt(usize, newIndicatorText, 10);
+    }
+
+    const button: Button = .{
+        .indicatorsConnected = indicators.items,
+    };
+    print("Button: {[button]any}\n", .{.button = button});
+    return button;
+}
+
+pub fn readMachineScheme(allocator: std.mem.Allocator, line: []const u8) !MachineScheme {
+    var indicatorDiagram: []bool = &.{};
+    var buttons = std.ArrayList(Button).empty;
+    const joltages:[]i32 = &.{};
+
+    var tokens = std.mem.tokenizeScalar(u8, line, ' ');
+    while (tokens.next()) |token| {
+        const tokenContent = token[1..token.len-1];
+        if (token[0] == '[') {
+            indicatorDiagram = try parseIndicatorDiagram(allocator, tokenContent);
+        } else if (token[0] == '(') {
+            const newButton = try buttons.addOne(allocator);
+            newButton.* = try parseButton(allocator, tokenContent);
+        }
+    }
+
+    const machineScheme: MachineScheme = .{
+        .indicatorDiagram = indicatorDiagram,
+        .buttons = buttons.items,
+        .joltages = joltages,
+    };
+
+    return machineScheme;
+}
+
+pub fn readInput(allocator: std.mem.Allocator, fileName: []const u8) ![]MachineScheme {
+    const inputBuffer = try readInputIntoString(allocator, fileName);
+
+    var machineSchemes = std.ArrayList(MachineScheme).empty;
+
+    var lines = std.mem.tokenizeScalar(u8, inputBuffer, '\n');
+    while (lines.next()) |line| {
+        const newMachineScheme = try machineSchemes.addOne(allocator);
+        newMachineScheme.* = try readMachineScheme(allocator, line);
+    }
+
+    return machineSchemes.items;
+}