The SKI kalkulus adalah varian dari kalkulus Lambda yang tidak menggunakan ekspresi lambda. Sebaliknya, hanya aplikasi dan kombinator S , K , dan saya yang digunakan. Dalam tantangan ini, tugas Anda adalah menerjemahkan istilah SKI ke dalam istilah Lambda dalam bentuk normal β .
Spesifikasi Input
Input adalah istilah SKI dalam representasi tekstual berikut. Anda dapat memilih untuk menerima baris tambahan opsional. Input terdiri dari karakter S
, K
, I
, (
, dan )
dan memenuhi tata bahasa berikut (dalam bentuk ABNF) dengan sterm
menjadi simbol awal:
sterm = sterm combinator ; application
sterm = combinator ;
sterm = '(' sterm ')' ; grouping
combinator = 'S' | 'K' | 'I' ; primitives
Spesifikasi Output
Outputnya adalah istilah lambda tanpa variabel bebas dalam representasi tekstual berikut. Anda dapat memilih untuk mengeluarkan baris tambahan opsional. Keluaran harus memenuhi tata bahasa berikut dalam bentuk ABNF dengan lterm
menjadi simbol awal:
lterm = lterm operand ; application
lterm = ALPHA '.' lterm ; lambda
lterm = operand
operand = '(' lterm ')' ; grouping
operand = ALPHA ; variable (a letter)
Kendala
Anda dapat berasumsi bahwa input memiliki bentuk normal β. Anda dapat mengasumsikan bahwa bentuk normal β menggunakan paling banyak 26 variabel yang berbeda. Anda dapat mengasumsikan bahwa input dan output mewakili 79 karakter.
Input sampel
Berikut adalah beberapa input sampel. Output adalah salah satu output yang mungkin untuk input yang diberikan.
input output
I a.a
SKK a.a
KSK a.b.c.ac(bc)
SII a.aa
Mencetak gol
Solusi terpendek dalam oktet menang. Celah umum dilarang.
sterm
danlterm
menggunakan asosiatif kiri ketika tanda kurung tidak ada.SKI
sebagaiS(KI)
.Jawaban:
Haskell , 232 byte
Cobalah online!
Bagaimana itu bekerja
Ini adalah antarmuka parser yang berbeda dengan jawaban saya untuk "Menulis penerjemah untuk kalkulus lambda yang tidak diketik " , yang juga memiliki versi tidak dikenali dengan dokumentasi.
Secara singkat,
Term = T (Char -> String)
adalah jenis istilah kalkulus lambda, yang tahu bagaimana menerapkan diri ke istilah lain (a :: Term -> Term -> Term
) dan bagaimana menampilkan diri sebagaiString
((%) :: Term -> Char -> String
), diberi variabel segar awal sebagai aChar
. Kita dapat mengonversi suatu fungsi dengan istilah ke suatu istilah denganl :: (Term -> Term) -> Term
, dan karena penerapan istilah yang dihasilkan cukup memanggil fungsi (a (l f) == f
), istilah secara otomatis dikurangi menjadi bentuk normal ketika ditampilkan.sumber
Ruby, 323 byte
Saya tidak percaya omong kosong ini bekerja sama sekali:
Menggunakan substitusi regex untuk melakukan reduksi β pada string mentah adalah beberapa hal Tony-the-Pony. Meskipun demikian, outputnya terlihat benar setidaknya untuk testcas mudah:
Ini dia penanganan
K(K(K(KK)))
dengan beberapa output debug, yang memakan waktu sekitar 7 detik pada laptop saya, karena rekursi ekspresi reguler lambat . Anda dapat melihat konversi α-nya beraksi!sumber
Python 2, 674
Catatan: setelah
while 1:
, 3 baris diberi indentasi dengan karakter tab.Ini pada dasarnya adalah kode di belakang http://ski.aditsu.net/ , diterjemahkan ke python, sangat disederhanakan dan golf.
Referensi: (ini mungkin kurang berguna sekarang karena kode dikompresi)
V = istilah variabel
A = istilah aplikasi
L = istilah lambda
c = variabel penghitung
p = ganti variabel dengan suku
r = kurangi
m = penomoran ulang variabel akhir
u = penominan ulang variabel internal (untuk istilah yang digandakan)
s = konversi string
(parameter s = diri)
C = karakter pemisah untuk konversi string
I, K, S: combinators
E = parse
Contoh:
(↑ ini diharapkan karena
SII(SII)
tidak dapat direduksi)Terima kasih Mauris dan Sp3000 untuk membantu membunuh banyak byte :)
sumber
def m(a,b,c):return foo
menjadim=lambda a,b,c:foo
bahkan di dalam kelas, yang mungkin menghemat banyak byte.a.b.c.a(c)(b(c))
sebagai ungkapan lambda yang valid: apa itu(c)
?Lisp umum, 560 byte
"Akhirnya, aku menemukan gunanya
PROGV
."Tidak disatukan
Pengurangan beta
Variabel terikat secara dinamis selama reduksi dengan
PROGV
simbol Common Lisp baru, menggunakanMAKE-SYMBOL
. Hal ini memungkinkan untuk menghindari tabrakan penamaan (misalnya bayangan variabel terikat yang tidak diinginkan). Saya bisa menggunakanGENSYM
, tetapi kami ingin memiliki nama yang ramah untuk simbol. Itulah sebabnya simbol dinamai dengan huruf dari ake z(sebagaimana diizinkan oleh pertanyaan).N
mewakili kode karakter huruf yang tersedia berikutnya dalam lingkup saat ini dan dimulai dengan 97, aliasa .Ini adalah versi
R
(tanpaW
makro) yang lebih mudah dibaca :Hasil antara
Parsing dari string:
Mengurangi:
(Lihat jejak eksekusi)
Cukup cetak:
Tes
Saya menggunakan kembali suite tes yang sama dengan jawaban Python:
Contoh uji 8 terlalu besar untuk tabel di atas:
a.a.a.a.a.b.a
adalah benar dan tidak menggunakan sebanyak huruf sebagai jawaban Python, di mana binding untuka
,b
,c
dand
tidak direferensikan.Performa
Looping selama 7 tes kelulusan di atas dan mengumpulkan hasilnya segera (output SBCL):
Melakukan pengujian yang sama ratusan kali mengarah ke ... "Penyimpanan lokal thread habis" pada SBCL, karena keterbatasan yang diketahui mengenai variabel khusus. Dengan CCL, memanggil ruang uji yang sama 10.000 kali membutuhkan 3,33 detik.
sumber