103 lines
3.4 KiB
Zig
103 lines
3.4 KiB
Zig
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;
|
|
}
|
|
};
|
|
|