EDIT: Bazılarınızın şüphelendiği gibi, resmi yorumlayıcıda bir hata vardı: kompozisyonun sırası .tersine çevrildi. Tercümenin iki versiyonu vardı ve burada yanlış olanı kullandım. Örnekler de bu yanlış versiyon için yazılmıştır. Yorumlayıcıyı depoda ve aşağıdaki örneklerde düzelttim. Açıklaması >da biraz belirsizdi, bu yüzden bunu düzelttim. Ayrıca, bu kadar uzun sürdüğü için özür dilerim, gerçek hayattaki bazı şeylere takıldım.
EDIT2: Yorumcumun uygulamada .örneklere yansıyan bir hatası vardı (tanımlanmamış davranışa dayanıyorlardı). Sorun düzeltildi.
Giriş
Shift , birkaç yıl önce yaptığım ama bugün yayınladığım ezoterik bir işlevsel programlama dilidir. Yığın tabanlıdır, ancak Haskell gibi otomatik köri vardır.
Şartname
Shift'te iki veri türü vardır:
- Keyfi pozitif bir arititeye (giriş sayısı) sahip olan ve bir çıkış listesi döndüren işlevler . Örneğin, tek girişini çoğaltan bir fonksiyonun 1 değeri ve iki girişini değiştiren bir fonksiyonun 2 değeri vardır.
- Hepsi özdeş olan ve fonksiyon olmamaktan başka amacı olmayan boşluklar.
Bir Shift programı , her biri tek bir ASCII karakteri olan sıfır veya daha fazla komuttan oluşur . Toplamda 8 komut vardır:
!( Uygulanır ) bir işlevi çıkarfve bir değerxistiften ve geçerlifiçinx. EğerfArity 1 vardır, listef(x)istifin önünde eklenir. Arity varsa, yığınan > 1yeni bir(n-1)işlev eklenirg. Girdileri alır ve geri döner .x1,x2,...,xn-1f(x,x1,x2,...,xn-1)?( boş ), bir boş yığını yığına iter.+( klon ) yığına girdisini çoğaltan tekli bir işlevi iter: herhangi bir değerxeşlenir[x,x].>( Kaydırma ) yığına bir alır bir tekli fonksiyonu itern-ary fonksiyonufve bir döner(n+1)-ary fonksiyonugilk argüman yok sayarx, çağrıfgeri kalanlar üzerinde, ve çivilerxsonucu önünde. Örneğin,shift(clone)girdileri alana,bve döndüren bir ikili işlevdir[a,b,b]./( Çatal ) yığına, üç giriş alır üçlü fonksiyonu itera,b,cve döner[b]iseaboş olduğu ve[c]başka türlü.$( call ) yığına bir işlevifve değeri açanxve tam olarak olduğu gibi uygulanan bir ikili işlevi iter .fx!.( Zincir ) yığına çıkar iki işlevi bir ikili işlev iterfvegbir işlev: ve bunların bileşimi verirhaynı Arity sahiptirf, ve normal olarak, girişlerine uygulandığıfonlara ve daha sonra tam olarak geçerlidirg(çağrı sonucu onun çağının dikte ettiği kadar),fsonuçta kalan çıktıdan kullanılmayan öğelerleh. Örneğin, varsayalımfikinci argüman klonunu ve bir ikili işlevdirgolan çağrı . Yığın içeriyorsa[f,g,a,b,c]ve.!!içeriyorsa[chain(f,g),a,b,c];!!sonra yaparsak , ofzaman ilk öncea,b,[a,b,b], daha sonragilk 2 elementine uygulanır, çünkü arity 2 olduğundan üretilir[a(b),b]ve yığın sonunda olur[a(b),b,c].@( diyelim ) girdisini döndüren tekli bir işlevi iter ve0boşsa ve bir işlevse yazdırır1.
!Yığına bir değer basmak dışında tüm komutların girdi yapmanın bir yolu olmadığını ve herhangi bir çıktıyı almanın tek yolunun kullanmak olduğunu unutmayın @. Bir program, komutları tek tek değerlendirerek, "say" çağrıldığında 0s veya 1s yazdırarak ve çıkarak yorumlanır. Burada açıklanmayan herhangi bir davranış (bir boşluk uygulamak, 0 veya 1 uzunluğunda bir yığın uygulamak, bir boşluk üzerine "zincir" çağırmak vb.) Tanımlanmamıştır: yorumlayıcı çökebilir, sessizce başarısız olabilir, girdi isteyebilir veya her neyse.
Görev
Göreviniz Shift için bir tercüman yazmaktır. Yorumlanması için bir Shift programı olan STDIN, komut satırı veya işlev bağımsız değişkeninden almalı ve STDOUT'a yazdırmalı veya sonuç olarak 0s ve 1s'nin (muhtemelen sonsuz) çıktısını döndürmelidir . Bir işlev yazarsanız , sonsuz uzunlukta çıkışlara bir şekilde erişebilmeniz gerekir (Python'daki jeneratör, Haskell'deki tembel liste, vb.). Alternatif olarak, başka bir girdi, bir sayı alabilir nve ndaha uzunsa çıktıdaki en az karakterleri döndürebilirsiniz n.
En düşük bayt sayısı kazanır ve standart boşluklara izin verilmez.
Test Durumları
Bu Shift programı yazdırır 01:
?@!@@!
Soldan başlayarak: itme boş, itme diyelim , o zaman uygulamak söz taslağa. Bu çıktı 0. Ardından, itme demek iki kez, ikinci uygulamak söz ilkine. Bu çıktı 1.
Bu program sonsuza kadar dönerek çıktı üretmez:
$+.!!+!!
İtme çağrı ve klon , daha sonra uygulamak zincirini (biz iki ihtiyaç onlara !beri s zincir ikili işlevdir). Artık yığın, bir bağımsız değişkeni alan, çoğaltan ve ikinci kopyayı ilk kopyayı çağıran bir işlev içeriyor. İle +!!, bu işlevi çoğaltır ve kendi başına çağırırız.
Bu program yazdırır 0010:
?@$.++>!.!!.!!.!!!!+?/!!!@!@>!!!
Bir alanı itin ve söyleyin . Ardından, ikinci argümanını bkopyalayan, sonra ilkini kopyalayan ave onu kendisiyle birleştiren bir ikili işlev oluşturun, ardından kompozisyonu bdöndürerek kopyasına uygular [a(a(b)),b]. O uygula demek ve boş, ardından uygulamak söz yığını üzerinde kalan iki elemanlarına.
Bu program yazdırılır 0. !!!Eklediğiniz her biri için ek yazdırır 0.
?@+$>!>!+>!///!!>!>!.!!.!!.!!+!!!!
Bir alanı itin ve söyleyin . Ardından, f,g,xgirdi olarak ve geri dönen üçlü bir işlev oluşturun [f,f,g,g(x)]. Bu işlevi klonlayın ve kendinize, örneğin boşluğa uygulayın. Bu uygulama yığını değiştirmez, bu nedenle fonksiyonu istediğimiz kadar tekrar uygulayabiliriz.
Bu program sonsuz sekansı yazdırır 001011011101111..., burada 1s sayısı her zaman bir artar:
@?/!@>!??/!!>!+.!!.!!.!!.+>!.!!$$$$+$>!>!$>!>!+>!$>!>!>!+>!>!///!!>!>!>!.!!.!!.!!.!!.!!.!!.!!.!!.!!.!!+!!!!!
Depo açıklamalı bir sürüm içeriyor.
f(x1, x2, ..., xn)ve g(y1, y2, ..., ym). Arayan .bir fonksiyonu bunlardan ve iter hem pops h(z1, z2, ..., zn). Şimdi tüm bu argümanları yavaş yavaş körükleyerek yiyebilirsiniz !. Bu ntür uygulamalardan sonra , kalan işlevin yalnızca bir bağımsız değişkeni vardı ve bu noktada bazı yeni değerleri iten ve hemen yığındaki değerleri tüketen ve bunlara çağrı yapan hesaplar f(z1, z2, ..., zn)(yani f, curried tüm bağımsız değişkenlere uygulanır) . mg
.tam olarak Martin'in tanımladığı gibi çalışır, ancak değerlerden fdaha az bir liste döndürürse m, sonuç tanımsızdır (kompozisyon arity'ye sahiptir n, bu nedenle yığından daha fazla argüman yiyemez). Esas olarak, çıktısı, süreleri kullanılarak itilen ve uygulanan fgeçici bir yığın olarak kullanılır ve bunun sonucu, ana yığına eklenir. gm!