0votos

Contraseñas (Haskell) en Haskell

por josejuan hace 3 años

Creo que hay que verificar que al menos hay una letra, no más de 20 y todas son letras minúsculas, sino, quitar tres reglas de ahí (líneas 11, 12 y 13).

Verificar que las contraseñas introducidas sean "seguras" de acuerdo a 3 reglas que deben cumplirse (Resolver el ejercicio acorde a los planteamientos dados en el lenguaje de programación Haskell)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
import Data.List (groupBy) 
import Data.Function (on) 
 
vocal      = flip elem "aeiou" 
consonante = flip elem "bcdfghjklmnpqrstvwxyz" 
 
-- La aplicación del preficado no aparece más de n veces consecutivas 
no_mas_de n f = null ∘ filter (λ(x:xs) → f x ∧ length xs ≥ n - 1) ∘ groupBy ((≡) `on` f) 
 
contraseña_válida pwd = all ($ pwd) 
  [ (>0) ∘ length                                                               -- al menos una letra 
  , (<21) ∘ length                                                              -- no más de 20 letras 
  , all (λc → vocal c ∨ consonante c)                                           -- todo letras minúsculas 
  , any vocal                                                                   -- alguna vocal 
  , no_mas_de 3 vocal                                                           -- no más de 3 vocales 
  , no_mas_de 3 consonante                                                      -- no más de 3 consonantes 
  , and ∘ flip map "abcdfghijklmnpqrstuvwxyz" ∘ (λxs c → no_mas_de 2 (≡c) xs)   -- rara... 
2 comentarios
0votos

Escrito por JCarles hace 3 años

Pues sí, no me había fijado en ese párrafo de los requisitos de longitud y letras minúsculas. Revisaré mi solución.

Mi primera aproximación fue algo parecido a lo que has puesto (aunque más humanizado y menos "haskilístico") pero me di cuenta que al poner los requisitos individualmente provoca una lectura múltiple del input. En tu caso, por ejemplo, si el password es "aabababababababababa", tu validación ha tenido que mirar la longitud, todos los carácteres para ver si es todo vocales y todo consonantes, si hay más de 3 vocales seguidas, si hay más de 3 consonantes seguidas, hasta darse cuenta que, y en la última condición, que las dos primeras letras son repetidas. Sé que a nivel de velocidad es insignificante, pero algorítmicamente, ¿no sería más correcto (a nivel de ejecución) tratarlo como un sistema finito de estados?

Por otra parte, ¿me ayudas a poder usar tu "pretty-mode" con ghci? He googleado y no he encontrado la forma.
0votos

Escrito por josejuan hace 3 años

Bueno, no veo claro que revisar N reglas a lo largo de M caracteres sea más ni menos eficiente que revisar M caracteres a lo largo de N reglas. Cierto que en el segundo caso puedes haber revisado (N-1)*M caracteres y fallar en la última regla (cuando con la otra estrategia podría detectarlo en N*1), pero de la misma forma con la primera puedes estar revisando las N reglas durante M caracteres (N*M) y con la segunda fallar en la primera (1*M). En particular, para contraseñas válidas, ambas estrategias revisan N*M caracteres. Por tanto, he preferido independizar las reglas que favorece la legibilidad, revisión y refactorización acción del código (añadir y quitar reglas es trivial).

Eso en cuanto a la complejidad, si hablamos de la constante multiplicativa parece (a ojo) que resultará más óptimo fusionar las reglas (más que nada porque hay más oportunidades de optimización), pero sólo merecería la pena si hay que revisar millones en muy poco tiempo y tendría el gran inconveniente de la legibilidad y mantenibilidad. Además, un simple análisis estadístico (en línea, es decir mientras va revisando) puede anteponer las reglas con mayor P de fallar (lo cual seguramente será un speedup mayor que la anterior).

Resumiendo, me pareció más lógico hacerlo legible.

Uso vim con el conceal activado para la sustitución de caracteres, esta documentado en (por ejemplo) haskell-vim-now.

Comenta la solución

Tienes que identificarte para poder publicar tu comentario.