Tantangannya adalah menulis penerjemah untuk kalkulus lambda yang tidak diketik dalam karakter sesedikit mungkin. Kami mendefinisikan kalkulus lambda yang tidak diketik sebagai berikut:
Sintaksis
Ada tiga jenis ekspresi berikut:
Ekspresi lambda memiliki bentuk di
(λ x. e)
manax
bisa berupa nama variabel hukum dane
ekspresi hukum apa pun. Di sinix
disebut parameter dane
disebut fungsi tubuh.Demi kesederhanaan, kami menambahkan batasan lebih lanjut bahwa tidak boleh ada variabel dengan nama yang sama seperti
x
saat ini dalam ruang lingkup. Suatu variabel mulai berada dalam cakupan ketika namanya muncul di antara(λ
dan.
dan berhenti berada dalam lingkup pada yang bersangkutan)
.- Aplikasi fungsi memiliki bentuk di
(f a)
manaf
dana
merupakan ekspresi hukum. Di sinif
disebut fungsi dana
disebut argumen. - Variabel memiliki bentuk di
x
manax
nama variabel hukum.
Semantik
Suatu fungsi diterapkan dengan mengganti setiap kemunculan parameter di badan fungsi dengan argumennya. Lebih formal ekspresi dari bentuk ((λ x. e) a)
, di mana x
adalah nama variabel dan e
dan a
adalah ekspresi, mengevaluasi (atau mengurangi) untuk ekspresi e'
di mana e'
merupakan hasil dari penggantian setiap kemunculan x
di e
dengan a
.
Bentuk normal adalah ungkapan yang tidak dapat dievaluasi lebih lanjut.
Tantangan
Misi Anda, jika Anda memilih untuk menerimanya, adalah untuk menulis seorang juru bahasa yang mengambil sebagai input ekspresi dari kalkulus lambda yang tidak diketik yang tidak mengandung variabel bebas dan menghasilkan sebagai output bentuk normal ekspresi (atau ekspresi alpha-kongruen dengan itu) . Jika ekspresi tidak memiliki bentuk normal atau itu bukan ekspresi yang valid, perilaku tidak terdefinisi.
Solusi dengan jumlah karakter terkecil menang.
Beberapa catatan:
- Input dapat dibaca dari stdin atau dari nama file yang diberikan sebagai argumen baris perintah (Anda hanya perlu mengimplementasikan satu atau yang lain - tidak keduanya). Output menuju ke stdout.
- Atau Anda dapat mendefinisikan fungsi yang mengambil input sebagai string dan mengembalikan output sebagai string.
- Jika karakter non-ASCII bermasalah untuk Anda, Anda dapat menggunakan karakter backslash (
\
) alih-alih λ. - Kami menghitung jumlah karakter, bukan byte, jadi meskipun file sumber Anda dikodekan sebagai unicode, λ dihitung sebagai satu karakter.
- Nama variabel legal terdiri dari satu atau lebih huruf kecil, yaitu karakter antara a dan z (tidak perlu mendukung nama alfanumerik, huruf besar atau huruf non-latin - meskipun hal itu tidak akan membatalkan solusi Anda, tentu saja).
- Sejauh menyangkut tantangan ini, tidak ada tanda kurung opsional. Setiap ekspresi lambda dan setiap aplikasi fungsi akan dikelilingi oleh tepat sepasang kurung. Tidak ada nama variabel yang akan dikelilingi oleh tanda kurung.
- Gula sintaksis seperti menulis
(λ x y. e)
untuk(λ x. (λ y. e))
tidak perlu didukung. - Jika kedalaman rekursi lebih dari 100 diperlukan untuk mengevaluasi suatu fungsi, perilaku tidak terdefinisi. Itu harus lebih dari cukup rendah untuk diimplementasikan tanpa optimasi dalam semua bahasa dan masih cukup besar untuk dapat mengeksekusi sebagian besar ekspresi.
- Anda juga dapat mengasumsikan bahwa spasi akan seperti dalam contoh, yaitu tidak ada spasi di awal dan akhir input atau sebelum
λ
atau.
dan tepat satu spasi setelah a.
dan antara fungsi dan argumennya dan setelah aλ
.
Input dan Output Sampel
Memasukkan:
((λ x. x) (λ y. (λ z. z)))
Keluaran:
(λ y. (λ z. z))
Memasukkan:
(λ x. ((λ y. y) x))
Keluaran:
(λ x. x)
Memasukkan:
((λ x. (λ y. x)) (λ a. a))
Keluaran:
(λ y. (λ a. a))
Memasukkan:
(((λ x. (λ y. x)) (λ a. a)) (λ b. b))
Keluaran:
(λ a. a)
Memasukkan:
((λ x. (λ y. y)) (λ a. a))
Keluaran:
(λ y. y)
Memasukkan:
(((λ x. (λ y. y)) (λ a. a)) (λ b. b))
Keluaran:
(λ b. b)
Memasukkan:
((λx. (x x)) (λx. (x x)))
Keluaran: apa saja (Ini adalah contoh ekspresi yang tidak memiliki bentuk normal)
Memasukkan:
(((λ x. (λ y. x)) (λ a. a)) ((λx. (x x)) (λx. (x x))))
Output:
(λ a. a)
(Ini adalah contoh ekspresi yang tidak menormalkan jika Anda mengevaluasi argumen sebelum pemanggilan fungsi, dan sayangnya contoh yang gagal diupayakan solusi saya)Memasukkan:
((λ a. (λ b. (a (a (a b))))) (λ c. (λ d. (c (c d)))))
Keluaran:
`(λ a. (λ b. (a (a (a (a (a (a (a (a b))))))))))
Ini menghitung 2 ^ 3 dalam angka Gereja.
(\y. a)
.