code-golf - lista - validar contraseña javascript expresiones regulares
Code Golf: Validación de direcciones de correo electrónico sin expresiones regulares (15)
C89, 175 caracteres.
#define G &&*((a+=t+1)-1)==
#define H (t=strspn(a,A
t;e(char*a){char A[66]="_.0123456789Aa";short*s=A+12;for(;++s<A+64;)*s=s[-1]+257;return H))G 64&&H+12))G 46&&H+12))>1 G 0;}
Estoy usando la función de biblioteca estándar strspn()
, por lo que siento que esta respuesta no es tan "limpia" como la respuesta de Strager que funciona sin ninguna función de biblioteca. (¡También le robé su idea de declarar una variable global sin un tipo!)
Uno de los trucos aquí es que poniendo .
y _
al comienzo de la cadena A
, es posible incluirlos o excluirlos fácilmente en una prueba de strspn()
: cuando desee permitirlos, use strspn(something, A)
; cuando no lo hagas, usa strspn(something, A+12)
. Otra es suponer que sizeof (short) == 2 * sizeof (char)
, y construir la matriz de caracteres válidos 2 a la vez a partir del par "semilla" Aa
. El resto solo buscaba una manera de forzar que las subexpresiones se vieran lo suficientemente similares como para que pudieran ser extraídas en #define
d macros.
Para hacer que este código sea más "portátil" (heh :-P), puede cambiar el código de creación de matriz desde
char A[66]="_.0123456789Aa";short*s=A+12;for(;++s<A+64;)*s=s[-1]+257;
a
char*A="_.0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
Por un coste de 5 personajes adicionales.
(Editar: Qué es Code Golf: Code Golf son desafíos para resolver un problema específico con la cantidad más pequeña de código por número de caracteres en el idioma que prefiera. Más información aquí en Meta StackOverflow).
Code Golfers, aquí hay un desafío en las operaciones de cuerdas.
Validación de la dirección de correo electrónico , pero sin expresiones regulares (o una biblioteca de análisis similar), por supuesto. No se trata tanto de las direcciones de correo electrónico, sino de lo breve que puede escribir las diferentes operaciones de cadena y las restricciones que se indican a continuación.
Las reglas son las siguientes (sí, lo sé, esto no es compatible con RFC, pero estas serán las 5 reglas para este desafío):
Al menos 1 personaje de este grupo antes de la @:
A-Z, a-z, 0-9, . (period), _ (underscore)
@ tiene que existir, exactamente una vez
El período (.) Tiene que existir exactamente una vez después de la @
Al menos 1 solo [AZ, az] carácter entre @ y lo siguiente. (período)
Al menos 2 solo [AZ, az] caracteres después de la final. período
Publique solo el método / función, que tomaría una cadena (dirección de correo electrónico propuesta) y luego devolvería un resultado booleano (verdadero / falso) dependiendo de si la dirección de correo electrónico es válida (verdadera) o inválida (falsa).
Samples:
[email protected] (valid/true) @w.org (invalid/false)
b@[email protected] (invalid/false) test@org (invalid/false)
test@%.org (invalid/false) s%[email protected] (invalid/false)
[email protected] (invalid/false) [email protected] (valid/true)
[email protected] (valid/true) foo@a%.com (invalid/false)
¡Buena suerte!
Haskell (GHC 6.8.2), 165 161 144C personajes
Usando la coincidencia de patrones, elem
, span
y all
:
a=[''A''..''Z'']++[''a''..''z'']
e=f.span(`elem`"._0123456789"++a)
f(_:_,''@'':d)=g$span(`elem`a)d
f _=False
g(_:_,''.'':t@(_:_:_))=all(`elem`a)t
g _=False
Lo anterior fue probado con el siguiente código:
main :: IO ()
main = print $ and [
e "[email protected]",
e "[email protected]",
e "[email protected]",
not $ e "b@[email protected]",
not $ e "test@%.org",
not $ e "[email protected]",
not $ e "@w.org",
not $ e "test@org",
not $ e "s%[email protected]",
not $ e "foo@a%.com"
]
J
:[[/%^(:[[+-/^,&i|:[$['' '']^j+0__:k<3:]]
C (166 caracteres)
#define F(t,u)for(r=s;t=(*s-64?*s-46?isalpha(*s)?3:isdigit(*s)|*s==95?4:0:2:1);++s);if(s-r-1 u)return 0;
V(char*s){char*r;F(2<,<0)F(1=)F(3=,<0)F(2=)F(3=,<1)return 1;}
Se requiere la nueva línea única, y la he contado como un carácter.
C89 (166 caracteres)
#define B(c)isalnum(c)|c==46|c==95
#define C(x)if(!v|*i++-x)return!1;
#define D(x)for(v=0;x(*i);++i)++v;
v;e(char*i){D(B)C(64)D(isalpha)C(46)D(isalpha)return!*i&v>1;}
No volver a entrar, pero se puede ejecutar varias veces. Banco de pruebas:
#include<stdio.h>
#include<assert.h>
main(){
assert(e("[email protected]"));
assert(e("[email protected]"));
assert(e("[email protected]"));
assert(!e("b@[email protected]"));
assert(!e("test@%.org"));
assert(!e("[email protected]"));
assert(!e("@w.org"));
assert(!e("test@org"));
assert(!e("s%[email protected]"));
assert(!e("foo@a%.com"));
puts("success!");
}
Conjunto de caracteres C89 agnóstico (262 caracteres)
#include <stdio.h>
/* the ''const '' qualifiers should be removed when */
/* counting characters: I don''t like warnings :) */
/* also the ''int '' should not be counted. */
/* it needs only 2 spaces (after the returns), should be only 2 lines */
/* that''s a total of 262 characters (1 newline, 2 spaces) */
/* code golf starts here */
#include<string.h>
int v(const char*e){
const char*s="0123456789._abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
if(e=strpbrk(e,s))
if(e=strchr(e+1,''@''))
if(!strchr(e+1,''@''))
if(e=strpbrk(e+1,s+12))
if(e=strchr(e+1,''.''))
if(!strchr(e+1,''.''))
if(strlen(e+1)>1)
return 1;
return 0;
}
/* code golf ends here */
int main(void) {
const char *t;
t = "[email protected]"; printf("%s ==> %d/n", t, v(t));
t = "[email protected]"; printf("%s ==> %d/n", t, v(t));
t = "[email protected]"; printf("%s ==> %d/n", t, v(t));
t = "b@[email protected]"; printf("%s ==> %d/n", t, v(t));
t = "test@%.org"; printf("%s ==> %d/n", t, v(t));
t = "[email protected]"; printf("%s ==> %d/n", t, v(t));
t = "@w.org"; printf("%s ==> %d/n", t, v(t));
t = "test@org"; printf("%s ==> %d/n", t, v(t));
t = "s%[email protected]"; printf("%s ==> %d/n", t, v(t));
t = "foo@a%.com"; printf("%s ==> %d/n", t, v(t));
return 0;
}
Versión 2
Sin embargo, el conjunto de caracteres C89 es agnóstico y se corrigieron errores (303 caracteres; 284 sin el #include)
#include<string.h>
#define Y strchr
#define X{while(Y
v(char*e){char*s="0123456789_.abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
if(*e!=''@'')X(s,*e))e++;if(*e++==''@''&&!Y(e,''@'')&&Y(e+1,''.''))X(s+12,*e))e++;if(*e++==''.''
&&!Y(e,''.'')&&strlen(e)>1){while(*e&&Y(s+12,*e++));if(!*e)return 1;}}}return 0;}
Esa #define X es absolutamente asquerosa!
Prueba como para mi primera versión (buggy).
''Usando no regex'': PHP 47 caracteres.
<?=filter_var($argv[1],FILTER_VALIDATE_EMAIL);
Cualquiera que sea la versión de C ++ MSVC2008 es compatible.
Aquí está mi humilde sumisión. Ahora sé por qué me dijeron que nunca hiciera las cosas que hice aquí:
#define N return 0
#define I(x) &&*x!=''.''&&*x!=''_''
bool p(char*a) {
if(!isalnum(a[0])I(a))N;
char*p=a,*b=0,*c=0;
for(int d=0,e=0;*p;p++){
if(*p==''@''){d++;b=p;}
else if(*p==''.''){if(d){e++;c=p;}}
else if(!isalnum(*p)I(p))N;
if (d>1||e>1)N;
}
if(b>c||b+1>=c||c+2>=p)N;
return 1;
}
No es la mejor solución, sin duda, y bastante detallada, pero es válida.
Corregido (todos los casos de prueba pasan ahora)
static bool ValidateEmail(string email)
{
var numbers = "1234567890";
var uppercase = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
var lowercase = uppercase.ToLower();
var arUppercase = uppercase.ToCharArray();
var arLowercase = lowercase.ToCharArray();
var arNumbers = numbers.ToCharArray();
var atPieces = email.Split(new string[] { "@"}, StringSplitOptions.RemoveEmptyEntries);
if (atPieces.Length != 2)
return false;
foreach (var c in atPieces[0])
{
if (!(arNumbers.Contains(c) || arLowercase.Contains(c) || arUppercase.Contains(c) || c == ''.'' || c == ''_''))
return false;
}
if(!atPieces[1].Contains("."))
return false;
var dotPieces = atPieces[1].Split(''.'');
if (dotPieces.Length != 2)
return false;
foreach (var c in dotPieces[0])
{
if (!(arLowercase.Contains(c) || arUppercase.Contains(c)))
return false;
}
var found = 0;
foreach (var c in dotPieces[1])
{
if ((arLowercase.Contains(c) || arUppercase.Contains(c)))
found++;
else
return false;
}
return found >= 2;
}
Python (181 caracteres incluyendo nuevas líneas)
def v(E):
import string as t;a=t.ascii_letters;e=a+"1234567890_.";t=e,e,"@",e,".",a,a,a,a,a,"",a
for c in E:
if c in t[0]:t=t[2:]
elif not c in t[1]:return 0>1
return""==t[0]
Básicamente, solo una máquina de estados que usa nombres de variables ofuscadamente cortos.
Erlang 266 caracteres:
-module(cg_email).
-export([test/0]).
%%% golf code begin %%%
-define(E,when X>=$a,X=<$z;X>=$A,X=<$Z).
-define(I(Y,Z),Y([X|L])?E->Z(L);Y(_)->false).
-define(L(Y,Z),Y([X|L])?E;X>=$0,X=<$9;X=:=$.;X=:=$_->Z(L);Y(_)->false).
?L(e,m).
m([$@|L])->a(L);?L(m,m).
?I(a,i).
i([$.|L])->l(L);?I(i,i).
?I(l,c).
?I(c,g).
g([])->true;?I(g,g).
%%% golf code end %%%
test() ->
true = e("[email protected]"),
false = e("b@[email protected]"),
false = e("test@%.org"),
false = e("[email protected]"),
true = e("[email protected]"),
false = e("test@org"),
false = e("s%[email protected]"),
true = e("[email protected]"),
false = e("foo@a%.com"),
ok.
Java : 257 caracteres (sin incluir el final de las 3 líneas para facilitar la lectura ;-)).
boolean q(char[]s){int a=0,b=0,c=0,d=0,e=0,f=0,g,y=-99;for(int i:s)
d=(g="@._0123456789QWERTYUIOPASDFGHJKLZXCVBNMqwertyuiopasdfghjklzxcvbnm".indexOf(i))<0?
y:g<1&&++e>0&(b<1|++a>1)?y:g==1&e>0&(c<1||f++>0)?y:++b>0&g>12?f>0?d+1:f<1&e>0&&++c>0?
d:d:d;return d>1;}
Pasa todas las pruebas (mi versión anterior era incorrecta).
Python, 149 caracteres (después de colocar todo el bucle for
en una línea separada por punto y coma, lo que no he hecho aquí por motivos de "legibilidad"):
def v(s,t=0,o=1):
for c in s:
k=c=="@"
p=c=="."
A=c.isalnum()|p|(c=="_")
L=c.isalpha()
o&=[A,k|A,L,L|p,L,L,L][t]
t+=[1,k,1,p,1,1,0][t]
return(t>5)&o
Casos de prueba , tomados de la respuesta de Strager :
assert v("[email protected]")
assert v("[email protected]")
assert v("[email protected]")
assert not v("b@[email protected]")
assert not v("test@%.org")
assert not v("[email protected]")
assert not v("@w.org")
assert not v("test@org")
assert not v("s%[email protected]")
assert not v("foo@a%.com")
print "Yeah!"
Explicación : Al iterar sobre la cadena, dos variables se mantienen actualizadas.
t
mantiene el estado actual:
-
t = 0
: estamos al principio. -
t = 1
: Estamos al principio y hemos encontrado al menos un carácter legal (letra, número, subrayado, punto) -
t = 2
: Hemos encontrado el "@
" -
t = 3
: hemos encontrado al menos un carácter legal (es decir, una letra) después de "@
" -
t = 4
: hemos encontrado el período en el nombre de dominio -
t = 5
: hemos encontrado un carácter legal (letra) después del período -
t = 6
: hemos encontrado al menos dos caracteres legales después del período
o
como en "okay" comienza como 1
, es decir, verdadero, y se establece en 0
tan pronto como se encuentra un carácter que es ilegal en el estado actual. Los personajes legales son:
- En el estado
0
: letra, número, guión bajo, punto (cambiar el estado a1
en cualquier caso) - En el estado
1
: letra, número, guión bajo, punto, signo de entrada (cambie el estado a2
si se encuentra "@
") - En estado
2
: letra (cambiar estado a3
) - En el estado
3
: letra, período (cambie el estado a 4 si se encuentra el período) - En los estados
4
a6
: letra (incremento de estado cuando está en4
o5
)
Cuando hemos recorrido todo el camino a través de la cadena, devolvemos si t==6
( t>5
es un carácter menos) y o
es 1.
Rubí , 225 caracteres . Este es mi primer programa de Ruby, así que probablemente no sea muy parecido a Ruby :-)
def v z;r=!a=b=c=d=e=f=0;z.chars{|x|case x when''@'';r||=b<1||!e;e=!1 when''.''
e ?b+=1:(a+=1;f=e);r||=a>1||(c<1&&!e)when''0''..''9'';b+=1;r|=!e when''A''..''Z'',''a''..''z''
e ?b+=1:f ?c+=1:d+=1;else r=1 if x!=''_''||!e|!b+=1;end};!r&&d>1 end
VBA / VB6 - 484 caracteres
Explícito apagado
uso: VE ("[email protected]")
Function V(S, C)
V = True
For I = 1 To Len(S)
If InStr(C, Mid(S, I, 1)) = 0 Then
V = False: Exit For
End If
Next
End Function
Function VE(E)
VE = False
C1 = "abcdefghijklmnopqrstuvwxyzABCDEFGHILKLMNOPQRSTUVWXYZ"
C2 = "0123456789._"
P = Split(E, "@")
If UBound(P) <> 1 Then GoTo X
If Len(P(0)) < 1 Or Not V(P(0), C1 & C2) Then GoTo X
E = P(1): P = Split(E, ".")
If UBound(P) <> 1 Then GoTo X
If Len(P(0)) < 1 Or Not V(P(0), C1) Or Len(P(1)) < 2 Or Not V(P(1), C1) Then GoTo X
VE = True
X:
End Function