





































Prepara tus exámenes y mejora tus resultados gracias a la gran cantidad de recursos disponibles en Docsity
Gana puntos ayudando a otros estudiantes o consíguelos activando un Plan Premium
Prepara tus exámenes
Prepara tus exámenes y mejora tus resultados gracias a la gran cantidad de recursos disponibles en Docsity
Prepara tus exámenes con los documentos que comparten otros estudiantes como tú en Docsity
Encuentra los documentos específicos para los exámenes de tu universidad
Estudia con lecciones y exámenes resueltos basados en los programas académicos de las mejores universidades
Responde a preguntas de exámenes reales y pon a prueba tu preparación
Consigue puntos base para descargar
Gana puntos ayudando a otros estudiantes o consíguelos activando un Plan Premium
Comunidad
Pide ayuda a la comunidad y resuelve tus dudas de estudio
Ebooks gratuitos
Descarga nuestras guías gratuitas sobre técnicas de estudio, métodos para controlar la ansiedad y consejos para la tesis preparadas por los tutores de Docsity
Este documento es una guía de ejercicios de programación en Python enfocada en estructuras de datos básicas. Contiene 60 problemas organizados en tres categorías: arreglos (matrices/vectores), cadenas de texto y estructuras avanzadas (grafos, árboles, tablas hash). Cada ejercicio presenta un enunciado claro seguido de su solución en Python, con explicaciones sobre la lógica implementada y análisis de complejidad algorítmica (O(n), O(n log n), etc.). Incluye problemas como búsqueda de patrones en matrices, ordenamiento de estructuras complejas, validación de expresiones, algoritmos de compresión (Huffman), recorridos en grafos (Dijkstra, Floyd-Warshall) y manipulación de estructuras avanzadas (árboles B, tries). Es ideal para estudiantes que buscan reforzar conceptos teóricos mediante ejercicios aplicados en Python. Su organización progresiva (de básico a avanzado) lo convierten en un recurso valioso para el aprendizaje práctico de programación.
Tipo: Exámenes
1 / 45
Esta página no es visible en la vista previa
¡No te pierdas las partes importantes!






































Ejercicios de Arreglos, Cadenas y Estructuras (continuaci´on)
Ejercicios de Arreglos, Cadenas y Estructuras (continuaci´on)
48 if coincidencia : 49 resultados. append (( 50 i , j , # Inicio ( fila , columna ) 51 ki , kj # Fin ( fila , columna ) 52 ) ) 53 54 return resultados 55 56 # V e r s i n optimizada para b s q u e d a horizontal / vertical 57 def buscar_patron_optimizado ( matriz , patron ) : 58 from collections import defaultdict 59 60 if not matriz or not patron : 61 return [] 62 63 filas = len ( matriz ) 64 columnas = len ( matriz [0]) if filas > 0 else 0 65 len_patron = len ( patron ) 66 resultados = [] 67 68 # Preprocesamiento : Mapa de caracteres a posiciones 69 mapa_caracteres = defaultdict ( list ) 70 for i in range ( filas ) : 71 for j in range ( columnas ) : 72 mapa_caracteres [ matriz [ i ][ j ]]. append (( i , j ) ) 73 74 # Solo buscar en posiciones donde empieza el primer caracter 75 for i , j in mapa_caracteres. get ( patron [0] , []) : 76 # Horizontal derecha 77 if j + len_patron <= columnas : 78 if all ( matriz [ i ][ j + k ] == patron [ k ] for k in range ( len_patron ) ) : 79 resultados. append (( i , j , i , j + len_patron -1) ) 80 81 # Vertical abajo 82 if i + len_patron <= filas : 83 if all ( matriz [ i + k ][ j ] == patron [ k ] for k in range ( len_patron ) ) : 84 resultados. append (( i , j , i + len_patron -1 , j ) ) 85 86 # Diagonal derecha - abajo 87 if i + len_patron <= filas and j + len_patron <= columnas : 88 if all ( matriz [ i + k ][ j + k ] == patron [ k ] for k in range ( len_patron ) ) : 89 resultados. append (( i , j , i + len_patron -1 , j + len_patron -1) ) 90 91 return resultados 92 93 # Casos de prueba 94 matriz_ejemplo = [ 95 [ ’A ’ , ’B ’ , ’C ’ , ’D ’] , 96 [ ’E ’ , ’F ’ , ’G ’ , ’H ’] , 97 [ ’I ’ , ’J ’ , ’K ’ , ’L ’] , 98 [ ’M ’ , ’N ’ , ’O ’ , ’P ’] 99 ] 100 101 patrones = [ 102 " ABC " , # Horizontal 103 " EJQ " , # No existe 104 " AFKP " , # Diagonal 105 " HLP " , # No existe 106 " DHL " , # Diagonal inversa 107 " MNOP " , # Horizontal inferior 108 " ABCDHLP " # Demasiado largo 109 ] 110 111 # Probar todos los casos 112 for patron in patrones : 113 print ( f " Buscando ’{ patron } ’: " ) 114 print ( " V e r s i n completa : " , buscar_patron ( matriz_ejemplo , patron ) ) 115 print ( " V e r s i n optimizada : " , buscar_patron_optimizado ( matriz_ejemplo , patron ) ) 116 print ( " -" * 60)
Explicaci´on:
1 class Persona : 2 def init ( self , nombre , edad , salario ) : 3 self. nombre = nombre 4 self. edad = edad 5 self. salario = salario 6 7 def repr ( self ) : 8 return f " Persona ( nombre = ’{ self. nombre } ’ , edad ={ self. edad } , salario ={ self. salario }) " 9 10 def ordenar_personas ( personas ) : 11 """ 12 Ordena una lista de personas por edad ascendente y salario descendente. 13 14 P a r m e t r o s : 15 personas : Lista de objetos Persona 16 17 Retorna : 18 Lista ordenada s e g n los criterios especificados 19 """ 20 if not personas : 21 return [] 22 23 # I m p l e m e n t a c i n con sorted y key personalizada 24 return sorted ( personas , key = lambda p : ( p. edad , -p. salario ) ) 25 26 # V e r s i n con algoritmo de ordenamiento manual ( Merge Sort ) 27 def ordenar_personas_manual ( personas ) : 28 if len ( personas ) <= 1: 29 return personas. copy () 30 31 medio = len ( personas ) // 2 32 izquierda = ordenar_personas_manual ( personas [: medio ]) 33 derecha = ordenar_personas_manual ( personas [ medio :]) 34 35 resultado = [] 36 i = j = 0 37 38 while i < len ( izquierda ) and j < len ( derecha ) : 39 # Comparar por edad ascendente 40 if izquierda [ i ]. edad < derecha [ j ]. edad : 41 resultado. append ( izquierda [ i ]) 42 i += 1 43 elif izquierda [ i ]. edad > derecha [ j ]. edad : 44 resultado. append ( derecha [ j ]) 45 j += 1 46 else :
12 Conjunto de subcadenas que cumplen los criterios 13 """ 14 if not S or K <= 0 or V < 0 or K > len ( S ) : 15 return set () 16 17 vocales = { ’a ’ , ’e ’ , ’i ’ , ’o ’ , ’u ’} 18 resultado = set () 19 n = len ( S ) 20 21 # Precomputar conteo de vocales en ventana deslizante 22 conteo_vocales = 0 23 for i in range ( K ) : 24 if S [ i ]. lower () in vocales : 25 conteo_vocales += 1 26 27 if conteo_vocales == V : 28 resultado. add ( S [: K ]. lower () ) 29 30 # Ventana deslizante para eficiencia O ( n ) 31 for i in range (K , n ) : 32 # Eliminar el caracter que sale de la ventana 33 if S [i - K ]. lower () in vocales : 34 conteo_vocales -= 1 35 36 # Agregar el nuevo caracter 37 if S [ i ]. lower () in vocales : 38 conteo_vocales += 1 39 40 # Verificar c o n d i c i n 41 if conteo_vocales == V : 42 resultado. add ( S [i - K +1: i +1]. lower () ) 43 44 return resultado 45 46 # V e r s i n alternativa para c o m p a r a c i n ( menos eficiente ) 47 def subcadenas_naive (S , K , V ) : 48 vocales = { ’a ’ , ’e ’ , ’i ’ , ’o ’ , ’u ’} 49 return { S [ i : i + K ]. lower () for i in range ( len ( S ) -K +1) 50 if sum (1 for c in S [ i : i + K ] if c. lower () in vocales ) == V } 51 52 # Casos de prueba 53 test_cases = [ 54 ( " ProgramandoEnPython " , 5 , 2) , # Subcadenas con 2 vocales en 5 caracteres 55 ( " AEIOUaeiou " , 3 , 3) , # Todas vocales 56 ( " XYZxyz " , 2 , 0) , # Sin vocales 57 ( " a " , 1 , 1) , # Caso m n i m o 58 ( " PythonEsGenial " , 10 , 4) , # Caso realista 59 ( " " , 3 , 2) , # Cadena v a c a 60 ] 61 62 for S , K , V in test_cases : 63 print ( f " Cadena : ’{ S } ’ , K ={ K } , V ={ V } " ) 64 print ( f " Subcadenas ( ventana deslizante ) : { subcadenas_con_vocales (S , K , V ) } " ) 65 print ( f " Subcadenas ( naive ) : { subcadenas_naive (S , K , V ) } " ) 66 print ( " -" * 60)
Explicaci´on:
1 def matriz_sumas_acumuladas ( matriz ) : 2 """ 3 Calcula la matriz de sumas acumuladas donde cada elemento (i , j ) contiene 4 la suma de todos los elementos desde (0 ,0) hasta (i , j ) en la matriz original. 5 6 P a r m e t r o s : 7 matriz : Lista de listas de n m e r o s ( matriz cuadrada ) 8 9 Retorna : 10 Nueva matriz con las sumas acumuladas 11 """ 12 if not matriz : 13 return [] 14 15 n = len ( matriz ) 16 m = len ( matriz [0]) if n > 0 else 0 17 18 # Crear matriz de resultados inicializada en 0 19 dp = [[0] * m for _ in range ( n ) ] 20 dp [0][0] = matriz [0][0] 21 22 # Llenar primera fila 23 for j in range (1 , m ) : 24 dp [0][ j ] = dp [0][ j -1] + matriz [0][ j ] 25 26 # Llenar primera columna 27 for i in range (1 , n ) : 28 dp [ i ][0] = dp [i -1][0] + matriz [ i ][0] 29 30 # Llenar el resto de la matriz 31 for i in range (1 , n ) : 32 for j in range (1 , m ) : 33 dp [ i ][ j ] = matriz [ i ][ j ] + dp [i -1][ j ] + dp [ i ][ j -1] - dp [i -1][ j -1] 34 35 return dp 36 37 # V e r s i n alternativa usando numpy ( para matrices grandes ) 38 def ma tr iz _s um as a cu mu la da s nu mp y ( matriz ) : 39 import numpy as np 40 arr = np. array ( matriz ) 41 return np. cumsum ( np. cumsum ( arr , axis =0) , axis =1). tolist () 42 43 # Casos de prueba 44 matrices = [ 45 [[1 , 2] , [3 , 4]] , # Matriz 2 x 46 [[1 , 2 , 3] , [4 , 5 , 6] , [7 , 8 , 9]] , # Matriz 3 x 47 [[5]] , # Matriz 1 x 48 [] , # Matriz v a c a 49 [[1 , 0 , 0] , [0 , 1 , 0] , [0 , 0 , 1]] # Matriz identidad 50 ] 51 52 for mat in matrices : 53 print ( f " Matriz original : " ) 54 for fila in mat : 55 print ( fila ) 56 57 print ( " \ nSumas acumuladas : " ) 58 resultado = matriz_sumas_acumuladas ( mat )
43 44 # Casos de prueba 45 libros1 = [ 46 Libro ( " Cien a o s de soledad " , " Gabriel G a r c a M r q u e z " , 1967) , 47 Libro ( " El Principito " , " Antoine de Saint - E x u p r y " , 1943) , 48 Libro ( " 1984 " , " George Orwell " , 1949) 49 ] 50 51 libros2 = [ 52 Libro ( " Cien a o s de soledad " , " Gabriel G a r c a M r q u e z " , 2001) , # Mismo t t u l o / autor , a o diferente 53 Libro ( " Ficciones " , " Jorge Luis Borges " , 1944) , 54 Libro ( " 1984 " , " George Orwell " , 1984) # E d i c i n especial con a o actualizado 55 ] 56 57 print ( " === Lista 1 === " ) 58 for libro in libros1 : 59 print ( libro ) 60 61 print ( " \ n === Lista 2 === " ) 62 for libro in libros2 : 63 print ( libro ) 64 65 print ( " \ n === F u s i n ( diccionario ) === " ) 66 for libro in fusionar_libros ( libros1 , libros2 ) : 67 print ( libro ) 68 69 print ( " \ n === F u s i n ( conjuntos ) === " ) 70 for libro in fusionar_libros_con_sets ( libros1 , libros2 ) : 71 print ( libro )
Explicaci´on:
1 def rotar_cadena_segura (S , R ) : 2 """ 3 Rota una cadena R posiciones a la derecha ( R positivo ) o izquierda ( R negativo ) 4 con v a l i d a c i n de rangos. 5 6 P a r m e t r o s : 7 S : Cadena de texto a rotar 8 R : N m e r o de posiciones a rotar ( positivo = derecha , negativo = izquierda ) 9 10 Retorna : 11 Cadena rotada o ValueError si R e s t fuera de rango
12 13 Excepciones : 14 ValueError : Si | R | > len ( S ) 15 """ 16 if not isinstance (S , str ) : 17 raise TypeError ( " La entrada debe ser una cadena de texto " ) 18 19 if not S : # Cadena v a c a 20 return S 21 22 n = len ( S ) 23 R = int ( R ) # Asegurar que es entero 24 25 # Validar rango permitido 26 if abs ( R ) > n : 27 raise ValueError ( f " R ({ R }) debe estar en el rango [ -{ n } , { n }] " ) 28 29 # Normalizar la r o t a c i n ( equivalente para rotaciones mayores ) 30 R = R % n # Esto maneja tanto R positivo como negativo 31 32 # Rotar la cadena 33 if R > 0: # R o t a c i n a la derecha 34 return S [ - R :] + S [: - R ] 35 else : # R o t a c i n a la izquierda ( R negativo ) 36 return S [ abs ( R ) :] + S [: abs ( R ) ] 37 38 # V e r s i n alternativa con desplazamiento circular 39 def rotar_cadena_circular (S , R ) : 40 n = len ( S ) 41 if n == 0: 42 return S 43 R = R % n 44 return S [n - R :] + S [: n - R ] 45 46 # Casos de prueba 47 test_cases = [ 48 ( " Python " , 2) , # R o t a c i n derecha 49 ( " Python " , -1) , # R o t a c i n izquierda 50 ( " Hello " , 5) , # R o t a c i n completa ( equivalente a 0) 51 ( " World " , 8) , # R o t a c i n mayor que longitud 52 ( " " , 3) , # Cadena v a c a 53 ( " OpenAI " , -3) , # R o t a c i n izquierda 54 ( " R o t a c i n " , 0) , # Sin r o t a c i n 55 ( " V a l i d a c i n " , 4) , # R o t a c i n derecha con acentos 56 ] 57 58 for S , R in test_cases : 59 print ( f " Cadena original : ’{ S } ’ " ) 60 try : 61 print ( f " R o t a c i n { R }: ’{ rotar_cadena_segura (S , R ) } ’ " ) 62 print ( f " Circular : ’{ rotar_cadena_circular (S , R ) } ’ " ) 63 except ValueError as e : 64 print ( f " Error : { e } " ) 65 except TypeError as e : 66 print ( f " Error : { e } " ) 67 print ( " -" * 50)
Explicaci´on:
55 if j > 0: vecinos. append ( matriz [ i ][ j -1]) # Izquierda 56 if j < columnas -1: vecinos. append ( matriz [ i ][ j +1]) # Derecha 57 58 if all ( valor > vecino for vecino in vecinos ) : 59 picos. append ((( i , j ) , valor ) ) 60 61 return picos 62 63 # Casos de prueba 64 matrices = [ 65 # Matriz con pico central 66 [[1 , 2 , 3] , 67 [4 , 5 , 2] , 68 [3 , 2 , 1]] , 69 70 # M l t i p l e s picos 71 [[1 , 3 , 1] , 72 [2 , 5 , 2] , 73 [1 , 4 , 1]] , 74 75 # Matriz v a c a 76 [] , 77 78 # Todos elementos iguales ( sin picos ) 79 [[2 , 2 , 2] , 80 [2 , 2 , 2] , 81 [2 , 2 , 2]] , 82 83 # Picos en bordes 84 [[9 , 2 , 3] , 85 [1 , 2 , 4] , 86 [5 , 6 , 7]] , 87 88 # Matriz grande 89 [[ i * j for j in range (100) ] for i in range (100) ] 90 ] 91 92 for idx , mat in enumerate ( matrices [:5]) : # Probar solo las primeras 5 para no saturar 93 print ( f " \ nMatriz { idx + 1}: " ) 94 for fila in mat : 95 print ( fila ) 96 97 print ( " \ nPicos encontrados ( e s t n d a r ) : " ) 98 picos = encontrar_picos ( mat ) 99 for pos , val in picos : 100 print ( f " P o s i c i n { pos }: { val } " ) 101 102 print ( " \ nPicos encontrados ( optimizado ) : " ) 103 picos_opt = encontrar picos_opt imizado ( mat ) 104 for pos , val in picos_opt : 105 print ( f " P o s i c i n { pos }: { val } " ) 106 107 print ( " = " * 40) 108 109 # Probar matriz grande solo con v e r s i n optimizada 110 if len ( matrices ) > 5: 111 print ( " \ nProbando matriz grande (100 x100 ) ... " ) 112 picos_grandes = encontrar picos_optimizado ( matrices [5]) 113 print ( f " Se encontraron { len ( picos_grandes ) } picos en matriz grande " )
Explicaci´on:
1 class Mensaje : 2 def init ( self , emisor , receptor , texto ) : 3 self. emisor = emisor 4 self. receptor = receptor 5 self. texto = texto 6 7 def repr ( self ) : 8 return f " Mensaje ( emisor = ’{ self. emisor } ’ , receptor = ’{ self. receptor } ’ , texto = ’{ self. texto } ’) " 9 10 def codificar_mensajes ( mensajes ) : 11 """ 12 Codifica una lista de mensajes invirtiendo el orden de las vocales en el texto , 13 manteniendo el resto de caracteres igual. 14 15 P a r m e t r o s : 16 mensajes : Lista de objetos Mensaje 17 18 Retorna : 19 Lista de mensajes codificados 20 """ 21 def invertir_vocales ( texto ) : 22 vocales = { ’a ’ , ’e ’ , ’i ’ , ’o ’ , ’u ’ , ’A ’ , ’E ’ , ’I ’ , ’O ’ , ’U ’} 23 # Encontrar todas las vocales y sus posiciones 24 chars = list ( texto ) 25 indices_vocales = [ i for i , c in enumerate ( chars ) if c in vocales ] 26 vocales_encontradas = [ chars [ i ] for i in indices_vocales ] 27 28 # Invertir el orden de las vocales 29 for i , idx in enumerate ( indices_vocales ) : 30 chars [ idx ] = vocales_encontradas [ -( i +1) ] 31 32 return ’ ’. join ( chars ) 33 34 # Crear copia de los mensajes para no modificar los originales 35 mensajes_codificados = [] 36 for msg in mensajes : 37 texto_codificado = invertir_vocales ( msg. texto ) 38 mensaje_codificado = Mensaje ( msg. emisor , msg. receptor , texto_codificado ) 39 mensajes_codificados. append ( mensaje_codificado ) 40 41 return mensajes_codificados 42 43 # V e r s i n alternativa usando stack 44 def codificar_mensajes_stack ( mensajes ) : 45 vocales = { ’a ’ , ’e ’ , ’i ’ , ’o ’ , ’u ’ , ’A ’ , ’E ’ , ’I ’ , ’O ’ , ’U ’} 46 mensajes_cod = [] 47 48 for msg in mensajes : 49 # Extraer vocales en orden 50 vocales_texto = [ c for c in msg. texto if c in vocales ] 51 # Reemplazar en orden inverso 52 texto_cod = []
9 Retorna : 10 Lista ordenada de elementos comunes 11 """ 12 if not arreglos : 13 return [] 14 15 # Usar el arreglo m s p e q u e o como base para eficiencia 16 arreglo_base = min ( arreglos , key = len ) 17 comunes = set ( arreglo_base ) 18 19 for arr in arreglos : 20 if arr is not arreglo_base : 21 # Actualizar i n t e r s e c c i n con el arreglo actual 22 comunes. intersection_update ( arr ) 23 if not comunes : # O p t i m i z a c i n : salir si no hay comunes 24 break 25 26 return sorted ( comunes ) 27 28 # V e r s i n alternativa para arreglos muy grandes ( usando iteradores ) 29 def interseccion_grande ( arreglos ) : 30 from collections import defaultdict 31 32 if not arreglos : 33 return [] 34 35 contador = defaultdict ( int ) 36 for arr in arreglos : 37 for num in set ( arr ) : # Evitar contar duplicados en un mismo arreglo 38 contador [ num ] += 1 39 40 k = len ( arreglos ) 41 return sorted ( num for num , count in contador. items () if count == k ) 42 43 # Casos de prueba 44 test_cases = [ 45 [[1 , 2 , 3 , 4 , 5] , [2 , 4 , 6 , 8] , [0 , 2 , 4 , 10]] , # I n t e r s e c c i n [2 , 4] 46 [[1 , 2 , 3] , [4 , 5 , 6] , [7 , 8 , 9]] , # Sin i n t e r s e c c i n 47 [[1 , 1 , 2 , 2 , 3] , [1 , 2 , 2 , 3] , [1 , 2 , 3 , 3]] , # Con duplicados 48 [[] , [1 , 2 , 3]] , # Con arreglo v a c o 49 [[1 , 2 , 3]] , # Un solo arreglo 50 [] # Lista v a c a 51 ] 52 53 for i , caso in enumerate ( test_cases ) : 54 print ( f " \ nCaso { i +1}: " ) 55 for j , arr in enumerate ( caso ) : 56 print ( f " Arreglo { j +1}: { arr } " ) 57 58 print ( " \ n I n t e r s e c c i n e s t n d a r : " , interseccion_arreglos ( caso ) ) 59 print ( " I n t e r s e c c i n grande : " , interseccion_grande ( caso ) ) 60 print ( " = " * 60)
Explicaci´on:
1 import re 2 from typing import List 3 4 class Usuario : 5 def init ( self , nombre : str , c o n t r a s e a : str ) : 6 self. nombre = nombre 7 self. c o n t r a s e a = c o n t r a s e a 8 9 def repr ( self ) : 10 return f " Usuario ( nombre = ’{ self. nombre } ’ , c o n t r a s e a = ’{ ’* ’* len ( self. c o n t r a s e a ) } ’) " 11 12 def v a l i d a r _ c o n t r a s e a s ( usuarios : List [ Usuario ]) -> List [ Usuario ]: 13 """ 14 Filtra usuarios con c o n t r a s e a s que cumplen los requisitos de seguridad : 15 - Al menos 8 caracteres 16 - Al menos una m a y s c u l a 17 - Al menos un n m e r o 18 - Al menos un c a r c t e r especial ( @$! %?&) 19 20 P a r m e t r o s : 21 usuarios : Lista de objetos Usuario 22 23 Retorna : 24 Lista de usuarios con c o n t r a s e a s v l i d a s 25 """ 26 patron = r " ^(?=.[ A - Z ]) (?=.\ d ) (?=.[ @$! %?&]) [A - Za - z \ d@$! %?&]{8 ,} $ " 27 usuarios_validos = [] 28 29 for usuario in usuarios : 30 if re. fullmatch ( patron , usuario. c o n t r a s e a ) : 31 usuarios_validos. append ( usuario ) 32 33 return usuarios_validos 34 35 # V e r s i n alternativa con v a l i d a c i n manual ( sin regex ) 36 def validar_manual ( usuarios : List [ Usuario ]) -> List [ Usuario ]: 37 especiales = { ’@ ’ , ’$ ’ , ’! ’ , ’ %’ , ’* ’ , ’? ’ , ’& ’} 38 validos = [] 39 40 for usuario in usuarios : 41 c o n t r a s e a = usuario. c o n t r a s e a 42 if len ( c o n t r a s e a ) < 8: 43 continue 44 45 tiene_mayuscula = any ( c. isupper () for c in c o n t r a s e a ) 46 tiene_numero = any ( c. isdigit () for c in c o n t r a s e a ) 47 tiene_especial = any ( c in especiales for c in c o n t r a s e a ) 48 49 if tiene_mayuscula and tiene_numero and tiene_especial : 50 validos. append ( usuario ) 51 52 return validos 53 54 # Casos de prueba 55 usuarios = [ 56 Usuario ( " admin " , " Admin123! " ) , # V l i d a 57 Usuario ( " invitado " , " abc123 " ) , # I n v l i d a ( faltan m a y s c u l a y especial ) 58 Usuario ( " test " , " A@1bcdef " ) , # V l i d a 59 Usuario ( " user " , " password " ) , # I n v l i d a 60 Usuario ( " demo " , " Demo@2023 " ) , # V l i d a