17

(編集: Code Golf とは: Code Golf は、特定の問題を特定の問題を解決するための課題であり、文字数に応じて任意の言語で特定の問題を解決します。 詳細については、Meta StackOverflow を参照してください。)

コード ゴルファーの皆さん、文字列操作の課題です。

Email Address Validationですが、もちろん正規表現 (または同様の解析ライブラリ) はありません。メールアドレスについてはそれほど重要ではありませんが、以下に示すさまざまな文字列操作と制約をどれだけ短く記述できるかが重要です。

ルールは次のとおりです (はい、これは RFC に準拠していませんが、このチャレンジの 5 つのルールになります)。

  • @ の前に、このグループから少なくとも 1 文字:

    A-Z, a-z, 0-9, . (period), _ (underscore)
    
  • @ は必ず 1 回だけ存在する必要があります

    john@smith.com
        ^
    
  • ピリオド (.) は @ の後に 1 回だけ存在する必要があります

    john@smith.com
              ^
    
  • @ とそれに続く の間に少なくとも 1つの [AZ, az] 文字のみ。(限目)

    john@s.com
         ^
    
  • 最後. 限目

    john@smith.ab
               ^^
    

メソッド/関数のみを投稿してください。これは、文字列 (提案された電子メール アドレス) を受け取り、有効 (true) または無効 (false) である電子メール アドレスに応じて、ブール値の結果 (true/false) を返します。

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

J

:[[/%^(:[[+-/^,&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()ため、この回答は、ライブラリ関数を使用しないストレンジャーの回答ほど「クリーン」ではないと感じています。(私はまた、型なしでグローバル変数を宣言するという彼のアイデアを盗みました!)

ここでのトリックの 1 つは、文字列の先頭に.andを置くことで、テストにそれらを簡単に含めたり除外したりできることです。それらを許可したい場合は、;を使用します。そうでない場合は、 を使用します。もう 1 つは、 を想定し、「シード」ペアから一度に 2 つの有効な文字の配列を構築することです。残りは、 d マクロに引き出せるように、部分式を十分に似たものにする方法を探していました。_Astrspn()strspn(something, A)strspn(something, A+12)sizeof (short) == 2 * sizeof (char)Aa#define

このコードをより「移植可能」にするために (heh :-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;}

1 つの改行が必要であり、1 文字として数えました。

于 2009-09-08T02:16:39.573 に答える
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 文字; #include なしで 284 文字)

#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

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

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

ルビー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

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

すべてのテストに合格します (私の古いバージョンは正しくありませんでした)。

于 2009-09-07T21:27:16.923 に答える
1

Haskell (GHC 6.8.2)、165 161 144C 文字


パターン マッチング、elemspanおよびの使用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

上記は、次のコードでテストされました。

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 に答える