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