लावारिस लैंबडा कैलकुलस के लिए एक दुभाषिया लिखें


45

चुनौती यह है कि जितने संभव हो उतने लैंबडा कैलकुलस के लिए एक दुभाषिया लिखें । हम अप्रकाशित लैम्ब्डा कैलकुलस को इस प्रकार परिभाषित करते हैं:

वाक्य - विन्यास

निम्नलिखित तीन प्रकार के भाव हैं:

  • एक लैम्ब्डा अभिव्यक्ति का वह रूप है (λ x. e)जहाँ xकोई भी कानूनी चर नाम और eकोई कानूनी अभिव्यक्ति हो सकती है। यहां xपैरामीटर eकहा जाता है और फ़ंक्शन बॉडी कहा जाता है।

    सादगी की खातिर हम आगे प्रतिबंध लगाते हैं कि एक ही नाम के साथ एक चर नहीं होना चाहिए जैसा कि xवर्तमान में गुंजाइश है। एक चर उस दायरे में होना शुरू होता है जब उसका नाम बीच में दिखाई देता है और .इसी के दायरे में होना बंद हो जाता है )

  • समारोह आवेदन फार्म है (f a)जहां fऔर aकानूनी अभिव्यक्ति कर रहे हैं। यहां fफ़ंक्शन aको कहा जाता है और तर्क कहा जाता है।
  • एक वैरिएबल का वह रूप है xजहां xएक कानूनी वैरिएबल नाम है।

शब्दार्थ

फ़ंक्शन में पैरामीटर की प्रत्येक घटना को उसके तर्क के साथ प्रतिस्थापित करके एक फ़ंक्शन लागू किया जाता है। अधिक औपचारिक रूप से प्रपत्र की एक अभिव्यक्ति ((λ x. e) a)है, जहां xएक चर नाम है और eऔर aभाव, मूल्यांकन करता है (या कम कर देता है) अभिव्यक्ति कर रहे हैं e'जहां e'से प्रत्येक घटना की जगह का परिणाम है xमें eसाथ a

एक सामान्य रूप एक अभिव्यक्ति है जिसका मूल्यांकन आगे नहीं किया जा सकता है।

चुनौती

आपका मिशन, क्या आपको इसे स्वीकार करना चाहिए, एक दुभाषिया लिखना है जो अपने इनपुट के रूप में बिना किसी मुक्त चर वाले लांपा कलन की अभिव्यक्ति लेता है और इसका आउटपुट अभिव्यक्ति के सामान्य रूप (या एक अभिव्यक्ति अल्फा-अनुरूप) के रूप में होता है। । यदि अभिव्यक्ति का कोई सामान्य रूप नहीं है या यह एक मान्य अभिव्यक्ति नहीं है, तो व्यवहार अपरिभाषित है।

सबसे छोटी संख्या वाले वर्णों का समाधान जीत जाता है।

नोटों की एक जोड़ी:

  • इनपुट या तो स्टड से पढ़ा जा सकता है या कमांड लाइन तर्क के रूप में दिए गए फ़ाइलनाम से (आपको केवल एक या दूसरे को लागू करने की आवश्यकता है - दोनों नहीं)। आउटपुट स्टडआउट जाता है।
  • वैकल्पिक रूप से आप एक फ़ंक्शन को परिभाषित कर सकते हैं जो इनपुट को स्ट्रिंग के रूप में लेता है और आउटपुट को स्ट्रिंग के रूप में वापस करता है।
  • यदि गैर-ASCII वर्ण आपके लिए समस्याग्रस्त हैं, तो आप \λ के बजाय बैकस्लैश ( ) वर्ण का उपयोग कर सकते हैं ।
  • हम वर्णों की संख्या की गणना करते हैं, बाइट्स की नहीं, इसलिए भले ही आपकी स्रोत फ़ाइल यूनिकोड λ के एक वर्ण के रूप में गिना जाए।
  • कानूनी चर नामों में एक या अधिक लोअर केस लेटर्स होते हैं, यानी a और z के बीच के अक्षर (अल्फ़ान्यूमेरिक नाम, अपर केस लेटर्स या नॉन-लैटिन लेटर्स का समर्थन करने की आवश्यकता नहीं है - हालाँकि ऐसा करने से आपका समाधान अमान्य नहीं होगा)।
  • जहां तक ​​इस चुनौती का सवाल है, कोई भी कोष्ठक वैकल्पिक नहीं हैं। प्रत्येक लैम्ब्डा अभिव्यक्ति और प्रत्येक फ़ंक्शन एप्लिकेशन को कोष्ठक के ठीक एक जोड़े से घिरा होगा। कोई चर नाम कोष्ठकों से घिरा नहीं होगा।
  • के (λ x y. e)लिए लिखने की तरह सिंथेटिक चीनी का (λ x. (λ y. e))समर्थन करने की आवश्यकता नहीं है।
  • यदि किसी फ़ंक्शन का मूल्यांकन करने के लिए 100 से अधिक की पुनरावृत्ति गहराई आवश्यक है, तो व्यवहार अपरिभाषित है। यह सभी भाषाओं में अनुकूलन के बिना लागू होने के लिए कम से कम पर्याप्त होना चाहिए और अभी भी काफी बड़ा है जो अधिकांश अभिव्यक्तियों को निष्पादित करने में सक्षम हो।
  • तुम भी, मान सकते हैं कि रिक्ति उदाहरणों की तरह हो जाएगा शुरुआत और इनपुट के अंत में या एक से पहले कोई रिक्त स्थान यानी λया .एक के बाद और वास्तव में एक अंतरिक्ष .और और एक समारोह और उसके तर्क के बीच एक के बाद λ

नमूना इनपुट और आउटपुट

  • इनपुट: ((λ x. x) (λ y. (λ z. z)))

    आउटपुट: (λ y. (λ z. z))

  • इनपुट: (λ x. ((λ y. y) x))

    आउटपुट: (λ x. x)

  • इनपुट: ((λ x. (λ y. x)) (λ a. a))

    आउटपुट: (λ y. (λ a. a))

  • इनपुट: (((λ 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)))

    आउटपुट: कुछ भी (यह एक ऐसी अभिव्यक्ति का उदाहरण है जिसका कोई सामान्य रूप नहीं है)

  • इनपुट: (((λ x. (λ y. x)) (λ a. a)) ((λx. (x x)) (λx. (x x))))

    आउटपुट: (λ a. a)(यह एक अभिव्यक्ति का एक उदाहरण है जो सामान्य नहीं होता है यदि आप फ़ंक्शन कॉल से पहले तर्कों का मूल्यांकन करते हैं, और दुख की बात है कि एक उदाहरण जिसके लिए मेरा प्रयास समाधान विफल हो जाता है)

  • इनपुट: ((λ a. (λ b. (a (a (a b))))) (λ c. (λ d. (c (c d)))))

    आउटपुट: `(λ a. (λ b. (a (a (a (a (a (a (a (a b)))))))))) यह चर्च के अंकों में 2 ^ 3 की गणना करता है।


1
क्या हम यह मान सकते हैं कि स्ट्रिंग के लिए प्रीपेड या अपीयरेड व्हाट्सएप नहीं होगा और वह व्हाट्सएप अन्यथा नमूना इनपुट में निर्दिष्ट है? यही है, डॉट और पैरामीटर नाम और व्हॉट्सएप के अन्य उदाहरणों के बीच कोष्ठक के बीच कोई व्हाट्सएप बिल्कुल 1 स्थान नहीं है।
JPvdMerwe

@JPvdMerwe: हाँ, अच्छी बात है, आप यह मान सकते हैं।
sepp2k

क्या कोई मुफ्त चर हैं? मेरा मतलब है कि अभिव्यक्ति की तरह एक लंबोदर द्वारा चर (\y. a)
फ़ूजएक्सएक्सएल

3
यहां से कई या सभी समाधान कैप्चर से बचने वाले प्रतिस्थापन को लागू करने में विफल होते हैं! आपको एक परीक्षण मामला जोड़ना चाहिए (जैसे (λ f। (Λ x। (Fx))) (λ y। (Λ x। Y))), जिसका मूल्यांकन (λ x। (Λ z। X)) से होना चाहिए। नहीं (λ x। (λ x। x))।
एंडर्स केसॉर्ग

1
@ sepp2k क्या आपने एक परीक्षण मामले के रूप में (λ f। (λ x। (fx))) (λ y। (λ x। y)) को जोड़ने पर विचार किया है और वर्तमान उत्तर को अस्वीकार कर दिया है जो गलत तरीके से (λ x) (λ x) बनाता है। x। x))?
एंडर्स कासोर्ग

जवाबों:


36

नवीनतम:

मैंने इसे 644 चार्ट तक निचोड़ा है , मैंने cEpy और Par में cEll के कुछ हिस्सों को फैक्टर किया है; सेल के लिए कैश्ड कॉल और अस्थायी स्थानीय चर में सीडीआर, और उन स्थानीय चर को "" (यानी गैर-पुनरावर्ती) कार्यों में ग्लोबल्स में स्थानांतरित कर दिया। इसके अलावा, दशमलव स्थिरांक चरित्र शाब्दिक और इस बुरा व्यवसाय से कम होते हैं ...

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

इससे पहले:

क्या मुझे प्रयास के लिए कुछ वोट मिल सकते हैं? मैं एक सप्ताह के लिए इस दिन और रात पर काम कर रहा हूं। मैंने मूल मैक्कार्थी पेपर को खोद लिया और पॉल ग्रैहम के द रूट्स ऑफ़ लिस्प में परिशिष्ट को पढ़ने तक पेपर में ही एक बग से ग्रस्त हो गया । मैं इतना विचलित हो गया कि मैंने अपने घर से बाहर ताला लगा दिया, फिर उस रात 12:30 बजे घर लौटने तक पूरी तरह से भूल गया (काउंटी में बाहर रहने वाले बिल्डिंग मैनेजर को फोन करने में थोड़ी देर हो गई), और खर्च करना पड़ा मेरी दादी की रात (मेरे लैपटॉप की बैटरी के सूखने तक दूर हो जाना)।

और उस सब के बाद, यह जीतने वाली प्रविष्टि के करीब भी नहीं है!

मुझे यकीन नहीं है कि इसे कैसे भी छोटा बना दिया जाए; और मैंने उन सभी गंदे चालों का उपयोग किया है जिनके बारे में मैं सोच सकता हूँ! शायद यह सी में नहीं किया जा सकता है।

मतगणना में कुछ उदारता के साथ (पहला हिस्सा एक स्ट्रिंग लेता है और परिणाम को प्रिंट करता है), यह 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मुक्त स्थान में 'नया' या 'अगला' पॉइंटर है। लेकिन कभी-कभी मैं मेमोरी में एक स्ट्रिंग लिखता हूं, फिर स्ट्रलेन और वेतन वृद्धि n; प्रभावी ढंग से मेमोरी का उपयोग करना और फिर इसे आवंटित करना, आकार की गणना के बाद आसान है। आप यह देख सकते हैं कि मैककार्थी पेपर से यह बहुत सीधा है, इसके अलावा 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;
}

1
मुझे एक चरित्र या दो को बचाने के लिए कुछ और तरकीबें मिलीं, लेकिन कट्टरपंथी कुछ भी नहीं। सरणी सिंटैक्स sprintf(n,...);n+=strlen(n)+1;को बेहतर बनाने के बजाय मुझे सभी अप्रत्यक्षों को एक 'पोस्टफिक्स' मैक्रो के साथ बदलने की अनुमति है ... जो 1 चार्ट को बचाता है और टोकन को अलग करने के लिए व्हाट्सएप आवश्यक होने के बाद "फ्री" लाइन ब्रेक देता है। n+=sprintf(n,...)+1;x[m]m[x]#define M [m]x M
लूजर ने

IOCCC 1989 से इसके और jar.2 xlisp 4.0 के साथ कुछ समानताएं प्रतीत होती हैं
लूजर ने

मैंने इसे एक फुलर लिस्प दुभाषिया में विस्तारित करने की कोशिश की
लूसर ड्रोग

यह कोड // um ...स्ट्रिंग के माध्यम से लूपिंग कर रहा है और कोष्ठक की गणना कर रहा है, जब तक कि यह सही घोंसले के स्तर पर मेल खाने वाले क्लोज-पार्न को न पा ले।
लूज़र ने

1
यह गलत तरीके से ((\ f। (\ X। (Fx))) (\ y। (\ X। Y))) से (\ x। (Fx)) का मूल्यांकन करता है।
एंडर्स कासोर्ग

22

बाइनरी लैम्ब्डा कैलकुलस 186

कार्यक्रम नीचे हेक्स डंप में दिखाया गया है

00000000  18 18 18 18 18 18 44 45  1a 10 18 18 45 7f fb cf  |......DE....E...|
00000010  f0 b9 fe 00 78 7f 0b 6f  cf f8 7f c0 0b 9f de 7e  |....x..o.......~|
00000020  f2 cf e1 b0 bf e1 ff 0e  6f 79 ff d3 40 f3 a4 46  |........oy..@..F|
00000030  87 34 0a a8 d0 80 2b 0b  ff 78 16 ff fe 16 fc 2d  |.4....+..x.....-|
00000040  ff ff fc ab ff 06 55 1a  00 58 57 ef 81 15 bf bf  |......U..XW.....|
00000050  0b 6f 02 fd 60 7e 16 f7  3d 11 7f 3f 00 df fb c0  |.o..`~..=..?....|
00000060  bf f9 7e f8 85 5f e0 60  df 70 b7 ff ff e5 5f f0  |..~.._.`.p...._.|
00000070  30 30 6f dd 80 5b b3 41  be 85 bf ff ca a3 42 0a  |00o..[.A......B.|
00000080  c2 bc c0 37 83 00 c0 3c  2b ff 9f f5 10 22 bc 03  |...7...<+...."..|
00000090  3d f0 71 95 f6 57 d0 60  18 05 df ef c0 30 0b bf  |=.q..W.`.....0..|
000000a0  7f 01 9a c1 70 2e 80 5b  ff e7 c2 df fe e1 15 55  |....p..[.......U|
000000b0  75 55 41 82 0a 20 28 29  5c 61                    |uUA.. ()\a|
000000ba

आप जिस प्रारूप का प्रस्ताव देते हैं, उसे स्वीकार नहीं करता है। बल्कि, यह बाइनरी लैम्ब्डा कैलकुलस (blc) प्रारूप में एक लैम्ब्डा शब्द की अपेक्षा करता है। हालांकि, यह न्यूनतम कोष्ठक का उपयोग करके सामान्य रूप में कमी में हर एक कदम दिखाता है।

उदाहरण: चर्च अंकों में 2 ^ 3 की गणना

Xxd -r> प्रतीकात्मक.ब्लॉक के साथ उपरोक्त हेक्स डंप सहेजें

से एक blc दुभाषिया पकड़ो http://tromp.github.io/cl/uni.c

cc -O2 -DM=0x100000 -m32 -std=c99 uni.c -o uni
echo -n "010000011100111001110100000011100111010" > threetwo.blc
cat symbolic.Blc threetwo.blc | ./uni
(\a \b a (a (a b))) (\a \b a (a b))
\a (\b \c b (b c)) ((\b \c b (b c)) ((\b \c b (b c)) a))
\a \b (\c \d c (c d)) ((\c \d c (c d)) a) ((\c \d c (c d)) ((\c \d c (c d)) a) b)
\a \b (\c (\d \e d (d e)) a ((\d \e d (d e)) a c)) ((\c \d c (c d)) ((\c \d c (c d)) a) b)
\a \b (\c \d c (c d)) a ((\c \d c (c d)) a ((\c \d c (c d)) ((\c \d c (c d)) a) b))
\a \b (\c a (a c)) ((\c \d c (c d)) a ((\c \d c (c d)) ((\c \d c (c d)) a) b))
\a \b a (a ((\c \d c (c d)) a ((\c \d c (c d)) ((\c \d c (c d)) a) b)))
\a \b a (a ((\c a (a c)) ((\c \d c (c d)) ((\c \d c (c d)) a) b)))
\a \b a (a (a (a ((\c \d c (c d)) ((\c \d c (c d)) a) b))))
\a \b a (a (a (a ((\c (\d \e d (d e)) a ((\d \e d (d e)) a c)) b))))
\a \b a (a (a (a ((\c \d c (c d)) a ((\c \d c (c d)) a b)))))
\a \b a (a (a (a ((\c a (a c)) ((\c \d c (c d)) a b)))))
\a \b a (a (a (a (a (a ((\c \d c (c d)) a b))))))
\a \b a (a (a (a (a (a ((\c a (a c)) b))))))
\a \b a (a (a (a (a (a (a (a b)))))))

चूंकि हेक्सडंप अपठनीय है, इसलिए यहां एक "डिस्सैम्बल्ड" संस्करण है

@10\\@10\\@10\\@10\\@10\\@10\@\@\@\@@\@1010\@\\\@10\\@10\@\@@@1111111111101
1110@11111110\@@110@11111110\\\\@1110\@1111110\@@101101111110@111111110\@111
111110\\\\@@110@111111011110@11111011110@@10@1111110\@10110\@@111111110\@111
111110\@110@101111011110@1111111111010@1010\\@1110@11010@\@\@1010\@110@1010\
\@@@@@\@1010\@\\\\@@@10\@@111111111011110\\@@101111111111111110\@@101111110\
@@10111111111111111111111110@@@@1111111110\\110@@@@\@1010\\\\@@10\@@@1111101
11110\\@\@@@10111111101111110\@@1011011110\\@@11111010110\\@111110\@@1011110
1110@111010\10\1011111110@111110\\\@101111111111011110\\@@11111111110@@11111
0111110\10\@@@@11111110\\@10\\1101111101110\@@1011111111111111111111110@@@@1
11111110\\@10\\@10\\11011111101110110\\\@@101110110@1010\\11011111010\@@1011
111111111111110@@@@\@1010\@\\@@@10\@@@1110@10\\\@1011110\\110\\\@10\\\@1110\
@@@11111111110@1111111101010\10\\@\@@@1110\\\@10@1110111110\\1110\110@@@1111
0110@@@1111010\\110\\\@10\\\@@1101111111101111110\\\@10\\\@@1101111110111111
10\\\110@1010110\\101110\\@@11010\\\@@1011111111111110@11110\@@1011111111111
101110\@\@@@@@@@@11010101010101010\\110\\10\\1010\10\\\1010\\1010@@@110\110\
@

@ के साथ \ _ और 01 (आवेदन) के साथ 00 (लैम्ब्डा) की जगह अब यह लगभग ब्रेनफुक के रूप में पठनीय है :-)

Http://www.ioccc.org/2012/tromp/hint.html भी देखें


7
BLC सिर्फ एक द्विआधारी वर्णमाला का उपयोग करने के लिए होता है। 00 लंबोदर है, 01 आवेदन है, और 1 ^ {n} 0 एक वैरिएबल है। इसमें कोई संकलन शामिल नहीं है।
जॉन ट्रम्प

3
आपको एक कारक x3 कहां मिलेगा? आप वास्तव में उस भाषा में एक अच्छा बिंदु उठाते हैं जिसमें बीएफ जैसे छोटे स्रोत अक्षर होते हैं। निष्पक्ष तुलना के लिए, सभी आकारों को बिट्स में व्यक्त किया जाना चाहिए, और बीएफ अक्षर केवल 3 बिट्स लेते हैं। अधिकांश अन्य भाषाओं में एएससीआईआई के लिए 7 बिट्स की आवश्यकता होती है, कुछ सभी 8 का उपयोग करते हैं।
जॉन ट्रम्प

1
BTW +1 यह बहुत अच्छा है!
लूज़र ने

1
यदि फ्रैक्चर में फ्रैक्चर स्वीकार्य है, तो मैं यह नहीं देखता कि यह समस्या क्यों होनी चाहिए। आप इसे नहीं पढ़ सकते हैं? आप चाहते हैं कि? जानें!
लूसर ने

1
वास्तविक इनपुट प्रारूप को पढ़ने के लिए इसे क्या करना होगा? मुझे लगता है कि जहाँ आप संभावित उतार चढ़ाव खो रहे हैं।
लूजर ने

14

हास्केल, 342 323 317 305 वर्ण

इस लेखन के रूप में, यह एकमात्र समाधान है जो (λ f। (Λ x। (Fx))) (λ y। (Λ x। Y)) का सही परिणाम (λ x।) (Λ z) का मूल्यांकन करता है। x)) के बजाय (λ x। (λ x। x))। लैम्ब्डा कैलकुलस के सही क्रियान्वयन के लिए कैप्चर से बचने वाले प्रतिस्थापन की आवश्यकता होती है , यहां तक ​​कि इस समस्या के सरलीकरण की गारंटी के तहत कि कोई भी वैरिएबल इसके स्कोप में दूसरे वेरिएबल को छाया नहीं देता है। (मेरा कार्यक्रम इस गारंटी के बिना भी काम करने के लिए होता है।)

data T=T{a::T->T,(%)::ShowS}
i d=T(i. \x v->'(':d v++' ':x%v++")")d
l f=f`T`\v->"(λ "++v++". "++f(i(\_->v))%('x':v)++")"
(?)=q.lex
q[(v,s)]k|v/="("=k(maybe T{}id.lookup v)s|'λ':u<-s,[(w,_:t)]<-lex u=t? \b->k(\e->l$b.(:e).(,)w).tail|0<1=s? \f->(?(.tail).k. \x z->f z`a`x z)
main=interact(? \f->(f[]%"x"++))

टिप्पणियाँ:

  • यह आवश्यकतानुसार GHC 7.0 में चलता है, क्योंकि यह चुनौती जनवरी 2011 में निर्धारित की गई थी। यदि मुझे GHC 7.10 मानने की अनुमति दी गई थी, तो यह 13 वर्णों से कम होगी ।

प्रलेखन के साथ अनगुल्ड संस्करण


इनपुट ((\ x। x) (\ y। (\ z। z)) के लिए ideone हैस्केल कंपाइलर में आपका प्रोग "in (\\ x। x) (\\ y।" \\ z। z)))) हास्केल में "लेक्स" का क्या मतलब है?
RosLuP

2
@RosLuP मेरा प्रोग्राम λ को स्वीकार करता है, \ _ को नहीं।
एंडर्स केसॉर्ग

ideone.com रिटर्न में इस imput ((λ x। x) (λ y। (λ z। z)) को टाइप करें: रनटाइम त्रुटि समय: 0 मेमोरी: 4876 सिग्नल: -1
RosLuP

1
@RosLuP Ideone ने यूनिकोड समर्थन को तोड़ दिया है। कमांड लाइन या किसी अन्य ऑनलाइन दुभाषिए की कोशिश करें (यह Rextester पर काम करता है , उदाहरण के लिए)।
एंडर्स कासोर्ग सेप

2
@codeshot प्रश्न लेखक ने पहले ही टिप्पणी कर दी है कि ((λ f। (λ x। (fx))) (λ y। (λ x। y))) ↦ (λ x। (λ z। x)) के लिए सही है। यह समस्या (असली लैम्ब्डा कैलकुलस की तरह)।
एंडर्स कासोर्ग

13

पायथन - 321 320

यहाँ मेरा (निश्चित) प्रयास है:

l="("
def S(s):
 if s[0]!=l:return s
 if s[1]=="\\":g=s.find('.');return"(\\ %s. %s)"%(s[3:g],S(s[g+2:-1]))
 i=2;c=s[1]==l
 while c:c+=(s[i]==l)-(s[i]==')');i+=1
 t=S(s[1:i])
 z=s[i+1:-1]
 if l!=t[0]:return"(%s %s)"%(t,S(z))
 g=t.find('.')
 t=S(t[g+2:-1]).replace(t[3:g],z)
 if t!=s:t=S(t)
 return t
print S(raw_input())

यह अच्छा लग रहा है, लेकिन काम करने के लिए प्रतीत नहीं होता है। मैंने कुछ उदाहरण इनपुट और आउटपुट जोड़े हैं, जिसके लिए आपका कोड गलत परिणाम उत्पन्न करता है।
sepp2k

1
यह कैप्चर से बचने के लिए प्रतिस्थापन करने में विफल रहता है। उदाहरण के लिए, ((\ f। (\ X। (Fx))) (\ y। (\ X। Y))) गलत तरीके से (\ x। (\ X। X)) का मूल्यांकन करता है।
एंडर्स केसॉर्ग

1
जब यह मुश्किल से काम कर रहा है तो इसे एक उत्तर के रूप में क्यों चिह्नित किया गया है? क्या आपने लेखक द्वारा दिए गए इनपुट और आउटपुट की कोशिश की है?
rbaleksandar

1
लेखक के प्रदान किए गए परीक्षण मामले इस उत्तर में बग को प्रदर्शित करने के लिए अपर्याप्त हैं।
एंडर्स कासोर्ग

1
यह उत्तर न तो सही है और न ही सबसे छोटा। यह कब्जा से बचने में विफल रहता है और स्ट्रिंग प्रतिस्थापन कीड़े हैं।
रिचर्ड पैडले

6

रूबी 254 अक्षर

f=->u,r{r.chars.take_while{|c|u+=c==?(?1:c==?)?-1:0;u>0}*''}
l=->x{x=~/^(\(*)\(\\ (\w+)\. (.*)/&&(b,v,r=$1,$2,$3;e=f[1,r];(e==s=l[e])?b==''?x:(s=f[2,r];(x==y=b.chop+e.gsub(v,s[2+e.size..-1])+r[1+s.size..-1])?x:l[y]):(b+'(\\ '+v+'. '+s+r[e.size..-1]))||x}

इसका उपयोग किया जा सकता है

puts l["((\\ x. (\\ y. x)) (\\ a. a))"]    # <= (\ y. (\ a. a))

समाधान अभी तक पूरी तरह से गोल्फ नहीं है, लेकिन पहले से ही लगभग अपठनीय है।


हैलो ईर्ष्या, मेरे पुराने दोस्त :)
luser droog

यह कैप्चर से बचने के लिए प्रतिस्थापन करने में विफल रहता है। उदाहरण के लिए, ((\ f। (\ X। (Fx))) (\ y। (\ X। Y))) गलत तरीके से (\ x। (\ X। X)) का मूल्यांकन करता है।
एंडर्स कासोर्ग

उपरोक्त कैप्चर बग के अलावा, यह गलत तरीके से (\ y। (\ Xx? ((\ X। Xx) y)))) से (\ y। (\ Xx। Yy)) का भी मूल्यांकन करता है, जहां अतिरंजित स्ट्रिंग हस्तक्षेप का निर्माण किया गया है। कोई नहीं चर yy।
एंडर्स कासोर्ग

3

संपादित करें: शुद्ध जावास्क्रिप्ट के तहत 250 के लिए नीचे मेरे जवाब की जाँच करें।

LiveScript (नो रेगेक्स का उपयोग करके 2852 243 वर्ण! पूरी तरह से गोल्फ नहीं - बेहतर किया जा सकता है)

L=(.0==\\)
A=->it.forEach?&&it.0!=\\
V=(.toFixed?)
S=(a,b,t=-1,l=0)->|L a=>[\\,S(a.1,b,t,l+1)];|A a=>(map (->S(a[it],b,t,l)),[0 1]);|a==l+-1=>S(b,0,l+-1,0)||a|l-1<a=>a+t;|_=>a
R=(a)->|L a=>[\\,R a.1]|(A a)&&(L a.0)=>R(S(R(a.0),R(a.1)).1)|_=>a

परीक्षा:

a = [\\,[\\,[1 [1 0]]]]
b = [\\,[\\,[1 [1 [1 0]]]]]
console.log R [a, b]
# outputs ["\\",["\\",[1,[1,[1,[1,[1,[1,[1,[1,[1,0]]]]]]]]]]]

जो 3^2=9, जैसा कि ओपी पर कहा गया है।

यदि कोई उत्सुक है, तो यहां कुछ टिप्पणियों के साथ एक विस्तारित संस्करण है:

# Just type checking
λ = 100
isλ = (.0==λ)
isA = -> it.forEach? && it.0!=λ
isV = (.toFixed?)

# Performs substitutions in trees
# a: trees to perform substitution in
# b: substitute bound variables by this, if != void
# f: add this value to all unbound variables
# l: internal (depth)
S = (a,b,t=-1,l=0) ->
    switch
    | isλ a             => [λ, (S a.1, b, t, l+1)]
    | isA a             => [(S a.0, b, t, l), (S a.1, b, t, l)]
    | a == l - 1        => (S b, 0, (l - 1), 0) || a
    | l - 1 < a < 100   => a + t
    | _                 => a

# Performs the beta-reduction
R = (a) ->
    switch
    | (isλ a)               => [λ,R a.1]
    | (isA a) && (isλ a.0)  => R(S(R(a.0),R(a.1)).1)
    | _                     => a

# Test
a = [λ,[λ,[1 [1 0]]]]
b = [λ,[λ,[1 [1 [1 0]]]]]
console.log show R [a, b]

यह समस्या से इनपुट और आउटपुट विनिर्देशों के अनुरूप नहीं है।
एंडर्स केसरग

3

वॉटरहाउस आर्क - 140 अक्षर

(=
f[is cons?&car._'λ]n[if
atom._ _
f._ `(λ,_.1,n:_.2)(=
c n:_.0
e _)(if
f.c(n:deep-map[if(is
c.1 _)e.1
_]c.2)(map n
_))]λ[n:read:rem #\._])

मुझे वाटरहाउस आर्क कहां मिल सकता है?
एंडर्स केसॉर्ग

1
एक दुभाषिया के रूप में अमान्य कहीं नहीं पाया जाता है
बिल्ली


@ ASCII- केवल मुझे पता है कि आर्क क्या है, लेकिन "वॉटरहाउस" भाग ने मुझे सुझाव दिया कि कुछ विशेष बोली आवश्यक थी। आप इसे चलाने के लिए मिल गया है?
एंडर्स कासोर्ग

@AndersKaseorg कोई बात नहीं। यह मिला
केवल

2

C 1039 बाइट्स

#define F for
#define R return
#define E if(i>=M||j>=M)R-1;
enum{O='(',C,M=3999};signed char Q[M],D[M],t[M],Z,v,*o=Q,*d=D,*T;int m,n,s,c,w,x,y;K(i,j,k){!Z&&(Z=t[O]=1)+(t[C]=-1);E;if(!o[i]){d[j]=0;R 0;}if((c=t[o[i]]+t[o[i+1]])!=2||o[i+2]!='\\'){d[j++]=o[i++];R K(i,j,i);}F(i+=2,y=w=0;i<M&&o[i]&&c;++i)c+=t[o[i]],!w&&c==1?w=i:0,!y&&o[i]=='.'?y=i+2:0;E;if(c){F(;d[j++]=o[i++];)E;R 0;}F(c=y;c<w;++c)if(o[c]=='\\')F(n=0,m=w+2;m<i;++m){if(o[m]==o[c+2]){F(x=0;o[m+x]&&isalpha(o[m+x])&&o[m+x]==o[c+2+x];++x);if(o[c+2+x]!='.'||isalpha(o[m+x]))continue;if(v>'Z')R-1;F(n=c+2;n<w;++n)if(o[n]==o[m]){F(x=0; o[m+x]&&isalpha(o[m+x])&&o[m+x]==o[n+x];++x);if(o[m+x]=='.'&&!isalpha(o[n+x]))F(;--x>=0;) o[n+x]=v;}++v;}}F(c=y;c<w&&j<M;++c){F(x=0;o[c+x]&&o[c+x]==o[k+4+x]&&isalpha(o[c+x]); ++x);if(o[k+4+x]=='.'&&!isalpha(o[c+x])){F(m=w+2;m<i-1&&j<M;++m)d[j++]=o[m];c+=x-1;}else d[j++]=o[c];}E;Z=2;R K(i,j,i);}char*L(char*a){F(s=n=0;n<M&&(o[n]=a[n]);++n);if(n==M)R 0;v='A';F(;++s<M;){Z=0;n=K(0,0,0);if(Z==2&&n!=-1)T=d,d=o,o=T;else break;}R n==-1||s>=M?0:d;}

वेरिएबल्स लोअरकेस लेटर्स [a..z] से इनपुट के रूप में अनुमति देते हैं। sys उत्पादन में आवश्यकता होने पर [A..Z] से अपरकेस अक्षरों का उपयोग करके वैरिएबल उत्पन्न कर सकते हैं ... ascii कैरेक्टर कॉन्फ़िगरेशन मान लें।

#define P printf
main()
{char  *r[]={ "((\\ abc. (\\ b. (abc (abc (abc b))))) (\\ cc. (\\ dd. (cc (cc dd)))))",
              "((\\ fa. (\\ abc. (fa abc))) (\\ yy. (\\ abc. yy)))",
              "((\\ x. x) z)", 
              "((\\ x. x) (\\ y. (\\ z. z)))", 
              "(\\ x. ((\\ y. y) x))", 
              "((\\ x. (\\ y. x)) (\\ a. a))", 
              "(((\\ 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)))",
              "(((\\ x. (\\ y. x)) (\\ a. a)) ((\\ x. (x x)) (\\ x. (x x))))",
             0}, *p;
 int    w;

 for(w=0; r[w] ;++w)
   {p=L(r[w]);
    P("o=%s d=%s\n", r[w], p==0?"Error ":p);
   }
 R  0;
}

/*1.039*/

विनिर्देशन के लिए \ या λ की आवश्यकता होती है, न कि /। इसे बहु-अक्षर चर नामों के लिए भी समर्थन की आवश्यकता होती है।
एंडर्स कासोर्ग

'\ n' इत्यादि प्रतीक '' के अन्य उपयोग हैं इसका उपयोग बेहतर है '/' के बजाय
RosLuP

1
फिर भी, चुनौती विनिर्देश को संतुष्ट करना है, न कि इसे बेहतर बनाना।
एंडर्स कासोर्ग

मैंने लिखा है कि यह थोड़ा अधिक अनुरूप होगा ... लेकिन आकार में विस्फोट ...
RosLuP


1

हास्केल 456 सी

यह बहुत कम हो सकता है यदि हास्केल का आलसी मूल्यांकन सुविधा पूरी तरह से उपयोग की जाती है। अफसोस की बात है, मुझे नहीं पता कि यह कैसे करना है।

साथ ही, बहुत से पात्र पार्सिंग चरण में बर्बाद हो जाते हैं।

data T=A[Char]|B[Char]T|C T T
(!)=(++)
s(A a)=a
s(B a b)="(λ "!a!". "!s b!")"
s(C a b)='(':s a!" "!s b!")"
e d(A a)=maybe(A a)id(lookup a d)
e d(B a b)=B a.e d$b
e d(C a b)=f d(e d a)(e d b)
f d(B x s)q=e((x,q):d)s
f d p q=C p q
d=tail
p('(':'λ':s)=let(A c,t)=p(d s);(b,u)=p(d.d$t);in(B c b,d u)
p('(':s)=let(a,t)=p s;(b,u)=p(d t)in(C a b,d u)
p(c:s)|elem c" .)"=(A "",c:s)|1<2=let((A w),t)=p s in(A(c:w),t)
r=s.e[].fst.p
main=do l<-getLine;putStrLn$r l

अनप्लग्ड संस्करण

data Expression = Literal String 
                | Lambda String Expression
                | Apply Expression Expression
                deriving Show

type Context = [(String, Expression)]

show' :: Expression -> String
show' (Literal a) = a
show' (Lambda x e) = "(λ " ++ x ++ ". " ++ show' e ++ ")"
show' (Apply e1 e2) = "(" ++ show' e1 ++ " " ++ show' e2 ++ ")"

eval :: Context -> Expression -> Expression
eval context e@(Literal a) = maybe e id (lookup a context)
eval context (Lambda x e) = Lambda x (eval context e)
eval context (Apply e1 e2) = apply context (eval context e1) (eval context e2)

apply :: Context -> Expression -> Expression -> Expression
apply context (Lambda x e) e2 = eval ((x, e2):context) e
apply context e1 e2 = Apply e1 e2

parse :: String -> (Expression, String)
parse ('(':'λ':s) = let
    (Literal a, s') = parse (tail s)
    (e, s'') = parse (drop 2 s')
    in (Lambda a e, tail s'')

parse ('(':s) = let
    (e1, s') = parse s
    (e2, s'') = parse (tail s')
    in (Apply e1 e2, tail s'')

parse (c:s) | elem c " .)" = (Literal "", c:s)
            | otherwise    = let ((Literal a), s') = parse s 
                             in (Literal (c:a), s')

run :: String -> String
run = show' . eval [] . fst . parse
main = do
  line <- getLine
  putStrLn$ run line

3
यह कैप्चर से बचने के लिए प्रतिस्थापन करने में विफल रहता है। उदाहरण के लिए, ((λ f। (Λ x। (Fx))) (λ y। (Λ x। Y))) गलत तरीके से (λ x। (Λ x। X)) का मूल्यांकन करता है।
एंडर्स कासोर्ग

1

जावास्क्रिप्ट के साथ 231 मिला / कोई रेगेक्स नहीं

(function f(a){return a[0]?(a=a.map(f),1===a[0][0]?f(function d(b,a,e,c){return b[0]?1===b[0]?[1,d(b[1],a,e,c+1)]:2===b[0]?b[1]===c-1?d(a,0,c-1,0)||b:c-1<b[1]?[2,b[1]+e]:b:[d(b[0],a,e,c),d(b[1],a,e,c)]:b}(a[0],a[1],-1,0)[1]):a):a})

2-तत्व सरणियाँ प्राप्त करता है। 1के लिए खड़ा हैλ और 2 एक ब्रूजन सूचकांक चर के लिए खड़ा है।

परीक्षा:

zero = [1,[1,[2,0]]]; // λλ0
succ = [1,[1,[1,[[2,1],[[[2,2],[2,1]],[2,0]]]]]]; // λλλ(1 ((2 1) 0))
console.log(JSON.stringify(reduce([succ,[succ,[succ,zero]]]))); // 0+1+1+1
// Output: [1,[1,[[2,1],[[2,1],[[2,1],[2,0]]]]]] = λλ(1(1(1 0))) = number 3

यह समस्या से इनपुट और आउटपुट विनिर्देशों के अनुरूप नहीं है।
एंडर्स कासोर्ग

1

पायथन: 1266 वर्ण (wc का उपयोग करके मापा गया)

from collections import *;import re
A,B,y,c=namedtuple('A',['l','r']),namedtuple('B',['i','b']),type,list.pop
def ab(t):c(t,0);p=c(t,0);c(t,0);return B(p,tm(t))
def tm(t):return ab(t)if t[0]=='\\'else ap(t)
def at(t):
    if t[0]=='(':c(t,0);r=tm(t);c(t,0);return r
    if 96<ord(t[0][0])<123:return c(t,0)
    if t[0]=='\\':return ab(t)
def ap(t):
    l = at(t)
    while 1:
        r = at(t)
        if not r:return l
        l = A(l,r)
def P(s):return tm(re.findall(r'(\(|\)|\\|[a-z]\w*|\.)',s)+['='])
def V(e):o=y(e);return V(e.b)-{e.i} if o==B else V(e.l)|V(e.r)if o==A else{e}
def R(e,f,t):return B(e.i,R(e.b,f,t)) if y(e)==B else A(R(e.l,f,t),R(e.r,f,t))if y(e)==A else t if e==f else e
def N(i,e):return N(chr(97+(ord(i[0])-96)%26),e) if i in V(e)else i
def S(i,e,a): return A(S(i,e.l,a),S(i,e.r,a)) if y(e)==A else(e if e.i==i else B(N(e.i,a),S(i,R(e.b,e.i,N(e.i,a)),a)))if y(e)==B else a if e==i else e
def T(e):
    if y(e)==A:l,r=e;return S(l.i,l.b,r)if y(l)==B else A(T(l),r)if y(l)==A else A(l,T(r))
    if y(e)==B:return B(e.i,T(e.b))
    q
def F(e):o=y(e);return r'(\%s. %s)'%(e.i,F(e.b))if o==B else'(%s %s)'%(F(e.l),F(e.r)) if o==A else e
def E(a):
    try: return E(T(a))
    except NameError:print(F(a))
E(P(input()))

लंबे शॉट द्वारा कम से कम नहीं, लेकिन यह अल्फा-रीनेमिंग और ओप्स पोस्ट में सूचीबद्ध सभी उदाहरणों को सही ढंग से संभालता है।


आप उन फ़ंक्शन नामों में से कुछ को छोटा कर सकते हैं, और उनमें से कुछ को लैम्ब्डा में बदल सकते हैं। आपके पास कुछ अतिरिक्त व्हाट्सएप भी हैं यहां
जो राजा

(1) 4-स्पेस इंडेंटेशन को सिंगल स्पेस के साथ बदलने से काफी बाइट्स बचेंगे। (२) क्या आप except NameErrorबस के साथ बदल सकते हैं except? (3) दो-चरित्र फ़ंक्शन नामों को एक-वर्ण नामों में बदला जा सकता है। (४) कुछ ऐसे स्थान हैं जहाँ आपके पास असाइनमेंट हैं जिनके चारों ओर रिक्त स्थान हैं =। (5) if t[0]=='c'से बदला जा सकता है if'c'==t[0]
फलों को तोड़ना

1045 बाइट्स इंडेंटेशन और लैम्ब्डा जैसे ज्यादातर फॉर्मेटिंग परिवर्तनों के माध्यम से
जो किंग

0

C ++ (gcc) ,782 766 758 731 बाइट्स

#include <string>
#include <map>
#define A return
#define N new E
using S=std::string;using C=char;using I=int;S V(I i){A(i>8?V(i/9):"")+C(97+i%9);}S W(C*&s){C*b=s;while(*++s>96);A{b,s};}struct E{I t,i;E*l,*r;E(E&o,I d,I e){t=o.t;i=o.i+(o.i>=d)*e;t?l=N{*o.l,d,e},t-1?r=N{*o.r,d,e}:0:0;}E(I d,std::map<S,I>m,C*&s){t=*s-40?i=m[W(s)],0:*++s-92?l=N{d,m,s},r=N{d,m,++s},++s,2:(m[W(s+=2)]=d,l=N{d+1,m,s+=2},++s,1);}I R(I d){A t?t-1?l->t==1?l->l->s(d,0,*r),*this=*l->l,1:l->R(d)||r->R(d):l->R(d+1):0;}I s(I d,I e,E&v){t?t-1?l->s(d,e,v),r->s(d,e,v):l->s(d,e+1,v):i==d?*this={v,d,e},0:i-=i>d;}S u(I d){A t?t-1?S{"("}+l->u(d)+' '+r->u(d)+')':S{"(\\ "}+V(d)+". "+l->u(d+1)+')':V(i);}};S f(C*s){E a{0,{},s};for(I c=999;a.R(0)&&c--;);A a.u(0);}

इसे ऑनलाइन आज़माएं!

यहां मूल विचार यह है कि कोड डी ब्रूजन सूचकांकों के विचार के आधार पर एक आंतरिक प्रतिनिधित्व का उपयोग करता है - सिवाय इसके कि मैं संदर्भित चर के बंधन की लंबो-गहराई को इंगित करने के लिए सूचकांकों को उल्टा करता हूं। कोड में:

  • E::tएक नोड पत्ता नोड के लिए नोड - 0 के प्रकार का प्रतिनिधित्व करता है, एक लैम्ब्डा नोड के लिए 1, और एक फ़ंक्शन एप्लिकेशन नोड के लिए 2। (चुना ताकि यह नोड की समता के साथ मेल खाता है, जो बस संभव होने के लिए होता है।) फिर E::lऔर E::rक्या बच्चे उपयुक्त हैं (सिर्फ E::lएक लंबो नोड के लिए), और E::iएक चर पत्ती नोड के लिए लंबो-डेप्थ इंडेक्स है।
  • कंस्ट्रक्टर E::E(E&o,int d,int e)एक उपसंचाई क्लोन करता है जो शुरू में लैम्ब्डा-डेप्थ dमें एक नए स्थान में चिपकाने के लिए लैम्ब्डा-डेप्थ में था d+e। यह कम से कम लैम्ब्डा गहराई में चर संरक्षण शामिल है d, जबकि कम से कम लैम्ब्डा गहराई में चर incrementing dद्वारा e
  • E::svचर संख्या dमें सब- डेप्रेशन का प्रतिस्थापन करता है *thisजबकि परिवर्तनीय संख्याओं से अधिक घटाता है d(और eजब इसे कॉल करने की आवश्यकता होती है तो लैम्बडा-डेप्थ इंक्रीमेंट पर नज़र रखने वाला एक आंतरिक विवरण है E::c)।
  • E::Rएएसटी के माध्यम से पूर्व-ऑर्डर खोज के अनुसार शीर्ष-सबसे या बाएं-सबसे उदाहरणों को प्राथमिकता देने के लिए एकल बीटा-कमी की खोज। यदि यह कोई प्रदर्शन नहीं करता है या शून्य पाया जाता है तो यह नॉनज़रो लौटाता है।
  • E::uएक to_stringप्रकार का ऑपरेशन है जो चर के लिए सिंथेटिक नामों का उपयोग करके "मानव पठनीय" स्ट्रिंग को पुनर्गठित करता है। (नोट उसकी वजह से एक छोटे से गोल्फ की Vसहायक समारोह यह केवल नाम शामिल उत्पन्न होगा aके माध्यम से i।)
  • कंस्ट्रक्टर E::E(int d, std::map<std::string, int> m, char*&s)एक इनपुट स्ट्रिंग की पार्सिंग करता है जो वर्तमान में बंधे हुए चर नामों को लैम्ब्डा-डेप्थ मसालों की sमैपिंग mके आधार पर एएसटी में बनाता है।
  • f प्रश्न का उत्तर देने वाला मुख्य कार्य है।

(जैसा कि आप TIO लिंक पर देख सकते हैं, कोड कई पात्रों के साथ संभाल चर नाम करता है, और यह भी की एक सही जवाब हो जाता है (\ a. (\ b. a))के लिए ((\ f. (\ x. (f x))) (\ y. (\ x. y)))। यह भी सिर्फ इतना है कि पार्स कोड कोई अतिरिक्त कीमत पर चर छाया संभाल कर सकते हैं।)


-16 ceilingcat द्वारा विचार (जो मैं भी स्वतंत्र रूप से साथ आया था) की वजह से आंशिक रूप से बाइट्स, और आंशिक रूप से बदलने के E*a=new E;लिए E&a=*new E;और उसके बाद बदल रहा है a->करने के लिएa.

सीलिंग द्वारा एक और टिप्पणी के कारण -8 और बाइट्स ( a.tटर्नरी से फैक्टर असाइनमेंट )

-27 बाइट्स को पार्सर और क्लोन को कंस्ट्रक्टर्स में परिवर्तित करने से E


-1

C 637 बाइट्स

#define R return
#define E if(i>=M||j>=M)R-1;
#define H d[j++]
enum{O=40,C,M=3999};signed char Q[M],D[M],t[M],Z,*o=Q,*d=D,*T;int m,n,s,c,w;K(i,j,k){!Z&&(Z=t[O]=1)+(t[C]=-1);E;if(!o[i]){H=0;R 0;}if((c=t[o[i]]+t[o[i+1]])!=2||o[i+2]!=92){H=o[i++];R K(i,j,i);}for(i+=2,w=0;i<M&&o[i]&&c;++i)c+=t[o[i]],!w&&c==1?w=i:0;E;if(c){for(;H=o[i++];)E;R 0;}for(c=k+7,n=j;c<w&&j<M;++c)if(o[c]==o[k+4]){if(o[c+1]==46){d[n++]=o[k++];R K(k,n,k);}for(m=w+2;m<i-1&&j<M;)H=o[m++];}else H=o[c];E;Z=2;R K(i,j,i);}char*L(char*a){for(s=n=0;n<M&&(o[n]=a[n]);++n);if(n==M)R 0;for(;++s<M;){Z=0;if((n=K(0,0,0))!=-1&&Z==2)T=d,d=o,o=T;else break;}R n==-1||s>=M?0:d;}

यह संस्करण सहायक चर का उपयोग नहीं करता है (इसलिए यह 100% का पालन नहीं करता है जो लैम्ब्डा कैलकुलस कहता है ... जितना कि यहां अन्य ...)। प्रत्येक चर को 1 वर्णकारक लंबा होना चाहिए (कुछ अन्य के रूप में यहां)। टेस्ट कोड:

#define P printf

main()
{char  *r[]={ "((\\ x. x) z)", 
              "((\\ x. x) (\\ y. (\\ z. z)))", 
              "(\\ x. ((\\ y. y) x))", 
              "((\\ x. (\\ y. x)) (\\ a. a))", 
              "(((\\ 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)))",
              "(((\\ x. (\\ y. x)) (\\ a. a)) ((\\ x. (x x)) (\\ x. (x x))))",
              "((\\ a. (\\ b. (a (a (a b))))) (\\ c. (\\ d. (c (c d)))))",
              "((\\ f. (\\ x. (f x))) (\\ y. (\\ x. y)))",
             0}, *y;
 int    w;

 for(w=0; r[w] ;++w)
   {y=L(r[w]);
    P("o=%s d=%s\n", r[w], y==0?"Error ":y);
   }
 R  0;
}

परिणाम:

/*
637
o=((\ x. x) z) d=z
o=((\ x. x) (\ y. (\ z. z))) d=(\ y. (\ z. z))
o=(\ x. ((\ y. y) x)) d=(\ x. x)
o=((\ x. (\ y. x)) (\ a. a)) d=(\ y. (\ a. a))
o=(((\ x. (\ y. x)) (\ a. a)) (\ b. b)) d=(\ a. a)
o=((\ x. (\ y. y)) (\ a. a)) d=(\ y. y)
o=(((\ x. (\ y. y)) (\ a. a)) (\ b. b)) d=(\ b. b)
o=((\ x. (x x)) (\ x. (x x))) d=Error
o=(((\ x. (\ y. x)) (\ a. a)) ((\ x. (x x)) (\ x. (x x)))) d=(\ a. a)
o=((\ a. (\ b. (a (a (a b))))) (\ c. (\ d. (c (c d))))) d=(\ b. (\ d. (b (b (b (b (b (b (b (b d))))))))))
o=((\ f. (\ x. (f x))) (\ y. (\ x. y))) d=(\ x. (\ x. x))
*/

यह अर्ध अनगलक है:

#define R return
#define E if(i>=M||j>=M)R-1;
#define H d[j++]
enum{O=40,C,M=3999}; // assume ascii
signed char Q[M],D[M],t[M],Z,*o=Q,*d=D,*T;
int m,n,s,c,w;

K(i,j,k)
{!Z&&(Z=t[O]=1)+(t[C]=-1); //inizializza tabelle

 E;if(!o[i]){H=0;R 0;}
 if((c=t[o[i]]+t[o[i+1]])!=2||o[i+2]!=92)
      {H=o[i++]; R K(i,j,i);}
 for(i+=2,w=0;i<M&&o[i]&&c;++i)
         c+=t[o[i]],!w&&c==1?w=i:0;
 E;
 if(c){for(;H=o[i++];)E;R 0;} 
//  01234567w12 i
//  ((/ x. x) z)
//   x                 w              z
// o[k+4]..o[k+5];  o[k+7]..o[w];  o[w+2]..o[i-1]

// sostituzione
// sostituisce a x z in w e lo scrive in d
for(c=k+7,n=j;c<w&&j<M;++c)
      if(o[c]==o[k+4])
         {if(o[c+1]==46) // non puo' sostituire una variabile dove c'e' lambda
             {d[n++]=o[k++]; R K(k,n,k);}
          for(m=w+2;m<i-1&&j<M;++m)
                H=o[m];
         }
      else H=o[c];
 E;
 Z=2;
 R K(i,j,i);
}

char*L(char*a)
{for(s=n=0;n<M&&(o[n]=a[n]);++n);
 if(n==M)R 0;
 for(;++s<M;)
   {Z=0;
    n=K(0,0,0);
//    if(Z==2)printf("n=%d>%s\n", n, d);
    if(Z==2&&n!=-1)T=d,d=o,o=T;
    else break;
   }
 R n==-1||s>=M?0:d; 
}

विनिर्देशन में \ या λ की आवश्यकता होती है, न कि /। इसे बहु-अक्षर चर नामों के लिए भी समर्थन की आवश्यकता होती है। इसके अतिरिक्त (मुझे पता है कि आप इसके बारे में जानते हैं, लेकिन हाँ, यह अभी भी गलत है), यह गलत तरीके से मूल्यांकन करता है ((/ / (? / X (fx))) (/ y। (/ X। Y)) से () / x। (/ (x। x))।
एंडर्स कासोर्ग

मैं / to \ _ में परिवर्तन कर रहा हूँ समस्या बहु पात्रों को अनुमति नहीं है। अगर कुछ अन्य का परीक्षण करें तो यह अन्य समाधान के लिए भी है
RosLuP
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.