1+ '''
2+ TURING MACHINE
3+ '''
4+
5+ class TM :
6+
7+ #/ Attributes #
8+ States : list = []
9+ Alphabet : list = []
10+ Transitions : list = []
11+ Initial : str = ""
12+ Finals : list = []
13+
14+ #* Constructor #
15+ def __init__ (self , states : set = {}, alphabet : set = {}, transitions : list = [], initial : str = "" , finals : set = {}):
16+
17+ '''
18+ CONSTRUCTOR:
19+ NOTE: ALL THE PARAMETERS ARE OPTIONAL;
20+ NOTE: YOU CAN ADD ELEMENTS WITH RESPECTIVE FUNCTIONS:
21+ "TM" creates an instance of a Turing Machine.
22+ It receives:
23+
24+ 1. "states" (set of strings): In a set, add strings to represent
25+ each state of the Turing Machine. Example:
26+ {"q0", "q1", "q2", "qf", "qx", "dx"};
27+
28+ 2. "alphabet" (set of strings): In a set, add all the symbols that
29+ the Turing Machine reads. If you add two characters as a symbol,
30+ note that it will be considered as a single unique symbol.
31+ NOTE: Upper and lower case generate different symbols.
32+ Example:
33+ {"ea", "ra", "faszaa"} <- Three-symbol alphabet;
34+ {"A", "a", "B", "b"} <- Four-symbol alphabet;
35+ {"a", "b", "c", "d", "d", "d", "d"} <- Four-symbol alphabet;
36+
37+ 3. "transitions" (set of *transitionObject* (tuples)):
38+ *transitionObject* looks like this:
39+ ("q0", "a", "b", "R", "q1");
40+ Where:
41+ * "q0" is the current state of the transition;
42+ * "a" is the symbol that the Turing Machine reads on the current state;
43+ * "b" is the symbol that the Turing Machine writes on the current position;
44+ * "R" or "L" specifies the direction the Turing Machine head moves after the transition;
45+ * "q1" is the next state after the transition.
46+ Example of a transitions set:
47+ { ("q0", "a", "b", "R", "q1"), ("q0", "b", "c", "L", "q1"), ("q1", "a", "a", "R", "q1") };
48+ NOTE: FOR THE BLANK SYMBOL USE "*".
49+
50+ 4. "initial" (string): Represents the initial state of the Turing Machine.
51+ If it is not included in "states", it will be added to the set of states.
52+ Example: "q0";
53+
54+ 5. "finals" (set of strings): Set of final states of the Turing Machine.
55+ Example: {"q1", "q2", "qf"};
56+
57+ RETURNS AN INSTANCE OF THE TURING MACHINE;
58+ '''
59+
60+ # The values of the automata #
61+ self .States = states
62+ self .Alphabet = alphabet
63+ self .Transitions = transitions
64+ self .Initial = initial
65+ self .Finals = finals
66+
67+ #* Getter:
68+ def __getattribute__ (self , __name : str ):
69+ return super (TM , self ).__getattribute__ (__name )
70+
71+ #* Setters:
72+ #/ For Automata States:
73+ def addState (self , state : str ):
74+ self .States .append (state )
75+ def setStates (self , states : set ):
76+ self .States = list (states )
77+
78+ #/ For Automata Alphabet:
79+ def addSymbol (self , symbol : str ):
80+ self .Alphabet .append (symbol )
81+ def setAlphabet (self , alphabet : set ):
82+ self .Alphabet = list (alphabet )
83+
84+ #/ For Automata Transitions:
85+ def addTransition (self , transition : tuple ):
86+ self .Transitions .append (transition )
87+ def setTransitions (self , transitions : list ):
88+ self .Transitions = transitions
89+
90+ #/ For Automata Initial State:
91+ def setInitial (self , initial : str ):
92+ if not initial in self .States :
93+ self .States .append (initial )
94+ self .Initial = initial
95+ self .actual = initial
96+
97+ #/ For Automata Final States:
98+ def addFinal (self , final : str ):
99+ self .Finals .append (final )
100+ def setFinals (self , finals : set ):
101+ self .Finals = list (finals )
102+
103+
104+ #? Methods:
105+ def show (self ):
106+ '''Prints Turing Machine data'''
107+ print ()
108+ print ("═" * 50 )
109+ print ("\n TURING MACHINE\n " )
110+ print ("═" * 50 )
111+ print (f"\n States: { set (self .States )} " )
112+ print (f"Alphabet: { set (self .Alphabet )} " )
113+ print (f"Initial state: \" { self .Initial } \" " )
114+ print (f"Final states: { set (self .Finals )} " )
115+ for t in self .Transitions :
116+ t1 = t [1 ] if t [1 ] != "" else "λ"
117+ t2 = t [2 ] if t [2 ] != "" else "λ"
118+ print (f"* δ(\" { t [0 ]} \" , \" { t1 } \" ) = (\" { t [3 ]} \" , \" { t2 } \" , \" { t [4 ]} \" )" )
119+ print ()
120+ print ("═" * 50 )
121+
122+ def transite (self , symbol : str , printStep : bool = False ):
123+ '''
124+ Receives the current reading symbol;
125+ Based on the current state and the transitions,
126+ it changes the current state and performs the necessary actions.
127+ '''
128+
129+ # Check if the transition exists:
130+ validTransitions = []
131+ for transition in self .Transitions :
132+ if self .actual == transition [0 ] and symbol == transition [1 ]:
133+ validTransitions .append (transition )
134+
135+ # If the Turing Machine has no valid transitions or more than one valid transition
136+ if len (validTransitions ) != 1 :
137+ print (f" * Invalid transition in \" { self .actual } \" reading \" { symbol } \" !" )
138+ self .error = True
139+ return
140+
141+ # Perform the transition:
142+ else :
143+ if printStep :
144+ print (f" * \" { self .actual } \" reads \" { symbol } \" , writes \" { validTransitions [0 ][2 ]} \" , moves { validTransitions [0 ][3 ]} , goes to \" { validTransitions [0 ][4 ]} \" ;" )
145+
146+ self .actual = validTransitions [0 ][4 ]
147+ self .tape [self .head ] = validTransitions [0 ][2 ]
148+
149+ # Move the head and extend the tape if necessary:
150+ if validTransitions [0 ][3 ] == "R" :
151+ self .head += 1
152+ if self .head == len (self .tape ):
153+ self .tape .append ("*" )
154+ elif validTransitions [0 ][3 ] == "L" :
155+ self .head -= 1
156+ if self .head < 0 :
157+ self .tape .insert (0 , "*" )
158+
159+ def accepts (self , string : str , stepByStep : bool = False ):
160+ '''
161+ Receives a string to process;
162+ Returns True if the string is accepted;
163+ Returns False if the string is not accepted;
164+ '''
165+
166+ # Initialize the actual state as the initial state and the tape with the string:
167+ self .actual = self .Initial
168+ self .error = False
169+ self .tape = list (string )
170+ self .head = 0
171+
172+ # It shows the step-by-step path for the string:
173+ if stepByStep :
174+ print (f"\n For string \" { string } \" :\n " )
175+
176+ # Process each symbol on the tape:
177+ while self .actual not in self .Finals and not self .error :
178+ symbol = self .tape [self .head ]
179+ self .transite (symbol , stepByStep )
180+
181+ print ()
182+
183+ # Check if the string was accepted or not:
184+ if self .error :
185+ return False
186+
187+ if self .actual in self .Finals :
188+ return True
189+ else :
190+ return False
0 commit comments