最新:
私はそれを下に絞ってきた644の文字私はコピーして、パーへの細胞の一部を織り込み、。cellおよびcdrの呼び出しを一時的なローカル変数にキャッシュし、それらのローカル変数を「ターミナル」(つまり、非再帰)関数のグローバルに移動しました。また、10進定数は文字リテラルよりも短く、この厄介なビジネス...
atom(x){
return m[x]>>5==3;
}
...小文字(ASCIIを想定)を正しく識別しますが、任意の `{|}〜も受け入れます。(ASCIIに関するこの同じ観察結果は、UTF-8に関するこの優れたビデオで作成されています。)
Et viola:|
#include<stdio.h>
#include<string.h>
#define X m[x]
#define R return
char*n,*m;int u,w,d;C(x,y){w=n-m;n+=sprintf(n,y?"(%s %s)":"(%s)",&X,m+y)+1;R w;}T(x){R X>>5==3;}
L(x){R X==92;}O(x,j){w=n-m;memcpy(n,&X,j);n+=j;*n++=0;R w;}E(x){X==' '?++x:0;R
X==41?0:L(x)?O(x,4):P(x);}P(x){d=0,w=x;do{X==40?d++:X==41?d--:0;++x;}while(d>0);R
O(w,x-w);}D(x){u=E(x+1);R u?E(x+1+strlen(m+u)):0;}V(x){int a=E(x+1),b=D(x);R
T(x)|T(a)?x:L(a)?C(a,V(b)):L(E(a+1))?V(S(V(b),E(a+3),D(a))):V(C(V(a),b?V(b):0));}S(w,y,x){R
T(x)?(X==m[y]?w:x):C(L(w+1)?E(x+1):S(w,y,E(x+1)),D(x)?S(w,y,D(x)):0);}
Y(char*s){n+=strlen(s=strcpy(n,s))+1;printf("%s\n%s\n\n",s,m+V(s-m));n=m+1;}
char*s[]={
"((\\ a. a) (b))",
"((\\ x. x) (\\ y. (\\ z. z)))",
"(\\ x. ((\\ y. y) x))",
"(((\\ x. (\\ y. x)) (\\ a. a)) (\\ b. b))",
"((\\ x. (\\ y. y)) (\\ a. a))",
"(((\\ x. (\\ y. y)) (\\ a. a)) (\\ b. b))",
"((\\x. (x x)) (\\x. (x x)))",0};
#include<unistd.h>
main(){char**k;n=m=sbrk(4096);*n++=0;for(k=s;*k;k++)Y(*k);R 0;}
以前:
努力して数票獲得できますか?私は一週間この昼と夜に取り組んでいます。オリジナルのMcCarthy論文を掘り出し、Paul GrahamのThe Roots of Lispの付録を読むまで、論文自体のバグに悩まされていました。私は気が散り、家を閉め出してから、その夜の12時30分に再び家に着くまで完全に忘れてしまいました(少し遅れて郡内に住んでいるビルのマネージャーに電話することになりました)。祖母の夜(ラップトップのバッテリーが乾くまでハッキングして)。
そして、結局のところ、それは優勝したエントリーの近くにさえありません!
これをもっと短くする方法がわかりません。そして、私は考えることができるすべての汚いトリックを使用しました!たぶん、Cではできません。
カウントに多少の寛大さ(最初のチャンクは文字列を取り、結果を出力します)では、778 770 709 694文字です。しかし、スタンドアロンにするには、そのsbrk
呼び出しが必要です。また、より複雑な式を処理するには、signal
ハンドラーも必要です。そしてもちろん、それを使用しようとするコードでモジュールにすることはできませんmalloc
。
悲しいかな、ここにあります:
#include<stdio.h>
#include<string.h>
#define K(j) strncpy(n,m+x,j);n+=j;goto N;
#define R return
#define X m[x]
#define L =='\\'
char*m,*n;T(x){R islower(X);}V(x){int a=E(x+1);R
T(x)?x:T(a)?x:m[a]L?C(a,V(D(x))):m[E(a+1)]L?V(S(V(D(x)),E(a+3),D(a))):V(C(V(a),D(x)?V(D(x)):0));}
C(x,y){char*t=n;sprintf(n,y?"(%s %s)":"(%s)",m+x,m+y);n+=strlen(n)+1;R
t-m;}Y(char*s){char*t=strcpy(n,s);n+=strlen(n)+1;printf("%s=>%s\n",s,m+V(t-m));n=m+1;}S(x,y,z){R
T(z)?(m[z]==m[y]?x:z):C(m[z+1]L?E(z+1):S(x,y,E(z+1)),D(z)?S(x,y,D(z)):0);}D(x){R
E(x+1)?E(x+strlen(m+E(x+1))+1):0;}E(x){char*t=n,d=0;if(X==' ')++x;if(T(x)){K(1)}if(X
L){K(4)}do{d=X?(X=='('?d+1:(X==')'?d-1:d)):0;*n++=m[x++];}while(d);N:*n++=0;R t-m;}
char*samp[]={
"a","a","b","b",
"((\\ a. a) (b))", "(b)",
"((\\ x. x) (\\ y. (\\ z. z)))", "(\\ y. (\\ z. z))",
"(\\ x. ((\\ y. y) x))", "(\\ x. x)",
"(((\\ x. (\\ y. x)) (\\ a. a)) (\\ b. b))", "(\\ a. a)",
"((\\ x. (\\ y. y)) (\\ a. a))", "(\\ y. y)",
"(((\\ x. (\\ y. y)) (\\ a. a)) (\\ b. b))", "(\\ b. b)",
"((\\x. (x x)) (\\x. (x x)))", "undef",
NULL};
#include<unistd.h>
unsigned sz;
#include<signal.h>
void fix(x){signal(SIGSEGV,fix);brk(m+(sz*=2));}
main(){
char**t;
signal(SIGSEGV,fix);
m=n=sbrk(sz=10*getpagesize());
*n++=0;
for(t=samp;*t;t+=2){
Y(*t);
printf("s.b. => %s\n\n", t[1]);
}
return 0;
}
これが最終的な削減の直前のブロックです。ここでのコツは、ポインターではなく整数カーソル(「暗黙のint」動作を利用)、および「スクラッチメモリ」の使用です。これchar*n
は、空き領域への「新しい」または「次の」ポインターです。しかし、文字列をメモリに書き込み、strlenを呼び出してnをインクリメントすることがあります。サイズの計算が容易になった後、メモリを効果的に使用してから割り当てます。cell()
関数とデータの文字列表現の間のインターフェイスを除いて、McCarthyの論文からほとんどまっすぐであることがわかります。
#include<stdio.h>
#include<string.h>
char*m,*n; //memory_base, memory_next
atom(x){ // x is an atom if it is a cursor to a lowercase alpha char.
return x?(islower(m[x])?m[x]:0):0;
}
eq(x,y){ // x and y are equal if they are both atoms, the same atom.
return x&&y&&atom(x)==atom(y);
}
cell(x){ // return a copy of the list-string by cursor, by parsing
char*t=n,d=0;
if(!x||!m[x])
return 0;
if(m[x]==' ')
++x;
if(atom(x)){
*n++=m[x];
*n++=0;
return(n-m)-2;
}
if(m[x]=='\\'){ // our lambda symbol
memcpy(n,m+x,4);
n+=4;
*n++=0;
return(n-m)-5;
}
do{ // um ...
d=m[x]?(m[x]=='('?d+1:(m[x]==')'?d-1:d)):0;
*n++=m[x++];
}while(d);
*n++=0;
return t-m;
}
car(x){ // return (copy of) first element
return x?cell(x+1):0;
}
cdr(x){ // return (copy of) rest of list
return car(x)?cell(x+strlen(m+car(x))+1):0;
}
cons(x,y){ // return new list containing first x and rest y
char*t=n;
return x?(sprintf(n,y?"(%s %s)":"(%s)",m+x,m+y),n+=strlen(n)+1,t-m):0;
}
subst(x,y,z){ // substitute x for z in y
if(!x||!y||!z)
return 0;
return atom(z)? (eq(z,y)?x:z):
cons(m[z+1]=='\\'?car(z):
subst(x,y,car(z)),cdr(z)?subst(x,y,cdr(z)):0);
}
eval(x){ // evaluate a lambda expression
int a;
return atom(x)?x:
atom(a=car(x))?x:
m[a]=='\\'?cons(a,eval(cdr(x))):
m[car(a)]=='\\'?eval(subst(eval(cdr(x)),cell(a+3),cdr(a))):
eval( cons(eval(a),cdr(x)?eval(cdr(x)):0));
}
try(char*s){ // handler
char*t=strcpy(n,s);
n+=strlen(n)+1;
printf("input: %s\n", s);
printf("eval => %s\n", m+eval(t-m));
n=m+1;
}