AoC2025/src/days/day10.zig
2025-12-10 16:33:04 +00:00

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;
}
};