Подтвердить что ты не робот

Code Golf: проверка адреса электронной почты без регулярных выражений

(Edit: What's Code Golf: Code Golf - это проблемы для решения конкретной проблемы с наименьшим количеством кода по количеству символов, которые вы предпочитаете. Подробнее здесь в Meta StackOverflow.)

Code Golfers, вот вызов строковых операций.

Проверка адресов электронной почты, но без регулярных выражений (или аналогичной библиотеки синтаксического анализа). Это не столько об адресах электронной почты, сколько о том, насколько короткими вы можете написать различные строковые операции и ограничения, приведенные ниже.

Правила следующие (да, я знаю, это не соответствует RFC, но это будут 5 правил для этой задачи):

  • Как минимум 1 символ из этой группы перед @:

    A-Z, a-z, 0-9, . (period), _ (underscore)
    
  • @должно существовать ровно один раз

    [email protected]
        ^
    
  • Период (.) должен существовать ровно через один раз после @

    [email protected]
              ^
    
  • Не менее 1 только символ [A-Z, a-z] между @и следующим. (Период)

    [email protected]
         ^
    
  • По крайней мере 2 только символы [A-Z, a-z] после финала. Период

    [email protected]
               ^^
    

Пожалуйста, опубликуйте только метод/функцию, которая возьмет строку (предложенный адрес электронной почты), а затем вернет логический результат (true/false) в зависимости от того, какой адрес электронной почты действителен (true) или недействителен (false).

Samples:
[email protected]    (valid/true)          @w.org     (invalid/false)    
[email protected]@d.org  (invalid/false)       [email protected]   (invalid/false)    
[email protected]%.org (invalid/false)       s%[email protected]  (invalid/false)    
[email protected] (invalid/false)       [email protected]  (valid/true)
[email protected]  (valid/true)          [email protected]%.com (invalid/false)

Удачи!

4b9b3361

Ответ 1

C89 (166 символов)

#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;}

Не повторный вход, но может выполняться несколько раз. Испытательная кровать:

#include<stdio.h>
#include<assert.h>
main(){
    assert(e("[email protected]"));
    assert(e("[email protected]"));
    assert(e("[email protected]"));
    assert(!e("[email protected]@d.org"));
    assert(!e("[email protected]%.org"));
    assert(!e("[email protected]"));
    assert(!e("@w.org"));
    assert(!e("[email protected]"));
    assert(!e("s%[email protected]"));
    assert(!e("[email protected]%.com"));
    puts("success!");
}

Ответ 2

J

:[[/%^(:[[+-/^,&i|:[$[' ']^j+0__:k<3:]]

Ответ 3

C89, 175 символов.

#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;}

Я использую стандартную библиотечную функцию strspn(), поэтому я чувствую, что этот ответ не такой "чистый", как строгарный ответ, который без каких-либо функций библиотеки. (Я также украл его идею объявить глобальную переменную без типа!)

Один из трюков заключается в том, что, положив . и _ в начале строки A, можно легко включить или исключить их в тесте strspn(): когда вы хотите разрешить им, используйте strspn(something, A); Если вы этого не сделаете, используйте strspn(something, A+12). Другой предполагает, что sizeof (short) == 2 * sizeof (char) и создание массива действительных символов 2 за раз из пары "семя" Aa. Остальное просто искало способ заставить подвыражения выглядеть достаточно похожими, чтобы их можно было вытащить в макросы #define d.

Чтобы сделать этот код более "портативным" (heh: -P), вы можете изменить код построения массива из

char A[66]="_.0123456789Aa";short*s=A+12;for(;++s<A+64;)*s=s[-1]+257;

к

char*A="_.0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";

за 5 дополнительных символов.

Ответ 4

Python (181 символ, включая символы новой строки)

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]

В основном просто машина состояния, использующая обнюхивающие короткие имена переменных.

Ответ 5

C (166 символов)

#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;}

Требуется одна новая строка, и я подсчитал ее как один символ.

Ответ 6

Python, 149 символов (после того, как весь цикл for помещается в одну строку с разделителями с запятой, которую я не сделал здесь для целей "читаемости" ):

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

Тестовые примеры, заимствованные из ответ strager:

assert v("[email protected]")
assert v("[email protected]")
assert v("[email protected]")
assert not v("[email protected]@d.org")
assert not v("[email protected]%.org")
assert not v("[email protected]")
assert not v("@w.org")
assert not v("[email protected]")
assert not v("s%[email protected]")
assert not v("[email protected]%.com")
print "Yeah!"

Объяснение. При повторении по строке две переменные продолжают обновляться.

t сохраняет текущее состояние:

  • t = 0: Мы в начале.
  • t = 1: Мы, где в начале и нашли хотя бы один юридический символ (буква, число, подчеркивание, период)
  • t = 2: Мы нашли "@"
  • t = 3: Мы нашли, по крайней мере, юридический характер (т.е. письмо) после "@"
  • t = 4: Мы нашли период в доменном имени
  • t = 5: Мы нашли один юридический символ (письмо) после периода
  • t = 6: Мы обнаружили по крайней мере два юридических символа после периода

o, как в "okay", начинается как 1, то есть true, и устанавливается в 0, как только обнаружен символ, который является незаконным в текущем состоянии. Юридические символы:

  • В состоянии 0: буква, номер, подчеркивание, период (в любом случае изменить состояние на 1)
  • В состоянии 1: буква, число, символ подчеркивания, период, знак at (изменение состояния до 2, если найдено "@" )
  • В состоянии 2: письмо (изменить состояние на 3)
  • В состоянии 3: буква, период (изменение состояния до 4, если найденный период)
  • В состояниях 4 thru 6: буква (состояние приращения при 4 или 5)

Когда мы прошли весь путь через строку, мы возвращаем, будет ли t==6 (t>5 меньше char), а o равно 1.

Ответ 7

Независимо от версии С++ MSVC2008.

Здесь мое скромное подчинение. Теперь я знаю, почему они сказали мне никогда не делать то, что я сделал здесь:

#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;
}

Ответ 8

Не самое большое решение, без сомнения, и довольно чертовски многословное, но оно действительно.

Исправлено (все тестовые примеры проходят сейчас)

    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;
}

Ответ 9

C89 набор символов агностик (262 символа)

#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 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 = "[email protected]@d.org"; printf("%s ==> %d\n", t, v(t));
  t = "[email protected]%.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 = "[email protected]"; printf("%s ==> %d\n", t, v(t));
  t = "s%[email protected]"; printf("%s ==> %d\n", t, v(t));
  t = "[email protected]%.com"; printf("%s ==> %d\n", t, v(t));

  return 0;
}

Версия 2

Тем не менее C89 набор символов агностик, ошибки исправлены (303 символа, 284 без #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;}

Это #define X абсолютно отвратительно!

Проверьте мою первую (багги) версию.

Ответ 10

Java: 257 символов (не включая 3 конца строк для удобочитаемости;-)).

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;}

Проходит все тесты (моя старшая версия была неправильной).

Ответ 11

VBA/VB6 - 484 символа

Явное выключение  использование: 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

Ответ 12

Erlang 266 символов:

-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([[email protected]|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("[email protected]@d.org"),
  false = e("[email protected]%.org"),
  false = e("[email protected]"),
  true  = e("[email protected]"),
  false = e("[email protected]"),
  false = e("s%[email protected]"),
  true  = e("[email protected]"),
  false = e("[email protected]%.com"),
  ok.

Ответ 13

Ruby, 225 символов. Это моя первая программа Ruby, поэтому она, вероятно, не очень похожа на 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

Ответ 14

'Без использования регулярного выражения: PHP 47 Chars.

<?=filter_var($argv[1],FILTER_VALIDATE_EMAIL);

Ответ 15

Haskell (GHC 6.8.2), 165 161 144C Персонажи


Использование сопоставления с образцом, elem, span и all:

a=['A'..'Z']++['a'..'z']
e=f.span(`elem`"._0123456789"++a)
f(_:_,'@':d)=g$span(`elem`a)d
f _=False
g(_:_,'.':[email protected](_:_:_))=all(`elem`a)t
g _=False

Выше было протестировано со следующим кодом:

main :: IO ()
main = print $ and [
  e "[email protected]",
  e "[email protected]",
  e "[email protected]",
  not $ e "[email protected]@d.org",
  not $ e "[email protected]%.org",
  not $ e "[email protected]",
  not $ e "@w.org",
  not $ e "[email protected]",
  not $ e "s%[email protected]",
  not $ e "[email protected]%.com"
  ]