1+ '''
2+ DETERMINISTIC FINITE ACCEPTORS AUTOMATONS
3+ '''
4+ 5+ class DFA :
6+ 7+ #/ Attributes #
8+ States : set = {}
9+ Alphabet : set = {}
10+ Transitions : list = []
11+ Initial : str = ""
12+ Finals : set = {}
13+ 14+ #/ Variables #
15+ actual : str = ""
16+ error : bool = False
17+ 18+ 19+ #* Constructor #
20+ def __init__ (self , states : set = {}, alphabet : set = {}, transitions : list = [], initial : str = "" , finals : set = {}):
21+ 22+ '''
23+ CONSTRUCTOR:
24+ NOTE: ALL THE PARAMETERS ARE OPTIONAL;
25+ NOTE: YOU CAN ADD ELEMENTS WITH RESPECTIVE FUNCTIONS:
26+ "DFA" create an instance of a Deterministic Finite Acceptor.
27+ It recieves:
28+
29+ 1. "states" (set of strings): In a set, add a strings to represent
30+ each state of the automata; Example:
31+ {"q0", "q1", "q2", "qf", "qx", "dx"};
32+
33+ 2. "alphabet" (set of strings): In a set, add all the symbols that
34+ the automata reads. If you add to chars as a symbol.
35+ NOTE: If you add a "symbol" as a string of more than one char, it will
36+ take it as a unique letter;
37+ NOTE: Upper and Lower case generates different symbols;
38+ Example:
39+ {"ea", "ra", "faszaa"} <- Three symbols alphabet;
40+ {"A", "a", "B", "b"} <- Four symbols alphabet;
41+ {"a", "b", "c", "d", "d", "d", "d"} <- Four symbols alphabet;
42+
43+ 3. "transitions" (set of *transitionObject* (tuples)):
44+ *transitionObject* looks like this:
45+ ("q0", "a", "q1");
46+ Where:
47+ * "q0" is the actual state of the transition;
48+ * "a" is the symbol that will read on the actual state;
49+ * "q1" is the next state after the symbol reading;
50+ Example of transitions set:
51+ {} ("q0", "a", "q1"), ("q0", "b", "q1"), ("q1", "a", "q1")" };
52+
53+ 4. "initial" (string): Represents your initial state.
54+ If it is not included in "states", it will add on it;
55+ Example: "q0";
56+
57+ 5. "finals" (set of strings): Set of final states of the
58+ Automata; Example: {"q1, "q2", "qf"};
59+
60+ RETURNS AN INSTANCE OF THE AUTOMATA;
61+ '''
62+ 63+ # The values of the automata #
64+ self .States = states
65+ self .Alphabet = states
66+ self .Transitions = transitions
67+ self .Initial = initial
68+ self .Finals = finals
69+ self .actual = initial
70+ self .transitionsCount = 0
71+ 72+ #* Getter:
73+ def __getattribute__ (self , __name : str ):
74+ # print('__getattribute__ ', __name)
75+ return super (DFA , self ).__getattribute__ (__name )
76+ 77+ #* Setters:
78+ #/ For Automata States:
79+ def addState (self , state : str ):
80+ self .States .append (state )
81+ def setStates (self , states : set ):
82+ self .States = states
83+ 84+ #/ For Automata Alphabet:
85+ def addSymbol (self , symbol : str ):
86+ self .Alphabet .append (symbol )
87+ def setAlphabet (self , alphabet : set ):
88+ self .Alphabet = alphabet
89+ 90+ #/ For Automata Transitions:
91+ def addTransition (self , transition : tuple ):
92+ self .Transitions .append (transition )
93+ def setTransitions (self , transitions : list ):
94+ self .Transitions = transitions
95+ 96+ #/ For Automata Initial State:
97+ def setInitial (self , initial : str ):
98+ if not initial in self .States :
99+ self .States .append (initial )
100+ self .Initial = initial
101+ self .actual = initial
102+ 103+ #/ For Automata Final States:
104+ def addFinal (self , final : str ):
105+ self .Finals .append (final )
106+ def setFinals (self , finals : set ):
107+ self .Finals = finals
108+ 109+ 110+ #? Methods:
111+ def transite (self , symbol : str , printStep : bool = False ):
112+ '''
113+ Recieves an actual reading symbol;
114+ Based on the actual state and the transitions,
115+ It changes the actual state to move;
116+ '''
117+ 118+ #/ The transition works like this:
119+ #* If self.actual == [transition[0](actual state on the transition tuple)]
120+ #* and symbol == [transition[1](letter on the transition tuple)], then:
121+ #* self.actual = [transition[2](next state on the transition tuple)];
122+ validTransitions = []
123+ for transition in self .Transitions :
124+ if self .actual == transition [0 ] and symbol == transition [1 ]:
125+ validTransitions .append (transition )
126+ 127+ # If Automata has 0 or more than 1 transitions:
128+ if len (validTransitions ) != 1 :
129+ print (f" * Transición δ(\" { self .actual } \" , \" { symbol } \" ) inválida!" )
130+ self .error = True
131+ return
132+ # Else; it generates a transition:
133+ else :
134+ if printStep :
135+ print (f" * \" { self .actual } \" lee \" { symbol } \" => \" { validTransitions [0 ][2 ]} \" ;" )
136+ self .actual = validTransitions [0 ][2 ]
137+ 138+ def accepts (self , string : str , stepByStep : bool = False ):
139+ '''
140+ Recieves a string to read;
141+ Returns true if the string is accepted;
142+ Returns false if the string is not accepted;
143+ '''
144+ 145+ # Initialize the actual state as the initial:
146+ self .actual = self .Initial
147+ self .error = False
148+ 149+ # Reads letter per letter:
150+ for character in string :
151+ self .transite (character , stepByStep )
152+ 153+ # If the string was accepted or not:
154+ # Firstly checks if transitionsCount == word lenght,
155+ # If not, is because it has an invalid transition:
156+ if self .error :
157+ return False
158+ 159+ if self .actual in self .Finals :
160+ return True
161+ else :
162+ return False
0 commit comments