17

(编辑:什么是 Code Golf:Code Golf 是用您喜欢的任何语言的字符数以最少的代码量解决特定问题的挑战。 更多信息请参见Meta StackOverflow。)

Code Golfers,这是字符串操作的挑战。

电子邮件地址验证,但当然没有正则表达式(或类似的解析库)。与其说是电子邮件地址,不如说是您可以编写多短的不同字符串操作和下面给出的约束。

规则如下(是的,我知道,这不符合 RFC,但这些将是本次挑战的 5 条规则):

  • 该组中至少有 1 个字符位于 @ 之前:

    A-Z, a-z, 0-9, . (period), _ (underscore)
    
  • @ 必须存在,只存在一次

    john@smith.com
        ^
    
  • 句点 (.) 必须在 @ 之后恰好存在一次

    john@smith.com
              ^
    
  • @ 和以下之间至少有 1 个[AZ, az]字符。(时期)

    john@s.com
         ^
    
  • 在最后的 . 之后至少只有 2 个 [AZ, az]字符。时期

    john@smith.ab
               ^^
    

请仅发布方法/函数,它将采用字符串(建议的电子邮件地址),然后根据电子邮件地址有效(真)或无效(假)返回布尔结果(真/假)。

Samples:
b@w.org    (valid/true)          @w.org     (invalid/false)    
b@c@d.org  (invalid/false)       test@org   (invalid/false)    
test@%.org (invalid/false)       s%p@m.org  (invalid/false)    
j_r@x.c.il (invalid/false)       j_r@x.mil  (valid/true)
r..t@x.tw  (valid/true)          foo@a%.com (invalid/false)

祝你好运!

4

15 回答 15

20

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("b@w.org"));
    assert(e("r..t@x.tw"));
    assert(e("j_r@x.mil"));
    assert(!e("b@c@d.org"));
    assert(!e("test@%.org"));
    assert(!e("j_r@x.c.il"));
    assert(!e("@w.org"));
    assert(!e("test@org"));
    assert(!e("s%p@m.org"));
    assert(!e("foo@a%.com"));
    puts("success!");
}
于 2009-09-07T18:11:59.770 回答
12

Ĵ

:[[/%^(:[[+-/^,&i|:[$[' ']^j+0__:k<3:]]
于 2009-09-07T20:46:06.887 回答
6

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(),所以我觉得这个答案不像 strager 的答案那样“干净”,没有任何库函数。(我还偷了他声明一个没有类型的全局变量的想法!)

这里的技巧之一是通过将.and_放在字符串的开头,A可以在测试中轻松地包含或排除它们strspn():当你想允许它们时,使用strspn(something, A); 如果不这样做,请使用strspn(something, A+12). 另一个是假设sizeof (short) == 2 * sizeof (char),并从“种子”对一次构建有效字符数组 2 Aa。其余的只是寻找一种方法来强制子表达式看起来足够相似,以便可以将它们拉出到#defined 宏中。

要使此代码更“可移植”(呵呵 :-P),您可以将数组构建代码从

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

char*A="_.0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";

额外花费 5 个字符。

于 2009-09-07T20:59:54.580 回答
5

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]

基本上只是一个使用令人困惑的短变量名的状态机。

于 2009-09-07T18:21:20.330 回答
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;}

需要一个换行符,我把它算作一个字符。

于 2009-09-08T02:16:39.573 回答
4

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("b@w.org")
assert v("r..t@x.tw")
assert v("j_r@x.mil")
assert not v("b@c@d.org")
assert not v("test@%.org")
assert not v("j_r@x.c.il")
assert not v("@w.org")
assert not v("test@org")
assert not v("s%p@m.org")
assert not v("foo@a%.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
  • In state :字母、数字、下划线、句点、at-sign(如果找到“ ”,则将1状态更改为)2@
  • 处于状态2:字母(将状态更改为3
  • 状态3:字母,句号(如果找到句号,则将状态更改为 4)
  • In states 4thru 6: letter (在4or时递增状态5

当我们一直遍历字符串时,我们返回是否t==6(t>5少一个字符) 并且o是 1。

于 2009-09-10T19:54:55.493 回答
2

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'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 = "b@w.org"; printf("%s ==> %d\n", t, v(t));
  t = "r..t@x.tw"; printf("%s ==> %d\n", t, v(t));
  t = "j_r@x.mil"; printf("%s ==> %d\n", t, v(t));
  t = "b@c@d.org"; printf("%s ==> %d\n", t, v(t));
  t = "test@%.org"; printf("%s ==> %d\n", t, v(t));
  t = "j_r@x.c.il"; 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%p@m.org"; printf("%s ==> %d\n", t, v(t));
  t = "foo@a%.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 真是太恶心了!

测试我的第一个(错误)版本。

于 2009-09-07T19:11:58.557 回答
2

毫无疑问,这不是最好的解决方案,而且非常冗长,但它是有效的。

已修复(所有测试用例现在都通过了)

    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;
}
于 2009-09-07T18:33:51.860 回答
2

无论 C++ 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;
}
于 2009-09-07T18:03:57.617 回答
1

Java257个字符(不包括可读性的 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;}

通过所有测试(我的旧版本不正确)。

于 2009-09-07T21:27:16.923 回答
1

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([$@|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("b@w.org"),
  false = e("b@c@d.org"),
  false = e("test@%.org"),
  false = e("j_r@x.c.il"),
  true  = e("r..t@x.tw"),
  false = e("test@org"),
  false = e("s%p@m.org"),
  true  = e("j_r@x.mil"),
  false = e("foo@a%.com"),
  ok.
于 2009-09-08T13:11:09.497 回答
1

红宝石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
于 2009-09-08T22:32:29.773 回答
1

VBA/VB6 - 484 个字符

显式关闭
用法:VE("b@w.org")

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
于 2009-09-07T22:15:29.700 回答
1

“不使用正则表达式”:PHP 47 字符。

<?=filter_var($argv[1],FILTER_VALIDATE_EMAIL);
于 2009-10-26T18:53:24.227 回答
1

Haskell (GHC 6.8.2),165 161 144C 个字符


使用模式匹配elemspanall

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

上面是用下面的代码测试的:

main :: IO ()
main = print $ and [
  e "b@w.org",
  e "r..t@x.tw",
  e "j_r@x.mil",
  not $ e "b@c@d.org",
  not $ e "test@%.org",
  not $ e "j_r@x.c.il",
  not $ e "@w.org",
  not $ e "test@org",
  not $ e "s%p@m.org",
  not $ e "foo@a%.com"
  ]
于 2009-10-26T19:48:28.983 回答