Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit 60b3a6f

Browse files
committed
Automata v.1.4.1
Fixed error: when automata empties the stack, and there is more transitions to do, it know update the automata state to [error], to avoid the poping of null values of the stack. It also has a two new implementations: safebox automatas simulator for example :3
1 parent 50958b6 commit 60b3a6f

File tree

3 files changed

+294
-3
lines changed

3 files changed

+294
-3
lines changed

‎pda.py‎

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -179,14 +179,14 @@ def transite(self, symbol: str, printStep: bool = False):
179179
for transition in self.Transitions:
180180
# print(self.stack[len(self.stack)-1])
181181
# print(f"if ({current} == {transition[0]}) and ({symbol} == {transition[1]} or {transition[1]} == \"\") and ({self.stack[len(self.stack)-1]} == {transition[2]}):")
182-
if (current == transition[0]) and (symbol == transition[1] or transition[1] == "") and (self.stack[len(self.stack)-1] == transition[2]):
182+
if (current == transition[0]) and (symbol == transition[1] or transition[1] == "") and (self.stack[len(self.stack)-1] == transition[2])and (notself.error):
183183
print(" * Transición a tomar:", transition)
184184
validTransitions.append(transition)
185185

186186
# If Automata has 0 transitions, it will go to the "limbo"; means error;
187187
# But only if it is more string to read:
188188
takesALambdaTransition = False
189-
if len(validTransitions) == 0:
189+
if len(validTransitions) == 0andlen(self.stack) >0:
190190
# If there is no more string:
191191
if symbol == "":
192192
# Checks if it arrives to a final state:
@@ -227,7 +227,11 @@ def transite(self, symbol: str, printStep: bool = False):
227227
newStates.append(transition[4])
228228

229229
# It pop the stack top symbol:
230-
self.stack.pop()
230+
if len(self.stack) > 0:
231+
self.stack.pop()
232+
else:
233+
self.error = True
234+
return
231235

232236
# It push down symbols on the stack:
233237
stacking = transition[3]

‎safebox-generator.py‎

Lines changed: 208 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,208 @@
1+
from dfa import DFA
2+
import os
3+
4+
def generateDFA(password: str):
5+
6+
#? DFA:
7+
#* Se espera que el autómata acepte:
8+
#* { wxv: w, v en {L, R}*, x es la contraseña };
9+
Automata = DFA()
10+
Automata.setAlphabet({"L", "R"})
11+
12+
#* Se comienza con el dibujo del autómata:
13+
# print(f"\nAutómata generado para \"{password}\":\n")
14+
15+
16+
#? ESTRUCTURA INICIAL ?#
17+
'''
18+
Se espera que el autómata acepte la contraseña de
19+
la caja fuerte independientemente de lo que venga
20+
antes de esta (v en {L, R}*); por ente, es necesario
21+
crear una estructura particular para el primer grupo
22+
de caracteres de la contraseña:
23+
24+
* Si la contraseña comienza con movimientos a la
25+
izquierda "L"; se "registra" este hecho.
26+
27+
* Si la contraseña comienza con movimientos a la
28+
derecha "R"; se "registra" este hecho.
29+
30+
Se toma este primer símbolo como la transición que
31+
el estado inicial tiene para avanzar a estados
32+
siguientes, y el complemento del símbolo (el otro),
33+
para generar un ciclo en el que no sale del estado
34+
inicial. Es decir, cuando se esté leyendo el inicio
35+
de la cadena, se espera que cuando lea el símbolo
36+
con el que inicia la contraseña, comience a avanzar
37+
suponiendo que ya se está tecleando la contraseña,
38+
en caso de que se lean otros símbolos, seguirá a la
39+
espera de que este primer símbolo llegue.
40+
41+
Esta primer estructura tiene "x" estados; en donde
42+
"x" representa la cantidad de movimientos del primer
43+
dígito de la contraseña (cantidad de símbolos de la
44+
estructura inicial, antes de comenzar con otra letra).
45+
46+
Los "x" estados de esta estructura regresan al estado
47+
inicial cuando encuentran un símbolo que no es igual al
48+
inicial de la contraseña, y avanzan hasta que el último
49+
estado de esta estructura (el número "x"), debe comenzar
50+
a leer otras letras, en ese caso, se ciclará a sí mismo
51+
mientras siga leyendo el símbolo inicial; esto porque se
52+
espera que si antes de la contraseña vinieron "mil" veces
53+
ese símbolo, los registre todos de manera igualmente válida
54+
que si sólo vinieron "x".
55+
'''
56+
#? Estado incial:
57+
Automata.setInitial("q0")
58+
#? Símbolo inicial:
59+
initialSymbol = password[0]
60+
#? Primeras transiciones:
61+
if initialSymbol == "L":
62+
Automata.addTransition(("q0", "R", "q0"))
63+
# print(f"(\'q0\', \'R\', \'q0\')")
64+
Automata.addTransition(("q0", "L", "q1"))
65+
# print(f"(\'q0\', \'L\', \'q1\')")
66+
notInitialSymbol = "R"
67+
else:
68+
Automata.addTransition(("q0", "L", "q0"))
69+
# print(f"(\'q0\', \'L\', \'q0\')")
70+
Automata.addTransition(("q0", "R", "q1"))
71+
# print(f"(\'q0\', \'R\', \'q1\')")
72+
notInitialSymbol = "L"
73+
74+
#? Primeros "x" estados:
75+
index = 1
76+
77+
#? Le las "x" repeticiones del primer símbolo;
78+
#? y crea estados para cada uno; bajo las reglas
79+
#? de la primer estructura:
80+
while initialSymbol == password[index]:
81+
82+
#/ Nuevo estado x:
83+
Automata.addState(str(f"q{index}"))
84+
85+
#/ Transición de este estado hacia le siguiente;
86+
#/ Avanzando porque encontró el símbolo inicial:
87+
Automata.addTransition((str(f"q{index}"), initialSymbol, str(f"q{index+1}")))
88+
# print(f"(\'q{index}\', \'{initialSymbol}\', \'q{index+1}\')")
89+
90+
#/ Transición en el que regresa al estado inicial:
91+
#/ Esto porque encontró un símbolo diferente al inicial:
92+
Automata.addTransition((str(f"q{index}"), notInitialSymbol, "q0"))
93+
# print(f"(\'q{index}\', \'{notInitialSymbol}\', \'q0\')")
94+
95+
index += 1
96+
97+
#? Crea el ciclo descrito para el último estado "x":
98+
#/ Transición para sí mismo:
99+
Automata.addState(str(f"q{index+1}"))
100+
Automata.addTransition((str(f"q{index}"), initialSymbol, str(f"q{index}")))
101+
# print(f"(\'q{index}\', \'{initialSymbol}\', \'q{index}\')")
102+
103+
#/ Transición para avanzar con el siguiente tipo de símbolo:
104+
Automata.addTransition((str(f"q{index}"), notInitialSymbol, str(f"q{index+1}")))
105+
# print(f"(\'q{index}\', \'{notInitialSymbol}\', \'q{index+1}\')")
106+
107+
108+
#? ESTRUCTURA GENERAL:
109+
'''
110+
Esta estructura sirve para el resto de dígitos de la contraseña;
111+
Para cada símbolo siguiente seguirá las reglas:
112+
113+
* Se crea un estado para cada siguiente movimiento (caracter):
114+
- Crea una transición para avanzar al siguiente estado,
115+
según el símbolo actual de la contraseña.
116+
- Cuando estás leyendo el símbolo inicial; la otra transición
117+
va a "q0"; es decir, vuelve a empezar porque al estar leyendo
118+
algo en la contraseña fue incorrecto.
119+
- Cuando estás leyendo el símbolo no-inicial, la otra transición
120+
va a "q1", porque supone que te equivocaste, pero que este error
121+
podría significar que es el primer símbolo correcto de la contraseña.
122+
'''
123+
print()
124+
#* Si toca cambiar de dirección al siguiente movimiento;
125+
#* Esto porque el siguiente caracter es diferente al actual:
126+
if index != len(password)-1 and password[index] != password[index+1]:
127+
change = True
128+
else:
129+
change = False
130+
index += 1
131+
132+
while index < len(password):
133+
134+
#* Se crea el estado para el símbolo actual:
135+
Automata.addState(str(f"q{index}"))
136+
137+
#* Se crea una transición de avance:
138+
Automata.addTransition((str(f"q{index}"), password[index], str(f"q{index+1}")))
139+
# print((str(f"q{index}"), password[index], str(f"q{index+1}")))
140+
141+
#? Si se está leyendo el caracter inicial:
142+
if password[index-1] == initialSymbol:
143+
#/ Transición de retroceso:
144+
if not change:
145+
Automata.addTransition((str(f"q{index}"), notInitialSymbol, "q0"))
146+
# print((str(f"q{index}"), notInitialSymbol, "q0"))
147+
else:
148+
Automata.addTransition((str(f"q{index}"), initialSymbol, "q1"))
149+
# print((str(f"q{index}"), initialSymbol, "q1"))
150+
151+
#? Si se está leyendo el caracter no-inicial:
152+
else:
153+
#/ Transición de retroceso:
154+
if not change:
155+
Automata.addTransition((str(f"q{index}"), initialSymbol, "q1"))
156+
# print((str(f"q{index}"), initialSymbol, "q1"))
157+
else:
158+
Automata.addTransition((str(f"q{index}"), notInitialSymbol, "q0"))
159+
# print((str(f"q{index}"), notInitialSymbol, "q0"))
160+
161+
#* Si toca cambiar de dirección al siguiente movimiento;
162+
#* Esto porque el siguiente caracter es diferente al actual:
163+
if index != len(password)-1 and password[index] != password[index+1]:
164+
change = True
165+
else:
166+
change = False
167+
index += 1
168+
169+
print()
170+
#? ESTRUCTURA FINAL:
171+
'''
172+
Esta estructura consiste en el estado final, al que se llegó
173+
SÓLO si la contraseña fue correcta; en ese caso, se ciclará
174+
a sí mismo independientemente de lo que reciba después; ya
175+
que la caja ya está abierta.
176+
'''
177+
Automata.addState(str(f"q{index}"))
178+
Automata.addTransition((str(f"q{index}"), "L", str(f"q{index}")))
179+
# print(f"(\'q{index}\', \'L\', \'q{index}\')")
180+
Automata.addTransition((str(f"q{index}"), "R", str(f"q{index}")))
181+
# print(f"(\'q{index}\', \'R\', \'q{index}\')")
182+
Automata.setFinals({str(f"q{index}")})
183+
184+
185+
#/ Executes the Automata:
186+
'''
187+
while True:
188+
word = input("Cadena: ")
189+
if Automata.accepts(word, stepByStep=False):
190+
# print(f"La cadena \"{word}\" SÍ es aceptada!")
191+
else:
192+
# print(f"La cadena \"{word}\" NO es aceptada!")
193+
'''
194+
195+
Automata.show()
196+
return Automata
197+
198+
199+
#? Punto de ejecución:
200+
if __name__ == "__main__":
201+
202+
while True:
203+
print("\n")
204+
os.system("cls")
205+
password = input("Contraseña: ")
206+
generateDFA(password)
207+
print("\n")
208+
os.system("pause")

‎safebox-validator.py‎

Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
from pda import PDA
2+
import os
3+
4+
def validatePassword(password: str):
5+
6+
'''
7+
Recibe una contraseña y valida si es
8+
correcta para el contexto de la caja
9+
fuerte, utilizando una autómata de
10+
pila que valida el siguiente formato:
11+
12+
L = { (L^n)(R^m)(L^o)(R^p):
13+
(4 <= n + m + o + p <= 40) };
14+
15+
Es decir; contraseñas con grupos de
16+
L's, luego R's, luego L's, luego R's,
17+
en donde cada grupo tenga por lo menos
18+
un caracter, y en conjunto no sumen más
19+
de 4 caracteres como longitud.
20+
21+
Esta propuesta no está implementada en
22+
la aplicación, por lo que es agena a esta,
23+
se propone como propuesta interesante
24+
tener constraseñas con el lenguaje:
25+
L' = { L = { (L^n)(R^m)(L^o)(R^p):
26+
(1 <= n, m, o, p <= 10 };
27+
28+
Es decir; contraseñas de cuatro grupos
29+
alternados (iguales a la propuesta anterior,
30+
pero en los cuales cada uno sólo admite un
31+
máximo de 10 símbolos).
32+
33+
También se propone a futuro extender el
34+
lenguaje que acepte contraseñas que comienzen
35+
con grupos de R's, no de sólo L's.
36+
37+
Retorna verdadero o falso según acepte o no
38+
acepte la contraseña de parámetro.
39+
'''
40+
41+
#? Se crea instancia del autómata (de pila):
42+
Estados = {"q0", "q1", "q2", "q3", "q4", "q5"}
43+
Alfabeto = {"L", "R"}
44+
Inicial = "q0"
45+
Finales = {"q4"}
46+
Alfapila = {"1", "Z"}
47+
Pila = ["Z"]
48+
Transiciones = [
49+
("q0", "L", "Z", "1111111111111111111111111111111111111111Z", "q1"),
50+
("q1", "L", "1", "", "q1"),
51+
("q1", "R", "1", "", "q2"),
52+
("q2", "R", "1", "", "q2"),
53+
("q2", "L", "1", "", "q3"),
54+
("q3", "L", "1", "", "q3"),
55+
("q3", "L", "1", "", "q3"),
56+
("q3", "R", "1", "", "q4"),
57+
("q4", "R", "1", "", "q4"),
58+
("q4", "", "Z", "Z", "q5")
59+
]
60+
Automata = PDA(Estados, Alfabeto, Transiciones, Inicial, Finales, Alfapila, Pila)
61+
Automata.show()
62+
print()
63+
return True if Automata.accepts(password, stepByStep=False) else False
64+
65+
66+
#* Punto de ejecución:
67+
if __name__ == "__main__":
68+
while True:
69+
os.system("cls")
70+
print()
71+
password = input("Contraseña: ")
72+
if validatePassword(password):
73+
print(f"\nLa contraseña \"{password}\" SÍ es válida")
74+
else:
75+
print(f"\nLa contraseña \"{password}\" NO es válida")
76+
print()
77+
print("═"*40)
78+
print("\n")
79+
os.system("pause")

0 commit comments

Comments
(0)

AltStyle によって変換されたページ (->オリジナル) /