Feat: made output function optional and added the example detector.py

This commit is contained in:
David Gil de Gómez Pérez
2026-07-16 11:53:03 +03:00
parent 9fae546330
commit 79b4554da6
2 changed files with 56 additions and 3 deletions
+52
View File
@@ -0,0 +1,52 @@
from typing import TypedDict
from snanosm.mealy import Machine, TransitionInputEnum
class Context(TypedDict):
count: int
position: int
matches: int
def dinc(context: Context):
context["count"] += 1
def dset(context: Context):
context["position"] = context["count"]
context["count"] += 1
def dprn(context: Context):
context["count"] += 1
print(f"SUBSTRING FOUND AT POSITION: {context['position']}")
context["matches"] += 1
# Detects the sequence AB in the string, printing the position and returning the amount of matches
def detector(input_string: str) -> int:
initial_context: Context = {
"count": 0,
"position": 0,
"matches": 0,
}
m = Machine(initial_context)
m.add_state("Q0", True, False)
m.add_state("Q1", False, False)
m.add_transition("A", "Q0", "Q1", lambda context: dset(context))
m.add_transition(TransitionInputEnum.MATCH_REST, "Q0", "Q0", lambda context: dinc(context))
m.add_transition("B", "Q1", "Q0", lambda context: dprn(context))
m.add_transition(TransitionInputEnum.MATCH_REST, "Q1", "Q0", lambda context: dinc(context))
for c in input_string:
m.process_input(c)
return initial_context["matches"]
if __name__ == "__main__":
print("== 1 ==")
n = detector("AAAAAAABAAAAAB")
print(f"Matches: {n}")
print("== 2 ==")
n = detector("AAAA")
print(f"Matches: {n}")
print("== 3 ==")
n = detector("ABCCBBACAB")
print(f"Matches: {n}")
+3 -2
View File
@@ -32,7 +32,7 @@ class State:
class Transition(Generic[TransitionInput]): class Transition(Generic[TransitionInput]):
def __init__(self, transition_input: TransitionInput, origin_name: str, destination_name: str, def __init__(self, transition_input: TransitionInput, origin_name: str, destination_name: str,
output_function: Callable[[Optional[object]], None]) -> None: output_function: Optional[Callable[[Optional[object]], None]]) -> None:
self.__transition_input = transition_input self.__transition_input = transition_input
self.__origin_name = origin_name self.__origin_name = origin_name
self.__destination_name = destination_name self.__destination_name = destination_name
@@ -40,6 +40,7 @@ class Transition(Generic[TransitionInput]):
self.__output_function = output_function self.__output_function = output_function
def execute_output(self, context): def execute_output(self, context):
if self.__output_function is not None:
self.__output_function(context) self.__output_function(context)
def get_destination_name_hash(self) -> int: def get_destination_name_hash(self) -> int:
@@ -63,7 +64,7 @@ class Machine(Generic[Input]):
self.__context = initial_context self.__context = initial_context
def add_transition(self, transition_input: TransitionInput, origin_name: str, destination_name: str, def add_transition(self, transition_input: TransitionInput, origin_name: str, destination_name: str,
output_function: Callable[[Optional[object]], None]) -> None: output_function: Optional[Callable[[Optional[object]], None]]) -> None:
ho = hash(origin_name) ho = hash(origin_name)
if ho not in self.__states.keys(): if ho not in self.__states.keys():
raise ValueError(f"Origin state {origin_name} does not exist.") raise ValueError(f"Origin state {origin_name} does not exist.")