Kipple'ı yorumla!


12

Giriş

Kipple , Mart 2003'te Rune Berg tarafından icat edilen yığın tabanlı, ezoterik bir programlama dilidir.

Kipple 27 yığın, 4 operatör ve bir kontrol yapısına sahiptir.

Yığınlar

Yığınları adlandırılır a- zve 32-bit işaretli tamsayı içerir. @Çıktı numaralarını daha uygun hale getirmek için özel bir yığın da vardır . Bir sayı üzerine itildiğinde @, o sayının rakamlarının ASCII değerleri aslında yerine itilir. (Örneğin, 12'ye basarsanız @, bunun @yerine 49 ve sonra 50'yi iter .)

iProgram yürütülmeden önce girdi girdi yığınına itilir . Yorumlayıcı, iyürütmeden önce saklanacak değerleri isteyecektir . Yürütme işlemi tamamlandıktan sonra, çıkış yığınındaki her şey oASCII karakteri olarak çıktı almak üzere açılır. Bu Kipple'ın tek IO mekanizması olduğundan, bir Kipple programıyla etkileşim kurmak imkansızdır.

Operatörler

İşlenen, bir yığın tanıtıcısı veya işaretli bir 32 bit tam sayıdır.

Push: >veya<

Sözdizimi: Operand>StackIndentifierveyaStackIndentifier<Operand

İtme operatörü işleneni sola götürür ve belirtilen yığının üzerine iter. Örneğin, 12>a12 değerini yığına iter a. a>byığındaki en üstteki değeri açar ave yığının üzerine iter b. Boş bir yığının patlaması her zaman 0 a<bdeğerini döndürür b>a. a<b>cdan üstteki değeri çıkar bve iter hem cve a.

Ekle: +

Sözdizimi: StackIndentifier+Operand

Ekle işleci, yığındaki en üstteki öğenin toplamını ve işleneni yığının üzerine iter. İşlenen bir yığınsa, değer ondan açılır. Örneğin, yığının en üst değeri a1 ise, a+23'ü üzerine iter. Eğer aboşsa a+2, üzerine 2 itecektir. Yığının en üst ave b1 ve 2 değerleri varsa, 2 a+bdeğerini yığından çıkarır bve 3'ü yığının üzerine iter a.

Çıkar: -

Sözdizimi: StackIndentifier-Operand

Çıkarma işleci, Toplama işleci gibi çalışır, ancak toplama yerine çıkarır.

Açık: ?

Sözdizimi: StackIndentifier?

Clear operatörü, en üstteki öğe 0 ise yığını boşaltır.

Aşağıdaki programı çalışacak böylece tercüman, yanındaki bir operatöre olmayan her şeyi göz ardı eder: a+2 this will be ignored c<i. Ancak, yorum eklemenin doğru yolu #karakteri kullanmaktır . A ile #satır sonu karakteri arasındaki her şey yürütmeden önce kaldırılır. ASCII karakteri # 10, Kipple'de satır sonu olarak tanımlanır.

İşlenenler iki operatör tarafından paylaşılabilir, örneğin a>b c>b c?olarak yazılabilir a>b<c?.

Program , değerleri (aşağıdan yukarıya) 1>a<2 a+aiçerecek şekilde içerecektir . Aynı şekilde operatör için.a[1 4][1 3]-

Kontrol Yapısı

Kipple'de sadece bir kontrol yapısı vardır: döngü.

Sözdizimi: (StackIndentifier code )

Belirtilen yığın boş olmadığı sürece, eşleşen parantez içindeki kod tekrarlanacaktır. Döngüler başka döngüler içerebilir. Örneğin, (a a>b)istifin tüm değerleri taşır ayığına bsırası olacak olsa da, ters . Bunu yapmanın işlevsel olarak aynı, ancak daha zarif bir yolu (a>b).

Örnekler

100>@ (@>o)

Bu çıktı 100

33>o 100>o 108>o 114>o 111>o 87>o 32>o 111>o 108>o 108>o 101>o 72>o

Bu yazdırılacaktır "Hello World!". oYığın çıktısı alınırken , yığının tepesinden alta doğru karakterleri açmaya başlar.

#prime.k by Jannis Harder
u<200
#change 200


k<2>m
u-2
(u-1 u>t u>z u<t
  (k>e e+0 e>r)
  (e>k)
  m+1
  m>t
  m>z
  m<t
  t<0>z? t?
  1>g
  (r>b
    m+0 m>a
    b+0 b>w
    (a-1 
      b+0 b>j
      j?
      1>s
      (j<0>s j?)
      s?
      (s<0 w+0 w>b s?)
      a>t
      a>z
      t>a
      b-1
      b>t
      b>z
      t>b
      z<0>t? z?
    a?)
    b?
    1>p
    (b<0 b? 0>p)
    p?
    (p 0>r? 0>p? 0>g)
  )
  g?
  (g m+0 m>k 0>g?)
u?)
(k>@
  10>o
  (@>o)
)

Bu asal sayı üreteci, ama nasıl çalıştığından emin değilim.

kurallar

  • Kipple'ı yorumlayan bir program / işlev yazmalısınız. Bu program / işlev bir kaynak dosyası aracılığıyla bir Kipple programı alabilir veya doğrudan kullanıcıdan STDIN aracılığıyla alabilir. STDIN kullanılamıyorsa, klavye girişinden almalı ve yazdırılamaz belirli bir karakter girilene kadar giriş almaya devam etmelidir. Örneğin, tercümanınız x86 makine koduyla yazılmışsa, Kipple programını karakter karakter olarak klavyeden alır ve esc(veya yazdırılabilir bir karakter yaymayan başka bir tuşa) basılana kadar bunu yapmaya devam eder .

  • Bir sözdizimi hatası veya yığın taşması gibi bir hata varsa, örneğin 0 yerine 10 veya yorumlayıcı / derleyici tarafından üretilen hata iletilerini döndürerek AMA HATA MESAJLARINI YAZDIRMAYIN .

  • Bu sorun için kod golfü ile ilgili diğer kurallar geçerlidir.

  • Kodunuz Kipple'ın örnek arşivindeki bazı örneklerle test edilecektir

Bu bir . Bayt cinsinden en kısa kod kazanacaktır. İyi şanslar!


Kipple'da isteğe bağlı bir operatör olduğunu unutmayın, "ancak bu spesifikasyonun bir parçası değildir ve resmi tercümanda sadece ekstra bir özelliktir. Burada bahsetmedim, bu nedenle başvurunuzda desteklenmesine gerek yok.

Spesifikasyonun herhangi bir bölümü hakkında herhangi bir şüpheniz varsa , Java ile yazılmış resmi tercüman ile inceleyebilirsiniz . Bu, derlenmiş program ve kaynak kodunu içeren bir zip dosyası indirecektir. GPL lisansı altındadır.


1
Yapmamız var 32 bitlik imzalı tamsayı kullanmak ya da biz konak uygulanması doğal tamsayı türüyle gidebilir? (En önemli olgu muhtemelen 8 bitlik tamsayılar ve keyfi duyarlıklı tamsayılar imzalı veya imzasız, 32 bit tamsayı imzasız edilir.)
Martin Ender

iyi, ben ezoterik wiki buldum oldu. evet, çünkü tercümanınız mekanizmalarının bu özelliğe dayandığı diğer kipple programlarıyla uyumlu olmayabilir

Hata durumunda davranış hakkında daha spesifik olabilir misiniz? Böylece yanlış bir cevap verebiliriz veya bir hata yayabiliriz, ancak hatayı yazdıramayız?
Alex

@Alex A. Evet, çünkü programın çıktısı olarak kabul edilebilir ve hata mesajıyla aynı çıktıya sahip olabilen bir kipple programı yapabilirsiniz. Ayrıca "daha ucuzdur" (daha az karakter kullanır), bir hata mesajı yazdıran bir fonksiyona / ifadeye sahip olmamaktır.

3
Bir kaynak programda hangi boşluk oluşabilir? iKaynak programı stdin'den alırsam nasıl girdi isteyebilirim ?
orlp

Yanıtlar:


6

C, 709702 bayt

Bayt skoru, yeni satırlar kaldırılabilir (kaldırılabilir), ancak okuma kolaylığı için buraya yeni satırlarla gönderirim:

#define R return
#define C ;break;case
c[999]={};*P=c;*S[28];M[99999]={};t;*T;
u(s,v){S[s]+=28;*S[s]=v;
if(s>26){for(t=v/10;t;t/=10)S[s]+=28;T=S[s];do{*T=48+v%10;T-=28;}while(v/=10);}}
o(s){t=S[s]-M>27;S[s]-=28*t;R S[s][28]*t;}
I(s){R s<65?27:s-97;}
O(int*p){if(!isdigit(*p))R o(I(*p));
for(;isdigit(p[-1]);--p);for(t=0;isdigit(*p);t*=10,t+=*p++-48);R t;}

main(i,a){for(i=0;i<28;++i)S[i]=M+i;
for(;~(*++P=getchar()););P=c+1;
for(;;){i=I(P[-1]);switch(*P++){
case 35:for(;*P++!=10;)
C'<':u(i,O(P))
C'>':u(I(*P),O(P-2))
C'+':u(i,*S[i]+O(P))
C'-':u(i,*S[i]-O(P))
C'?':if(!*S[i])S[i]=M+i
C'(':for(i=1,T=P;i;++T)i+=(*T==40)-(*T==41);if(S[I(*P)]-M<28)P=T;else u(26,P-c)
C')':P=c+o(26)-1
C-1:for(;i=o(14);)putchar(i); R 0;}}}

Derleyin gcc -w golf.c( -wakıl sağlığınız için uyarıları susturur).

iAsker, kodu stdin'den alırsanız nasıl yapılacağına dair soruşturmamıza henüz yanıt vermediğinden , girdi dışındaki her şeyi destekler . Sözdizimi hatalarını bildirmez.


ana gönderinin yorumlarında "i" yığını ile ilgili sorunuza cevap verdim.

btw kipple programlarını nasıl okuyor? komut argümanlarıyla mı? nasıl kullanmalıyım?

@GLASSIC Programın stdin ile ilgili olmasını beklemektedir.
orlp

Ne zamana kadar ? Hariç nasıl başlanır?

@GLASSIC Sadece programı stdin üzerinden geçirin. Örn ./a.out < prime.k.
orlp

3

Ruby, 718 bayt (şu anda rekabet etmiyor)

çok yorgunum

Dosya bir komut satırı bağımsız değişkeni olarak yüklenir ve girdi STDIN aracılığıyla gönderilir. Alternatif olarak, ikaydınıza girmeniz gerekmiyorsa dosyayı STDIN içine ekleyin .

Spesifikasyon ile ilgili bazı karışıklıklar nedeniyle, mevcut sürüm a<b>cdüzgün işlemiyor ve bu nedenle düzeltilene kadar rekabet etmiyor .

a<b>cdüzeltildi. Ancak, asal işlevler çalıştırılırken yine de yanlış sonuç döndürür, bu nedenle yine de rakipsiz bir yanıt olarak kalır.

(f=$<.read.gsub(/#.*?\n|\s[^+-<>#()?]*\s/m,' ').tr ?@,?`
t=Array.new(27){[]}
t[9]=STDIN.read.bytes
k=s=2**32-1
r=->c{c=c[0];c[0]==?(?(s[c[1..-2]]while[]!=t[c[1].ord-96]):(c=c.sub(/^(.)<(\D)>(.)/){$1+"<#{t[$2.ord-96].pop||0}>"+$3}.sub(/(\d+|.)(\W)(\d+|.)?/){_,x,y,z=*$~
a=x.ord-96
b=(z||?|).ord-96
q=->i,j=z{j[/\d/]?j.to_i: (t[i]||[]).pop||0}
l=t[a]
y<?-?(x==z ?l[-1]*=2:l<<(l.pop||0)+q[b]
l[-1]-=k while l[-1]>k/2):y<?.?(x==z ?l[-1]=0:l<<(l.pop||0)-q[b]
l[-1]+=k while l[-1]<-k/2-1):y<?>?t[a]+=a<1?q[b].to_s.bytes: [q[b]]:y<???
(t[b]+=b<1?q[a,x].to_s.bytes: [q[a,x]]): l[-1]==0?t[a]=[]:0
z||x}while c !~/^(\d+|.)$/)}
s=->c{(z=c.scan(/(\((\g<1>|\s)+\)|[^()\s]+)/m)).map &r}
s[f]
$><<t[15].reverse.map(&:chr)*'')rescue 0

Yine de +1. Fibonacci programını denedin mi?
edc65

@ edc65 Fibbonacci dizi programı da yanlış bir şey yazdırıyor: 0 1 1 2 4 8 16...Bu bir spec hatası olup olmadığını merak ediyorum
Value Ink

Hayır, Fibonacci programı bok gibi, örneğin çizgi a+0saçmalık
edc65

asal sayılarla ilgili sorun sanırım iç içe kontrol yapıları işlemez, ama yakut hakkında çok şey bilmiyorum, tahminim doğru şüpheliyim.

Bu program /(\((\g<1>|\s)+\)|[^()\s]+)/m, belirteçleri ve belirteç gruplarını bölmek için kullandığı yinelemeli normal ifade eşleşmesi nedeniyle iç içe geçmiş ebeveyn gruplarını düzgün işlemelidir . ( Regex101 üzerinde test edin ). Muhtemelen ayrıştırma işlemimin geri kalanında bir hata, ama nerede olduğunu bilmiyorum.
Değer Mürekkebi
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.