최신 :
나는 그것을 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의 The Lis 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;
}