Yazılmamış lambda hesabı için bir tercüman yazın


45

Buradaki zorluk, yazılmamış lambda matematiği için bir tercümanı olabildiğince az karakterle yazmaktır . Yazılmamış lambda hesabını şu şekilde tanımlarız:

Sözdizimi

Aşağıdaki üç tür ifade vardır:

  • Lambda deyimi forma sahiptir herhangi bir yasal değişken adı ve olabilecek herhangi bir hukuki ifadesi. İşte parametre denir ve işlev gövdesi denir.(λ x. e)xexe

    Sadelik uğruna, xşu anda kapsamda olan adda bir değişken bulunmaması gerektiğine dair daha fazla kısıtlama getiriyoruz. Bir değişken, adı arasında ve .ile göründüğünde kapsamda olmaya başlar ve karşılık gelen kapsamda olmayı durdurur ).

  • İşlev başvuru formu vardır ve yasal ifadelerdir. İşte işlev denir ve argüman denir.(f a)fafa
  • Bir değişken forma sahiptir yasal değişken adıdır.xx

semantik

Fonksiyon gövdesinde parametrenin her bir oluşumunu argümanı ile değiştirerek bir fonksiyon uygulanır. Daha biçimsel formunun ifadesi ((λ x. e) a), xdeğişken adım ve eve aifade ifadeler, değerlendirir (ya da azaltan) olan her oluşumunu değiştirilmesi sonucu olarak birlikte .e'e'xea

Normal bir form daha fazla değerlendirilemeyen bir ifadedir.

Meydan okuma

Göreviniz, kabul etmeyi seçmeniz durumunda, girdi olarak serbest değişken içermeyen ve yazılmamış lambda hesabının bir ifadesini alan ve çıktısı olarak ifadenin normal biçimini (veya ona uygun bir ifadesiyle) üreten bir tercüman yazmaktır. . İfadenin normal bir formu yoksa veya geçerli bir ifade değilse, davranış tanımsızdır.

En az sayıda karakter içeren çözüm kazanır.

Birkaç not:

  • Girdi, stdin'den veya komut satırı argümanı olarak verilen bir dosya adından okunabilir (ikisinden birini değil yalnızca birini veya diğerini uygulamanız gerekir). Çıktı stdout'a gider.
  • Alternatif olarak, girişi bir dizge olarak alan ve çıktıyı bir dizge olarak döndüren bir işlev tanımlayabilirsiniz.
  • ASCII olmayan karakterler sizin için sorunluysa \, λ yerine ters eğik çizgi ( ) karakterini kullanabilirsiniz .
  • Bayt değil, karakter sayısını sayarız; bu nedenle kaynak dosyanız unicode λ olarak kodlanmış olsa bile bir karakter olarak sayılır.
  • Yasal değişken isimleri bir veya daha fazla küçük harflerden oluşur, yani a ve z arasındaki karakterler (alfanümerik isimleri, büyük harfleri veya latin olmayan harfleri desteklemenize gerek yoktur - bunun yerine çözümünüzü geçersiz kılmaz).
  • Bu zorluk söz konusu olduğunda, parantez içinde isteğe bağlı değildir. Her lambda ifadesi ve her fonksiyon uygulaması tam olarak bir çift parantez ile çevrelenecektir. Hiçbir değişken isim parantez içine alınmaz.
  • Sözdizimsel şeker gibi yazma (λ x y. e)için (λ x. (λ y. e))desteklenmesi gerekmez.
  • Bir işlevi değerlendirmek için 100'den fazla özyineleme derinliği gerekirse, davranış tanımsızdır. Bu, tüm dillerde optimizasyon olmadan uygulanabilecek kadar düşük ve çoğu ifadeyi yürütebilecek kadar büyük olmalıdır.
  • Ayrıca, boşlukların örneklerde olduğu gibi, yani girişin başında ve sonunda boşluk kalmayacağını λveya bir fonksiyondan önce ve bir fonksiyondan .sonra ve a'dan sonra tam olarak bir boşluktan önce olacağını varsayabilirsiniz ..λ

Örnek Giriş ve Çıkış

  • Giriş: ((λ x. x) (λ y. (λ z. z)))

    Çıktı: (λ y. (λ z. z))

  • Giriş: (λ x. ((λ y. y) x))

    Çıktı: (λ x. x)

  • Giriş: ((λ x. (λ y. x)) (λ a. a))

    Çıktı: (λ y. (λ a. a))

  • Giriş: (((λ x. (λ y. x)) (λ a. a)) (λ b. b))

    Çıktı: (λ a. a)

  • Giriş: ((λ x. (λ y. y)) (λ a. a))

    Çıktı: (λ y. y)

  • Giriş: (((λ x. (λ y. y)) (λ a. a)) (λ b. b))

    Çıktı: (λ b. b)

  • Giriş: ((λx. (x x)) (λx. (x x)))

    Çıktı: herhangi bir şey (Bu, normal formu olmayan bir ifade örneğidir)

  • Giriş: (((λ x. (λ y. x)) (λ a. a)) ((λx. (x x)) (λx. (x x))))

    Çıktı: (λ a. a)(İşlev çağrısından önceki argümanları değerlendirirseniz normal olmayan bir ifadenin örneği ve ne yazık ki benim teşebbüsümün başarısız olduğu bir örnek.)

  • Giriş: ((λ a. (λ b. (a (a (a b))))) (λ c. (λ d. (c (c d)))))

    Çıktı: `(λ a. (λ b. (a (a (a (a (a (a (a (a b)))))))))) Bu, Kilise sayılarında 2 ^ 3 hesaplar.


1
Dizeye beyaz boşluk eklenmeyeceğini veya eklenmeyeceğini ve boşlukta örnek girişinde belirtilen şekilde olduğunu varsayabilir miyiz? Yani, parantezler arasında, nokta ile parametre adı arasında ve diğer boşlukların örnekleri arasında boşluk yoktur, tam olarak 1 boşluktur.
JPvdMerwe

@JPvdMerwe: Evet, iyi nokta, bunu varsayabilirsin.
sepp2k

Herhangi bir serbest değişken var mı? İfadedeki gibi bir lambda ile bağlanmamış değişkenleri kastediyorum (\y. a).
FUZxxl

3
Buradaki çözümlerin birçoğu veya tamamı, yakalanmayı önleyen ikameleri uygulayamıyor! (Λ x. (Λ x. Y)) gibi bir test durumu eklemelisiniz (λ x. (Λ z. X)); (λ x. (λ x. x)) değil.
Anders Kaseorg

1
@ sepp2k Bir sınama durumu olarak ((λ f. (λ x. (fx)))) (λ y. (λ x. y))) ve yanlış üreten (λ x. (λ) x. x))?
Anders Kaseorg

Yanıtlar:


36

En Yeni:

Onu 644 karaktere kadar sıkıştırdım , cEll'in parçalarını cOpy ve Par; önbellek, hücre ve cdr'yi geçici yerel değişkenlere çağırır ve bu yerel değişkenleri "terminal" (yani özyinelemeli olmayan) işlevlerde genellere taşır. Ayrıca, ondalık sabitler karakter değişmezlerinden daha kısadır ve bu kötü iş ...

atom(x){
    return m[x]>>5==3;
}

... küçük harfleri (ASCII varsayarak) doğru şekilde tanımlar, ancak `{|} ~ herhangi birini kabul eder. (ASCII hakkındaki bu aynı gözlem UTF-8 hakkındaki bu mükemmel videoda yapılmıştır .)

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

Daha erken:

Çaba için birkaç oy alabilir miyim? Bir haftadır bu gece ve gündüz üzerinde çalışıyorum. Orjinal McCarthy belgesini çıkardım ve Paul Graham'ın Lisp Kökleri ekini okuyana kadar gazetenin kendisinde bir hatadan sıkıldım . O kadar rahatsız oldum ki kendimi evimden kilitledim, sonra o gece saat 12: 30'da tekrar eve gelinceye kadar tamamen unuttum (ilçede yaşayan bina yöneticisini aramak için biraz geç kaldım) ve anneannemin gecesi (dizüstü bilgisayarımın pili kuruyana kadar kesiliyor).

Tüm bunlardan sonra, kazananlara bile yakın değil!

Bunun nasıl daha kısa hale getirileceğinden emin değilim; ve düşünebildiğim tüm kirli numaralarını kullandım! Belki C 'de yapılamaz.

Sayımdaki bazı cömertlik ile (ilk yığın bir ip alır ve sonucu yazdırır), 778 770 709 694 karakterdir. Ancak bunu tek başına yapmak için bu sbrkçağrıya sahip olması gerekir . Daha karmaşık ifadelerle başa çıkmak için signalişleyiciye de ihtiyacı var . Ve elbette, kullanmaya çalışan herhangi bir kod içeren bir modüle yapılamaz malloc.

Ne yazık ki, işte burada:

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

İşte son indirimlerden hemen önceki blok. Buradaki püf noktaları işaretçiler yerine tamsayı imleçleri ('örtülü int' davranışından yararlanarak) ve 'kazı kazan belleği' kullanımıdır: char*nboş alana 'yeni' ya da 'sonraki' işaretçisidir. Ama bazen hafızanın içine bir dize yazarım, sonra strlen ve artım n'yi çağırın; etkin bir şekilde bellek kullanıp sonra da tahsis ettikten sonra, hesaplamak daha kolaydır. cell()Verilerin dize ile gösterilmesi arasındaki fonksiyonlar dışında, McCarthy belgesinden oldukça açık olduğunu görebilirsiniz .

#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
Bir ya da iki karakteri kurtarmak için birkaç püf noktası buldum ama radikal bir şey değil. sprintf(n,...);n+=strlen(n)+1;Daha iyi gibidir n+=sprintf(n,...)+1;dizi sözdizimi evrilmesi x[m]yerine m[x]beni 'sonek' makro ile tüm indirections değiştirmek için izin #define M [m]... x M1 kömürü kazandırır ve belirteçleri ayırmak için gerekli olan boşluk beri "özgür" satır sonu veren.
luser droog,

Bununla ve bazı benzerlikler var. IOCCC 1989'dan jar.2 xlisp 4.0 .
luser droog

Bunu daha dolu bir Lisp tercümana genişletmeye çalıştım .
luser droog

// um ...Yorumlanan kod , dize arasında dolaşıyor ve parantez içinde eşleşen yakın pareni doğru yuva düzeyinde bulana kadar sayıyor.
kullanıcı

1
Bu hatalı ((\ f. (\ X. (Fx)))) (\ y. (\ X. Y))) ((xx. (Fx))) değerini değerlendirir.
Anders Kaseorg 27:15

22

İkili Lambda Hesabı 186

Aşağıdaki altıgen dökümde gösterilen program

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

önerdiğiniz biçimi kabul etmiyor. Aksine, ikili lambda hesabı (blc) biçiminde bir lambda terimi bekler. Bununla birlikte, minimal parantez kullanarak normal form indirgemesindeki her adımı gösterir.

Örnek: Kilise sayılarında 2 ^ 3 hesaplama

Yukarıdaki hex dökümünü xxd -r> symbolic.Blc ile kaydedin.

Http://tromp.github.io/cl/uni.c adresinden bir blc yorumcusu alın.

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)))))))

HexDump oldukça okunaklı olmadığı için, burada "demonte" bir versiyon

@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\
@

00 (lambda) 'ı \ ve 01 (uygulama) ile @ ile değiştirmek Artık neredeyse beyin fırtınası kadar okunaklı :-)

Ayrıca bkz. Http://www.ioccc.org/2012/tromp/hint.html


7
BLC sadece ikili bir alfabe kullanıyor. 00 lambda, 01 uygulama ve 1 ^ {n} 0 tekdüze bir değişkendir. Bu konuda derleme yok.
John Tromp

3
X3 faktörünü nereden alıyorsunuz? Aslında, BF gibi daha küçük kaynak alfabe sahip dillerin cezalandırıldığı dillerde iyi bir noktaya değindiniz. Adil bir karşılaştırma için, tüm boyutlar bit cinsinden ifade edilmelidir ve BF karakterleri her biri yalnızca 3 bit alır. Diğer birçok dilde ASCII için 7 bit gerekir, bazıları 8 kullanır.
John Tromp

1
BTW +1 Bu çok harika!
luser droog

1
Eğer frakrandaki frakran kabul edilebilirse, bunun neden bir problem olması gerektiğini anlamıyorum. Okuyamıyor musun? İstiyorsun? Öğrenin!
luser droog

1
Gerçek giriş biçimini okuması için ne gerekir? Sanırım potansiyel kazancını kaybettiğin yer orası.
luser droog

14

Haskell, 342 323 317 305 karakter

Bu yazı itibariyle, ((λ f. (Λ x. (Fx))) (λ y. (Λ x. Y))) doğru sonucu (λ x. (Λ z) olarak değerlendiren tek çözüm budur. x)) (λ x. (λ x. x)) yerine. Lambda matematiğinin doğru bir şekilde uygulanması, bu problemin basitleştirici garantisi altında olsa da, hiçbir değişkenin kendi kapsamındaki başka bir değişkeni gölgelendirmediği için yakalanmayı önleyen bir ikame gerektirir . (Programım bu garanti olmadan bile çalışıyor.)

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"++))

Notlar:

  • Bu, GHC 7.0'da çalışır çünkü bu zorluk Ocak 2011'de belirlendi . GHC 7.10'u üstlenmeme izin verilirse 13 karakter daha kısa olurdu.

Belgeleri ile Ungolfed sürümü .


ideone haskell derleyicideki ilerlemeniz ((\ x. x) (\ y. (\ z. z))) girişine ((\ x. x) ()) "çalışma zamanı hatası" ((\ \ x. x) (\\ y.) \\ z. z))) ... Haskell'de "lex" ne demek?
RosLuP

2
@RosLuP Programım λ kabul ediyor, \ değil.
Anders Kaseorg

ideone.com 'a bu imput ((λ x. x) (λ y. (λ z. z))) ifadesini yazınız. return: Çalışma zamanı hata süresi: 0 bellek: 4876 sinyal: -1
RosLuP

1
@RosLuP Ideone, Unicode desteğini kırmış gibi görünüyor. Komut satırını veya başka bir çevrimiçi tercümanı deneyin ( örneğin Rextester'da çalışır ).
Anders Kaseorg

2
@codeshot soru yazar zaten çok yorum ki ((λ f. (λ, x. (fx))) (λ y. (λ, x. y))) ↦ (λ, x. (λ z. X)) için doğrudur bu problem (tıpkı gerçek lambda matematiği gibi).
Anders Kaseorg

13

Python - 321 320

İşte benim (sabit) denemem:

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())

Bu güzel görünüyor, ama işe görünmüyor. Kodunuzun yanlış sonuçlar verdiği bazı örnek girişler ve çıkışlar ekledim.
sepp2k

1
Bu, yakalamayı önleme yerine geçme işlemini gerçekleştiremez. Örneğin, ((\ f. (\ X. (Fx)))) (\ y. (\ X. Y))) hatalı (\ x. (\ X. X)) olarak değerlendirir.
Anders Kaseorg

1
Zorlukla çalışırken neden bu bir cevap olarak işaretlenir? Yazar tarafından verilen giriş ve çıkışları denediniz mi?
rbaleksandar

1
Yazarın verdiği test durumları bu cevaptaki hataları göstermek için yeterli değildir.
Anders Kaseorg

1
Bu cevap ne doğru ne de en kısa yoldur. Yakalamadan kaçınıyor ve dize değiştirme hataları var.
Richard Padley

6

Ruby 254 karakter

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}

Gibi kullanılabilir

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

Çözüm henüz tam anlamıyla golf oynamadı, ancak neredeyse hiç okunamıyor.


merhaba gıpta, eski arkadaşım :)
luser droog

Bu, yakalamayı önleme yerine geçme işlemini gerçekleştiremez. Örneğin, ((\ f. (\ X. (Fx)))) (\ y. (\ X. Y))) hatalı (\ x. (\ X. X)) olarak değerlendirir.
Anders Kaseorg

Yukarıdaki yakalama hatasına ek olarak, bu, hatalı bir şekilde dize değişiminin üretildiği (\ y. (\ Xx. ((\ X. Xx) y))) ila (\ y. (\ Xx. Yy)) değerini de yanlış olarak değerlendirir. var olmayan değişken yy.
Anders Kaseorg

3

Düzenleme: saf JavaScript altında 250 için aşağıdaki cevabımı kontrol edin.

LiveScript kullanarak 2852 243 karakter (Regex yok! Tam olarak golf oynamadım - geliştirilebilir)

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

Ölçek:

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]]]]]]]]]]]

Hangisi 3^2=9OP belirtildiği gibi.

Merak eden varsa, işte size bazı yorumlar ile genişletilmiş bir versiyon:

# 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]

Bu, problemin giriş ve çıkış özelliklerine uymuyor.
Anders Kaseorg

3

Waterhouse Arc - 140 karakter

(=
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 #\._])

Waterhouse Arc'ı nereden bulabilirim?
Anders Kaseorg

1
Bir tercüman bulunamadığı için geçersiz
kedi

@AndersKaseorg burada
ASCII sadece

@ ASCII-sadece Arc'ın ne olduğunu biliyorum, ancak “Su Evi” kısmı bana belirli bir lehçenin gerekli olduğunu söyledi. Koşmasını sağladın mı?
Anders Kaseorg

@AndersKaseorg Boşver. Buldum
ASCII sadece

2

C 1039 bayt

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

Değişkenler, küçük harfleri kullanarak [a .z'den itibaren] girişler olarak izin verir, sys, çıktıda gerekirse büyük harfleri [A..Z'den] kullanarak değişkenler oluşturabilir ... ascii karakter konfigürasyonunu varsayalım.

#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*/

Spesifikasyon \ veya λ gerektirir, / gerektirmez. Ayrıca çok harfli değişken isimleri için destek gerektirir.
Anders Kaseorg

'\ n' etc sembol '\' başka kullanımları vardır, bunun yerine '/' kullanımı daha iyidir
RosLuP

1
Yine de zorluk, şartnameyi yerine getirmek, daha iyisini yapmak değil.
Anders Kaseorg

biraz daha uyumlu olması için bir şeyler yazdım ... ama büyüklük patladı ...
RosLuP 17:16


1

Haskell 456 C

Haskell'in tembel değerlendirme özelliği tam olarak kullanılıyorsa, daha kısa olabilir. Ne yazık ki, nasıl yapacağımı bilmiyorum.

Ayrıca, ayrıştırma adımında birçok karakter israf edilir.

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

Ungolfed versiyonu

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
Bu, yakalamayı önleme yerine geçme işlemini gerçekleştiremez. Örneğin, ((λ f. (Λ x. (Fx))) (λ y. (Λ x. Y))) yanlış olarak değerlendirir (λ x. (Λ x. X)).
Anders Kaseorg

1

JavaScript ile 231 var / Regex yok

(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 elemanlı dizileri alır. 1açılımı λve 2 Bruijn endeksi değişkeni simgeler.

Ölçek:

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

Bu, problemin giriş ve çıkış özelliklerine uymuyor.
Anders Kaseorg

1

Python: 1266 karakter (wc kullanılarak ölçülen)

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()))

Uzun bir vuruşta en kısa süre değil, ancak alfa yeniden adlandırma ve OPs postasında listelenen tüm örnekleri doğru şekilde işler.


Bu işlev adlarından bazılarını kısaltabilir ve bazılarını lambdaya dönüştürebilirsiniz. Ayrıca burada ve orada biraz fazla boşluk var
Jo King,

(1) 4 boşluklu girintiyi tek bir boşlukla değiştirmek, oldukça az sayıda bayt kazandıracaktır. (2) except NameErrorSadece yerini alabilir misiniz except? (3) İki karakterli fonksiyon isimleri, tek karakterli isimlerle yeniden adlandırılabilir. (4) Etrafında boşluk olan ödevlerin olduğu birkaç yer var =. (5) if t[0]=='c'ile değiştirilebilir if'c'==t[0].
Esolanging Fruit

1045 byte girinti ve lambdas gibi çoğunlukla biçimlendirme değişikliklere
Jo Kral

0

C ++ (gcc) ,782 766 758 731 bayt

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

Çevrimiçi deneyin!

Buradaki temel fikir, kodun, de Bruijn endeksleri fikrine dayanan içsel bir gösterimi kullanmasıdır; ancak, belirtilen değişkenin bağlanmasının lambda derinliğini belirtmek için endeksleri tersine çevirmem dışında. Kodda:

  • E::tdeğişken yaprak düğümü için bir düğüm - 0'ı, bir lambda düğümü için 1 ve bir işlev uygulama düğümü için 2'yi temsil eder. (Seçilebilecek düğümün arititesi ile çakışacak şekilde seçildi, sadece mümkün oldu.) O zaman E::lve E::ruygun olan çocuklar (sadece E::lbir lambda düğümü için) ve E::ideğişken yaprak düğümü için lambda derinlik indeksidir.
  • Yapıcı E::E(E&o,int d,int e), başlangıçta lambda derinliğinde dyeni bir yere yapıştırmak için lambda derinliğinde olan bir alt ifadeyi klonlar d+e. Bu daha az lambda derinlikte değişkenleri muhafaza içerir d, en az bir lambda-derinlikte değişkenleri artan süre dile e.
  • E::salt ifadenin bir ikame yapar vdeğişken dizi halinde dde *thisdaha fazla değişken sayıda azaltma sırasında d(ve ebu çağrı için ihtiyaç duyduğu zaman için lambda derinlik artışı takip bir iç detay E::c).
  • E::RAST üzerinden yapılan bir ön arama aramasına göre en üst veya en soldaki örnekleri tercih etmek için tek bir beta azaltma arar. Gerçekleştirecek bir azalma bulduğunda sıfır, sıfır ise sıfır yapar.
  • E::uto_stringdeğişkenler için sentetik isimler kullanarak bir "insan tarafından okunabilir" dizgiyi yeniden oluşturan bir tür işlemdir. (Not çünkü küçük bir golf arasında Vsadece isimleri içeren üretecektir yardımcı işlevi ayoluyla i).
  • Yapıcı E::E(int d, std::map<std::string, int> m, char*&s), halihazırda bağlı değişken isimlerinin lambda-derinlik indeksleri ile seşleştirilmesine dayanarak bir girdi dizgisini AST ifadesiyle ayrıştırır m.
  • f soruyu cevaplayan ana işlevdir.

(As kod çoklu karakterler ile sap değişken isimleri yapar TIO linkten görebilirsiniz ve aynı zamanda bir doğru cevabı alır (\ a. (\ b. a))için ((\ f. (\ x. (f x))) (\ y. (\ x. y))). Aynı zamanda sadece bu yüzden ayrıştırma kodu hiçbir ekstra ücret ödemeden değişken gölgeleme işleyebilir olur.)


-16 ve kısmen nedeniyle değişen nedeniyle (Ben de bağımsız ile gelmişti) ceilingcat tarafından fikrine kısmen bayt E*a=new E;için E&a=*new E;ve sonra değişen a->içina.

- ceilingcat'in başka bir yorumu nedeniyle 8 bayt daha ( a.tüçlü bölümden atama faktörü )

-27 bayt'ın ayrıştırıcı ve klonun kurucularına dönüştürülmesinden E


-1

C 637 bayt

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

Bu sürüm yardımcı değişkenler kullanmaz (bu lambda matematiğinin söylediği% 100’ü takip etmez). Her değişkenin 1 karakter uzunluğunda olması gerekir (bazıları burada olduğu gibi). Test kodu:

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

Sonuçlar:

/*
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))
*/

bu yarı ungolf olanı:

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

Spesifikasyon \ veya λ gerektirir, / gerektirmez. Ayrıca çok harfli değişken isimleri için destek gerektirir. Ek olarak (bunun farkında olduğunuzu biliyorum, ama evet, hala yanlış), bu yanlış ((/ f. (/ X. (Fx)))) (/ y. (/ X. Y))) (( / x. (/ x. x)).
Anders Kaseorg

Değişim / to \ var çoklu karakter değişkenine izin vermeme sorunu var. eğer bir başkasını test edersek, bu başka bir çözüm için de geçerlidir
RosLuP
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.