const std = @import("std"); pub const title = "Day 10: Factory"; pub fn run(allocator: std.mem.Allocator) !void { //const input = @embedFile("./input/day10.txt"); const input = \\[.##.] (3) (1,3) (2) (2,3) (0,2) (0,1) {3,5,4,7} \\[...#.] (0,2,3,4) (2,3) (0,4) (0,1,2) (1,2,3,4) {7,5,12,7,2} \\[.###.#] (0,1,2,3,4) (0,3,4) (0,1,2,4,5) (1,2) {10,11,11,5,10,5} ; var lines = std.mem.tokenizeScalar(u8, input, '\n'); var i: usize = 0; while (lines.next()) |line| { defer i += 1; const machine = try Machine.init(allocator, line); defer machine.deinit(); std.debug.print("{f}\n", .{machine}); const initial_lights_state: std.bit_set.IntegerBitSet(Machine.MaxLightCount) = .initEmpty(); const button_presses = machine.pressButtonSequences(initial_lights_state); std.debug.print("machine {d} required {d} button presses", .{i, button_presses}); } } const Machine = struct { lights_goal: std.bit_set.IntegerBitSet(MaxLightCount), buttons: []std.bit_set.IntegerBitSet(MaxLightCount), allocator: std.mem.Allocator, const Self = @This(); pub const MaxLightCount = 16; pub fn init(allocator: std.mem.Allocator, line: []const u8) !Self { std.debug.assert(line[0] == '['); var lights_goal: std.bit_set.IntegerBitSet(MaxLightCount) = .initEmpty(); var buttons: std.ArrayList(std.bit_set.IntegerBitSet(MaxLightCount)) = .empty; defer buttons.deinit(allocator); var line_iter = std.mem.tokenizeScalar(u8, line, ' '); while (line_iter.next()) |part| { const p = part[1..part.len - 1]; if (part[0] == '[' and part[part.len - 1] == ']') { for (p, 0..) |c, i| { if (c == '#') lights_goal.set(i); } } else if (part[0] == '(' and part[part.len - 1] == ')') { var button: std.bit_set.IntegerBitSet(MaxLightCount) = .initEmpty(); var values_iter = std.mem.tokenizeScalar(u8, p, ','); while (values_iter.next()) |value| { button.set(try std.fmt.parseUnsigned(usize, value, 10)); } try buttons.append(allocator, button); } } const buttons_slice = try buttons.toOwnedSlice(allocator); errdefer allocator.free(buttons_slice); return .{ .lights_goal = lights_goal, .buttons = buttons_slice, .allocator = allocator, }; } pub fn deinit(self: Self) void { self.allocator.free(self.buttons); } pub fn format(self: Self, w: *std.Io.Writer) std.Io.Writer.Error!void { try w.print("[{b}]", .{self.lights_goal.mask}); try w.writeByte(' '); for (self.buttons) |button| { try w.print("({b})", .{button.mask}); } } pub fn pressButtonSequences( self: Self, initial_lights_state: std.bit_set.IntegerBitSet(MaxLightCount), buttons_pressed: *usize, ) usize { var button_presses: usize = 0; for (self.buttons) |button| { const result = initial_lights_state.xorWith(button); if (result.mask == self.lights_goal.mask) { return 1; } button_presses += self.pressButtonSequences(result); } return button_presses; } };