最新:
我将其压缩到644个字符,将部分cEll分解为cOpy和Par。将对单元格和cdr的调用缓存到临时局部变量中,并将这些局部变量移至“终端”(即非递归)函数中的全局变量中。此外,十进制常量比字符文字短,这令人讨厌的事情...
atom(x){
return m[x]>>5==3;
}
...可以正确识别小写字母(假设为ASCII),但也可以接受`{|}〜中的任何一个。(在有关UTF-8的精彩视频中也有关于ASCII的相同观察。)
中提琴:|
#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)的《 Lisp的根源》的附录。我太分心了,以至于我将自己锁在屋外,然后完全忘记了,直到那天晚上12:30再次回到家(有点晚才打电话给住在县里的建筑经理),不得不花晚上在祖母家(偷东西直到笔记本电池没电了)。
毕竟,它甚至与获奖作品还差得远!
我不确定如何使它更短。而且我用了我能想到的所有肮脏的把戏!也许它不能用C语言完成。
有了一些慷慨的计算(第一个块采用一个字符串并打印出结果),它就是778 770 709 694个字符。但是要使其独立,它必须具有该sbrk
调用。为了处理更复杂的表达式,它也需要signal
处理程序。当然,它不能与任何尝试使用的代码一起制成模块malloc
。
所以,a,这里是:
#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;在更容易计算大小之后,有效地使用内存然后进行分配。您可以从McCarthy的论文中直接看到它,除了cell()
函数和数据的字符串表示形式之间的哪些接口。
#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;
}