Files
evilnkode/src/evilkode.py
2025-08-19 09:47:39 -05:00

48 lines
1.4 KiB
Python

import math
from dataclasses import dataclass
from typing import Iterator
@dataclass
class Observation:
keypad: list[list[int]]
key_selection: list[int]
@property
def property_list(self) -> list[set[int]]:
return [set(self.keypad[idx]) for idx in self.key_selection]
@dataclass
class EvilOutput:
possible_nkodes: list[list[int]]
iterations: int
@property
def number_of_possible_nkode(self):
return math.prod([len(el) for el in self.possible_nkodes])
@dataclass
class Evilkode:
observations: Iterator[Observation]
passcode_len: int
number_of_keys: int
properties_per_key: int
max_tries_before_lockout: int = 5
possible_nkode = None
def initialize(self):
possible_values = set(range(self.number_of_keys * self.properties_per_key))
self.possible_nkode = [possible_values.copy() for _ in range(self.passcode_len)]
def run(self) -> EvilOutput:
self.initialize()
for idx, obs in enumerate(self.observations):
if math.prod([len(el) for el in self.possible_nkode]) <= self.max_tries_before_lockout:
return EvilOutput(possible_nkodes=[list(el) for el in self.possible_nkode], iterations=idx+1)
for jdx, props in enumerate(obs.property_list):
self.possible_nkode[jdx] = props.intersection(self.possible_nkode[jdx])
raise Exception("error in Evilkode, observations stopped yielding")