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 çıkarf
ve bir değerx
istiften ve geçerlif
içinx
. Eğerf
Arity 1 vardır, listef(x)
istifin önünde eklenir. Arity varsa, yığınan > 1
yeni bir(n-1)
işlev eklenirg
. Girdileri alır ve geri döner .x1,x2,...,xn-1
f(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ğerx
eşlenir[x,x]
.>
( Kaydırma ) yığına bir alır bir tekli fonksiyonu itern
-ary fonksiyonuf
ve bir döner(n+1)
-ary fonksiyonug
ilk argüman yok sayarx
, çağrıf
geri kalanlar üzerinde, ve çivilerx
sonucu önünde. Örneğin,shift(clone)
girdileri alana,b
ve döndüren bir ikili işlevdir[a,b,b]
./
( Çatal ) yığına, üç giriş alır üçlü fonksiyonu itera,b,c
ve döner[b]
isea
boş olduğu ve[c]
başka türlü.$
( call ) yığına bir işlevif
ve değeri açanx
ve tam olarak olduğu gibi uygulanan bir ikili işlevi iter .f
x
!
.
( Zincir ) yığına çıkar iki işlevi bir ikili işlev iterf
veg
bir işlev: ve bunların bileşimi verirh
aynı Arity sahiptirf
, ve normal olarak, girişlerine uygulandığıf
onlara ve daha sonra tam olarak geçerlidirg
(çağrı sonucu onun çağının dikte ettiği kadar),f
sonuçta kalan çıktıdan kullanılmayan öğelerleh
. Örneğin, varsayalımf
ikinci argüman klonunu ve bir ikili işlevdirg
olan çağrı . Yığın içeriyorsa[f,g,a,b,c]
ve.!!
içeriyorsa[chain(f,g),a,b,c]
;!!
sonra yaparsak , of
zaman ilk öncea,b
,[a,b,b]
, daha sonrag
ilk 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 ve0
boş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 0
s veya 1
s 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 0
s ve 1
s'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 n
ve n
daha 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ı b
kopyalayan, sonra ilkini kopyalayan a
ve onu kendisiyle birleştiren bir ikili işlev oluşturun, ardından kompozisyonu b
dö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,x
girdi 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 1
s 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 n
tü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) . m
g
.
tam olarak Martin'in tanımladığı gibi çalışır, ancak değerlerden f
daha 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 f
geçici bir yığın olarak kullanılır ve bunun sonucu, ana yığına eklenir. g
m
!