Baskı, Artış, Azalış, Diğer Ad - Prindeal'ı Yorumlayın


30

Prindeal (belirgin ilkelerle-dee-al ) yeni bir ezoterik : sadece dört komutları vardır programlama dili pr int , içinde eksiltme , de eksiltme ve diğ ıas . Minimalizmine rağmen, Prindeal'de dört komutu akıllıca birleştirerek karmaşık matematiksel işlemler yapılabilir.

Bu kodda golf mücadelesinde göreviniz, Prindeal kodunu çalıştırabilecek en kısa programı yazmaktır.

Teknik özellik uzun ama mümkün olduğunca netleştirmeye çalıştım ve Prindeal'ı öğrenmek için çaba sarf ederseniz, oldukça şık olacağına inanıyorum!


Kavrama Prindeal

Ön İşleme

Bir Prindeal programı yorumlanmadan önce, bu şeylerin bu sırayla kaldırılması gerekir:

  1. #Çizginin bitimine kadar olan işaretten sonra herhangi bir şey , artı #kendisi. (Bu yorumlar.)
  2. Herhangi bir satırdaki sondaki boşluk.
  3. Tamamen boş satırlar.

Örneğin, Prindeal programı

p cat #The next line has 7 trailing spaces.
p dog       

#p mouse

önceden işlenmiş olur

p cat
p dog

Bundan sonra bu ön işleme adımının atıldığını varsayacağız.

Değişkenler

Nasıl kullanıldığını göstermeden önce değişkenleri hızlıca tanımlamamız gerekir.

Değişkenler (ve değişkenlere referanslar), Prindeal komutlarının argümanlarına iletilen şeydir. Değişkenler her zaman globaldir , bu nedenle bir değişkende yapılan değişiklikler, nerede olursa olsun, her yere yansıtılır.

Her değişken, negatif olmayan isteğe bağlı bir tam sayı tutar (0, 1, 2, 3, ...). Değişkenlerin önceden başlatılması gerekmez - her zaman ilk kullanıldığında veya çağrıldığında 0 değeriyle başlarlar .

- Bir değişken adı bir rakam ile başlamaz alphanumerics ve alt çizgilerden oluşan bir boş olmayan bir dize olabilir [a-zA-Z_][0-9a-zA-Z_]*de regex . Büyük / küçük harfe duyarlıdır spiny_lumpsuck3rve Spiny_lumpsuck3rfarklı değişkenlerdir.

infaz

Prindeal zorunlu bir programlama dilidir. Bir Prindeal programı çalıştırıldığında, ifadeleri yukarıdan aşağıya doğru yürütülür ve ardından program sona erer.

Bir Prindeal programındaki girintili olmayan her satır, bağımsız değişkenleri alabilen veya vermeyen tek bir komutun yürütülmesini içeren bir ifadedir.

Girintili satırlar yalnızca diğer ad komutlarından sonra gerçekleşir . Spesifik olarak, tam olarak tek boşluklarla girintili üç satır her takma komuttan sonra oluşur ve bunun bir parçası olarak kabul edilir. Yani takma ifadeler gerçekten dört satırdır. (Bir satır olabilirler, dördü sadece daha okunaklı.)

Takma Olmayan Tablolar

Diğer ad hariç, bir Prindeal programındaki her ifade şu şekildedir:

[command name] [argument 1] [argument 2] [argument 3] ...

İsteğe bağlı sayıda argüman olabilir (hiçbiri dahil değil). Her argüman her zaman bir değişkendir (( diğer adı tartışırken göreceğimiz gibi ) bir değişkene referanstır .

Yürütüldüğünde, her ifade, hatalarla karşılaşılıp karşılaşılmadığına bağlı olarak bir başarısızlık veya başarı olarak işaretlenir . (Bu yalnızca takma adı kullanmaya başladığımızda gerçekten önemlidir .)

Yerleşik baskı , artırma ve azaltma , yukarıdaki formdaki ifadelerdir. İşte yaptıkları:

  1. print komut adına sahiptir pve bir argüman alır. Girilen değişkenin adını ve değerini (ondalık olarak) "=", sonra bir yeni satırla ayırarak yazdırır. Her zaman bir başarı olarak işaretlenir .

    Örneğin, Prindeal programı

    p _MyVariable_321
    p screaming_hairy_armadillo
    

    çıktı

    _MyVariable_321 = 0
    screaming_hairy_armadillo = 0
    

    çünkü tüm değişkenler 0'dan başlar. (Eşittir işaretinden önceki ve sonraki boşluklar gereklidir.)

  2. artışın komut adı vardır ive bir argüman alır. 1 tarafından iletilen değişkenin değerini artırır. Her zaman başarılı olarak işaretlenir .

    Örneğin, program

    i alpaca
    p alpaca
    i alpaca
    p alpaca
    

    çıktı

    alpaca = 1
    alpaca = 2
    

    Daha alpacaönce hiç erişilmemiş olmasına rağmen, 0'dan 1'e nasıl artırıldığını unutmayın .

  3. azaltma komut adına sahiptir dve bir argüman alır. Girilen değişken sıfırdan farklı ise değeri 1 ile düşürülür ve ifade başarılı olarak işaretlenir . Girilen değişken 0 ise, hiçbir şey yapılmaz ve ifade bir hata olarak işaretlenir .

    Örneğin, program

    i malamute
    p malamute
    d malamute    #success
    p malamute
    d malamute    #failure
    p malamute
    d akita       #failure
    p akita
    

    çıktı

    malamute = 1
    malamute = 0
    malamute = 0
    akita = 0
    

    0 değerine sahip bir değişkeni azaltmanın hata üretmenin tek yolu olduğuna dikkat edin .

Diğer Ad Bildirimi ve Diğer Ad Komutları

Takma komutu özel bir sözdizimi vardır ve yeni komutlar tanımlamak için kullanılabilir, çünkü en güçlüdür. Takma komut adıdır ave bir takma ad deyimi forma sahiptir:

a [name of new command]
 [statement A]
 [statement B]
 [statement C]

Her birinin [statement X]herhangi bir diğer adı olmayan ifadeyi, yani formlu bir şeyi temsil ettiği yerde [command name] [argument 1] [argument 2] [argument 3] ....

Aliased komutunun adı [name of new command]boş olmayan herhangi bir alfanümerik dize ve rakamlı bir [a-zA-Z_][0-9a-zA-Z_]*regex ile başlamayan alt çizgiler olabilir.

(Bu, değişkenlerle aynı ad grubudur, ancak takma komutlar ve değişkenler, farklı yerlerde kullanılan farklı şeylerdir . Bir değişken, kötü sonuçları olmayan bir komutla aynı şekilde adlandırılabilir.)

Bir alias ifadesi çalıştırıldığında, orijinal dört p i d akomutun yanına yeni bir komut eklenir . Yeni komut, [command name]in ifadeleri olarak kullanılabilir ve diğer tüm diğer alias olmayan komutlar gibi bağımsız değişkenlerle çağrılabilir .

Bir takma komut adı olan bir ifade çalıştırıldığında, orijinal alias deyiminden tam olarak iki ifade daha çalıştırılır:

  • [statement A] her zaman çalıştırılır
  • [statement B]eğer çalıştırılan [statement A]bir oldu başarı
  • [statement C]eğer çalıştırılan [statement A]bir oldu başarısızlık

A, B ve C İfadeleri her zaman tembel olarak çalıştırılır , yani çalıştırıldığı sırada anında değerlendirilirler.

Yürütme bittiğinde , aliased komutu B veya C ifadesiyle aynı başarı veya başarısızlık bayrağıyla işaretlenir, hangisi çalıştırıldıysa . ( takma ifadelerin kendilerinin kendi içlerinde bulunamadıkları için işaretlenmeleri gerekmez.)

Diğer Ad Örneği 1

Diyelim ki değişkeni frogiki kat artıran yeni bir komut istiyoruz . Bu diğer ad ifadesi bunu başarır:

a increment_frog_twice
 i frog
 i frog
 d frog

Bildirimi A ( i frog) her zaman çalıştırmak ve her zaman olduğu gibi işaretlenir başarı deyimi B (böylece i frogde her zaman çalıştırılır) ve değişken frog böylece 2 ile artırılır increment_frog_twicekomut her zaman olduğu gibi işaretlenir başarı tablosu B daima çalıştırılması nedeniyle ve B her zaman olduğu başarı . C ( d frog) ifadesi hiçbir zaman çalıştırılmaz.

Yani çıktı

a increment_frog_twice
 i frog
 i frog
 d frog
p frog
increment_frog_twice
p frog

olabilir

frog = 0
frog = 2

Bu örneği genelleştirebiliriz, böylece herhangi bir değişkenin takma komutuna bir argüman vererek iki kez artırılması mümkündür.

Bir alias ifadesinde, 1, 2, 3, vs. tamsayıları aliased komutuna geçirilen 1., 2., 3. vb. Argümanları temsil eder. (Bu argümanlar düz değişkenler veya değişkenlerin kendilerine referanslar olabilir.) Bu sayılar yalnızca bir alias ifadesinde A, B ve C ifadesinin argümanlarında görünebilir . Başka bir yerde görünmeleri onların için bir anlam ifade etmiyor.

Diğer Ad Örneği 2

Bu, son örneği genelleştirir - girilen herhangi bir değişken increment_twice2 ile artacaktır 1, çünkü girilen ilk argümana bir referans:

a increment_twice
 i 1
 i 1
 d 1 #never reached
p toad
increment_twice toad
p toad

Bu programın çıktısı

toad = 0
toad = 2

Daha sonra iki argüman alan ve increment_twiceher ikisini de çağıran başka bir komutu takma ad verebiliriz:

a increment_twice
 i 1
 i 1
 d 1 #never reached
a increment_both_twice
 increment_twice 1
 increment_twice 2
 d 1 #never reached
increment_both_twice platypus duck
p platypus
p duck

Buradaki çıktı olacaktır.

platypus = 2
duck = 2

Aliased komutlarının özyinelemeli olabileceğini anlamak önemlidir, çünkü gerçek güçleri yatar. Örneğin, 0'a iletilen herhangi bir değişkeni ayarlayan bir komut yapabiliriz:

Diğer Ad Örnek 3

set_to_zeroKomut bir argüman alır ve 0'a onun değişken belgeleri ve bir şekilde işaretlenir başarı yapıldığında:

a set_to_zero
 d 1
 set_to_zero 1
 i _dummy_
i oryx
i oryx
i oryx
p oryx
set_to_zero oryx
p oryx

Bu programın çıktısı

oryx = 3
oryx = 0

Olan şu ki set_to_zero oryx, çalıştırıldığında d 1başarılı bir şekilde oryx3'ten 2'ye düşürür , sonra tekrar set_to_zero 1aranır set_to_zero oryx. Böylece süreç d 1bir başarısızlık olana kadar tekrar eder , yinelemeyi durdurur ve _dummy_değişkeni arttırır, böylece bir başarı elde edilir.


Meydan okuma

Prindeal kodunu tam olarak yukarıda açıklandığı şekilde çalıştırabilecek bir program yazın. Prindeal kodunu stdin, komut satırı veya metin dosyası olarak alın. Prindeal programının çıktısını stdout'a veya dilinizin en yakın alternatifi olarak yazdırın.

Alternatif olarak, kodu bir dizge olarak alan ve çıktı dizesini basan ya da döndüren bir işlev yazabilirsiniz.

Ek olarak şunu varsayabilirsiniz:

  • Giriş Prindeal kodu yalnızca yeni satırlar ve yazdırılabilir ASCII ve (isteğe bağlı olarak) boş bir satırla bitecek şekilde yazacaktır .
  • Giriş kodu geçerli Prindeal - iyi biçimlendirilmiş ve sözdizimsel olarak doğru olacaktır.
  • Kodun çalıştırılması, sonsuz döngüler veya tanımlanmamış komutlara veya verilmemiş bağımsız değişkenlere geçersiz referanslar üretmez.
  • Komut adları p, i, dve aüzerinde ad verilmiş asla. ( Değişkenlerin bu isimlere sahip olmayacağını varsaymayabilirsiniz.)

Ayrıca, değişken değerleriniz gerçekten isteğe bağlı bir tamsayı olup olmadığı da önemli değildir, çünkü yalnızca 1000'den daha küçük sayılar test edilecektir. Ayrıca, dilin tekrarlama limitleri ( Python gibi ) varsa, aşağıdaki test programı çalıştığı sürece daha karmaşık Prindeal programlarının karşılaşabileceği bir sorun yoktur.

Test programı

Burada kukla değişkenlerin ( _konvansiyonla başlayarak ) ve birçok yardımcı takma adın kullanılmasıyla toplama, çarpma ve üsteleme işlemlerini oluşturan geniş bir Prindeal programı :

#Command Definitions:
a s             #flag as a success
 i _
 d _
 d _
a f             #flag as a failure
 d _
 d _
 d _
a z             #1 = zero
 d 1
 z 1
 s
a n             #1 = one
 z 1
 i 1
 s
a move          #2 += 1, 1 = zero
 moveH 1 2
 move 1 2
 s
a moveH         #move helper
 d 1
 i 2
 f
a dupe          #2 += 1, 3 += 1, 1 = zero
 dupeH1 1 2 3
 dupe 1 2 3
 s
a dupeH1        #dupe helper
 d 1
 dupeH2 2 3
 f
a dupeH2        #dupe helper
 i 1
 i 2
 s
a copy          #2 = 1
 z 2
 copyH 1 2
 s
a copyH         #copy helper
 dupe 1 2 _copy
 move _copy 1
 s
a addTo         #1 += 2
 copy 2 _add
 #testing comments #
 move _add 1#in weird places # just because #
 s
#it's a g##d idea
###
a add           #1 = 2 + 3
 #its a good idea
 z 1
 addH 1 2 3
 s
##

#
a addH          #add helper
#this is a comment
 addTo 1 2 #as is this
 addTo 1 3
 s
a mul           #1 = 2 * 3
 mulH1 1 2
 mulH2 1 3
 s
a mulH1         #mul helper
 z 1
 copy 2 _mul
 s
a mulH2         #mul helper
 mulH3 1 2
 mulH2 1 2
 s
a mulH3         #mul helper
 d _mul
 addTo 1 2
 f
a mulBy         #1 *= 2
 mul _mulBy 1 2
 copy _mulBy 1
 s
a pow           #1 = 2^3
 powH1 1 3
 powH2 1 2
 s
a powH1         #pow helper
 n 1
 copy 2 _pow
 s
a powH2         #pow helper
 powH3 1 2
 powH2 1 2
 s
a powH3         #pow helper
 d _pow
 mulBy 1 2
 f

#Running Tests:
p A
p B
p C
n A         #A = 1
n B         #B = 1
add C A B   #C = A + B = 1 + 1 = 2
p ____
p A
p B
p C
add B A C   #B = A + C = 1 + 2 = 3
p ____
p A
p B
p C
mul d B C   #d = B * C = 3 * 2 = 6
p ____
p d
mulBy d B   #d = d * B = 6 * 3 = 18
p ____
p d
d A         #A = A - 1 = 1 - 1 = 0
mulBy d A   #d = d * A = 18 * 0 = 0
p ____
p d
pow A C B   #A = C ^ B = 2 ^ 3 = 8
p ____
p A
p B
p C
pow A B C   #A = B ^ C = 3 ^ 2 = 9
p ____
p A
p B
p C
pow C A B   #C = A ^ B = 9 ^ 3 = 729
p ____
p A
p B
p C

(Bu kodla oynuyorsanız, aynı değişken bir argüman olarak birden çok kez verilirse birçok komutun başarısız olacağını unutmayın. Bu kolayca düzeltilebilir, ancak sonuçtaki kod daha uzundur.)

Prindeal tercümanınız tam olarak çıktı üretebilmelidir:

A = 0
B = 0
C = 0
____ = 0
A = 1
B = 1
C = 2
____ = 0
A = 1
B = 3
C = 2
____ = 0
d = 6
____ = 0
d = 18
____ = 0
d = 0
____ = 0
A = 8
B = 3
C = 2
____ = 0
A = 9
B = 3
C = 2
____ = 0
A = 9
B = 3
C = 729

puanlama

Bayt cinsinden en kısa kod kazanır. Tiebreaker daha önceki bildirime gidiyor.

Brownie Bonus: Prindeal'da harika bir program yaz. Toplama ve çarpma yaptım, çıkarma veya bölme yapabilir misiniz?


Ah, sanırım bir kereliğine Pyth'i rahat bırakıp bir Lisp çekeceğim! Bir soru - fonksiyonlar ve değişkenler tamamen farklı ad alanlarında yaşar, değil mi? Bu yüzden, ben artırabilirim pve sonra p phangisi 1 yazdırabilir?
orlp

@orlp Doğru. (İçinde bununla ilgili bazı notlar var.)
Calvin'in Hobileri

2
Dil adını gördüğümde PRNDL'yi düşünen tek kişi ben olamam.
Downgoat

Diğer ad komutuna geçirilecek maksimum argüman var mı?
Zach Gates,

@ZachGates Hayır
Calvin'in Hobileri

Yanıtlar:


9

Pyth, 162 136 bayt

JfTmchcd\#).zKHW<ZlJI!e=T@J~+Z1=@Tk)=k0 .x=J+]h=Nm.xL@Tskd@K=NhT+]+tN0>J~Z0,=Y.x@H=eT0?qN\pps[Td\=dYb)?xGN?qN\iXHThY?YXTH_1=k1XKT:JZ=+Z3

Gösteri.

Değişkenleri inlining ve gelen değiştirerek 26 karakterden dışarı golfed Ive Eesaslı denetim akışı için ?ve .xesaslı denetim akışı.

İlk defa Pyth'ta değişkenlerim bitti. Pyth ( bdkGHNTYve JK) içindeki her bir değişken kullanımdaydı ve ben byeni satır olarak kullanmak istedim . Neyse ki, Nprogramın farklı bölümlerinde birbirinden tamamen farklı iki anlam ifade edebildim ve bu yüzden hala çalışıyor.

Ungolfed (-m ile çalıştır):

JfTmchcd\#).z
KH
W<ZlJ
  I!e=T@J~+Z1
    =@Tk)
  =k0
     .x
      =J+]h=Nm.xL@Tskd@K=NhT+]+tN0>J~Z0
      ,
        =Y.x@H=eT0
        ?qN\p
          ps[Td\=dYb)
          ?xGN
            ?qN\i
              XHThY
              ?Y
                XTH_1
                =k1
            XKT:JZ=+Z3

3
Ben hala onunla bile ne olduğunu söyleyemem seviyorum ungolfed ...
Jerry Jeremiah

Bu,
Pyth'in

8

Python 2, 600 584 397 373 bayt

Bu benim kendi golf referans çözümüm. Atıf verildiği sürece, herkes kendi cevabını kullanarak onu geliştirebilir veya mantığını izleyebilir.

Bu konudaki en güzel bölüm, hiçbir özyinelemenin yapılmadığı, dolayısıyla Python'un özyineleme sınırında hiçbir zaman sorun yaşamaması. Örneğin, SP Countup Prindeal programı süresiz olarak devam edebilir.

p=filter(len,[l.split('#')[0].split()for l in input().split('\n')]);m={};v={};i=0
while i<len(p):
 s=p[i]
 if'('in`s`:s=s[f]
 n,f=s[0],0
 if n in m:a,b,c=([s[int(g)]if g.isdigit()else g for g in t]for t in m[n]);p=[a,(b,c)]+p[i+1:];i=0;continue
 s=s[1]
 q=v.get(s,0)
 if'd'>n:m[s]=p[i+1:i+4];i+=3
 elif'i'<n:print s,'=',q
 elif'd'<n:v[s]=q+1
 elif q:v[s]-=1
 else:f=1
 i+=1

Alınan program dizgisinde, yeni satırlardan kaçan, örneğin kaçan bir program
'p _MyVariable_321\np screaming_hairy_armadillo'.

Ben çeşitli golf ipuçları aldı Sp en ve Pietu en cevapları. Teşekkürler beyler :)


6

Python 3, 345 336 335 328 bayt

a=0
A={}
V={}
def f(l):
 if l[0]in"d p i":c,u=l;U=V[u]=V.get(u,0)+"pi".find(c);S=U<0;V[u]+=S;c<"p"or print(u,"=",U)
 else:d=lambda q:[w.isdigit()and l[int(w)]or w for w in A[l[0]][q]];S=f(d(1+f(d(0))))
 return S
for z in open("P"):
 l=z.split("#")[0].split()
 if"a "==z[:2]:a,s,*x=3,l[1]
 elif l*a:x+=l,;a-=1;A[s]=x
 elif l:f(l)

(@Orlp sayesinde -6 bayt)

Hala golf oynuyorum. Programın adlı bir dosyada saklandığını varsayar P.

Çağrıları flambda içine koymak dbirkaç bayttan tasarruf sağlar, ancak son test durumunun maksimum özyineleme derinliğine ulaşmasını sağlar.

Bazı Prindeal programları

İşe yaramaz çıkarma programı

İşte işe yaramaz bir çıkarma programı . İşe yaramaz çünkü doğru şekilde çıkarsa bile, başarı / başarısızlık buna göre geri dönmez.

Çıktı şöyle olmalıdır:

a = 15
b = 6
__________ = 0
a = 9
b = 6

Saymak

a helper
 p 1
 countup 1
 i success

a countup
 i 1
 helper 1
 d failure

countup n

Yukarı sayar ve nsonsuza kadar yazdırır . Tercüman hızı için bir test olarak çalışabilir (klavyenin kesilmesindeki uzun geri dönüşlere dikkat edin).


2
Bu sorudaki herkes bu golfü kaçırdı, nedenini anlamıyorum. l[:(l+"#").find("#")]ve tüm varyasyonları basit bir şekilde değiştirilebilir l.split('#')[0].
orlp

@ orlp Oraya odaklandım findki , orada olmasaydım splitbile, yapabileceğinizi unuttum #. Thanks :)
Sp3000

6

JavaScript (ES6), 273 258

Düzenleme hatalar düzeltildi ve gerçek bir test paketi ekledi.

Baştaki boşlukları ve yeni satırları saymamak.

Elbette biraz daha golf oynayabilirsin.

Şimdi bir açıklama yazmak için çok yorgunum, bence geçici değerleri (parametreler) canlı tutmak için kapak kullanmanın iyi bir örneği.

Snippet'i EcmaScript 6 uyumlu bir tarayıcıda çalıştırma testi (özellikle MSIE değil Chrome değil. Firefox'ta test ettim, Safari 9 gidebilirdi)

F=p=>(
  p=p.match(/^[^#\n]+/gm).filter(r=>r.trim(o='',v=[])),
  s={
    '':_=>1,
    p:a=>o+=a+` = ${v[a]||0}\n`,
    i:a=>v[a]=-~v[a],
    d:a=>v[a]&&v[a]--,
    a:(n,j)=>s[n]=(u,t,a)=>x(p[!x(p[j+1],0,a,1)+j+2],0,a,1)
  },
  p.map(x=(r,i,w,l,a=r.split(/ +/).slice(l).map(x=>-x?w[x]:x))=>s[a[0]](a[1],i,a)),
  o
)

// TEST

$('#O tr').each(function() {
  var $cells = $(this).find('td')
  var prg = $cells.eq(0).text()
  console.log(prg)
  var output = F(prg)
  $cells.eq(1).text(output)
})
#O td { vertical-align:top; white-space: pre; border: 1px solid #888; font-family:monospace }
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<table>
<tr><th>Program</th><th>Outpout</th></tr>
<tbody id=O>  
<tr><td>p _MyVariable_321
p screaming_hairy_armadillo</td><td></td></tr>
<tr><td>i alpaca
p alpaca
i alpaca
p alpaca</td><td></td></tr>
<tr><td>i malamute
p malamute
d malamute    #success
p malamute
d malamute    #failure
p malamute
d akita       #failure
p akita</td><td></td></tr>
<tr><td>a increment_frog_twice
 i frog
 i frog
 d frog
p frog
increment_frog_twice
p frog</td><td></td></tr>
<tr><td>a increment_twice
 i 1
 i 1
 d 1 #never reached
a increment_both_twice
 increment_twice 1
 increment_twice 2
 d 1 #never reached
increment_both_twice platypus duck
p platypus
p duck</td><td></td></tr>
<tr><td>a set_to_zero
 d 1
 set_to_zero 1
 i _dummy_
i oryx
i oryx
i oryx
p oryx
set_to_zero oryx
p oryx</td><td></td></tr>
<tr><td>#Command Definitions:
a s             #flag as a success
 i _
 d _
 d _
a f             #flag as a failure
 d _
 d _
 d _
a z             #1 = zero
 d 1
 z 1
 s
a n             #1 = one
 z 1
 i 1
 s
a move          #2 += 1, 1 = zero
 moveH 1 2
 move 1 2
 s
a moveH         #move helper
 d 1
 i 2
 f
a dupe          #2 += 1, 3 += 1, 1 = zero
 dupeH1 1 2 3
 dupe 1 2 3
 s
a dupeH1        #dupe helper
 d 1
 dupeH2 2 3
 f
a dupeH2        #dupe helper
 i 1
 i 2
 s
a copy          #2 = 1
 z 2
 copyH 1 2
 s
a copyH         #copy helper
 dupe 1 2 _copy
 move _copy 1
 s
a addTo         #1 += 2
 copy 2 _add
 #testing comments #
 move _add 1#in weird places # just because #
 s
#it's a g##d idea
###
a add           #1 = 2 + 3
 #its a good idea
 z 1
 addH 1 2 3
 s
##

#
a addH          #add helper
#this is a comment
 addTo 1 2 #as is this
 addTo 1 3
 s
a mul           #1 = 2 * 3
 mulH1 1 2
 mulH2 1 3
 s
a mulH1         #mul helper
 z 1
 copy 2 _mul
 s
a mulH2         #mul helper
 mulH3 1 2
 mulH2 1 2
 s
a mulH3         #mul helper
 d _mul
 addTo 1 2
 f
a mulBy         #1 *= 2
 mul _mulBy 1 2
 copy _mulBy 1
 s
a pow           #1 = 2^3
 powH1 1 3
 powH2 1 2
 s
a powH1         #pow helper
 n 1
 copy 2 _pow
 s
a powH2         #pow helper
 powH3 1 2
 powH2 1 2
 s
a powH3         #pow helper
 d _pow
 mulBy 1 2
 f

#Running Tests:
p A
p B
p C
n A         #A = 1
n B         #B = 1
add C A B   #C = A + B = 1 + 1 = 2
p ____
p A
p B
p C
add B A C   #B = A + C = 1 + 2 = 3
p ____
p A
p B
p C
mul d B C   #d = B * C = 3 * 2 = 6
p ____
p d
mulBy d B   #d = d * B = 6 * 3 = 18
p ____
p d
d A         #A = A - 1 = 1 - 1 = 0
mulBy d A   #d = d * A = 18 * 0 = 0
p ____
p d
pow A C B   #A = C ^ B = 2 ^ 3 = 8
p ____
p A
p B
p C
pow A B C   #A = B ^ C = 3 ^ 2 = 9
p ____
p A
p B
p C
pow C A B   #C = A ^ B = 9 ^ 3 = 729
p ____
p A
p B
p C  
</td><td></td></tr>
</tbody>
</table>


Test programına başka yorumlar da ekledim ve kodunuzu çalışmaz hale getirmişe benziyorlar.
Calvin'in Hobileri

@ Calvin'sHobbies ilk, hızlı bir yama
edc65

3

C # 6, 653 bayt

İşte girişim, bir Python denizinin ortasında ...

class P{string[]l;string r="";Dictionary<string,int>v=new Dictionary<string,int>();Dictionary<string,int>s=new Dictionary<string,int>();public string R(string t){l=t.Split('\n');for(int i=0;i<l.Length;i++){var z=l[i].Split(' ');if(z[0]=="a"){s.Add(z[1],i);i+=3;}else E(i, null);}return r;}bool E(int n,string[]p){var z=l[n].Split(' ');var a=z.Skip(1).Select(x=>Char.IsDigit(x[0])?p[int.Parse(x)-1]:x).ToArray();if(a.Length>0&&!v.ContainsKey(a[0]))v[a[0]]=0;if (z[0]=="p")r+=$"{a[0]} = {v[a[0]]}\n";else if(z[0]=="i")v[a[0]]++;else if(z[0]=="d")if(v[a[0]]>0)v[a[0]]--;else return false;else{var y=s[z[0]];return E(y+1,a)?E(y+2,a):E(y+3,a);}return true;}}

Genişletildi ve yorumlandı:

class Prindeal
{
    string[] lines;
    string result = "";
    Dictionary<string, int> variables = new Dictionary<string, int>();
    Dictionary<string, int> statements = new Dictionary<string, int>();

    public string Run(string text)
    {
        lines = text.Split('\n');

        for (int i = 0; i < lines.Length; i++)
        {
            // Split on spaces to get the statement and any arguments
            var z = lines[i].Split(' ');

            // Are we defining a new statement?
            if (z[0] == "a")
            {
                // Add to the statements dictionary, step over definition statements
                statements.Add(z[1], i);
                i += 3;
            }
            else
            {
                // Execute the statement
                Execute(i, null);
            }
        }

        return result;
    }

    bool Execute(int lineNumber, string[] parameters)
    {
        // Split on spaces to get the statement and any arguments
        var z = lines[lineNumber].Split(' ');

        // Parse the arguments - if it's a number, get the corresponding 
        // parameter from the calling statement
        var arguments = z.Skip(1).Select(
            x => Char.IsDigit(x[0]) ? 
            parameters[int.Parse(x) - 1] : 
            x)
            .ToArray();

        // If the first argument isn't already in the variables dict, add it
        if (arguments.Length > 0 && !variables.ContainsKey(arguments[0])) variables[arguments[0]] = 0;

        // Print statement, using string interpolation
        if (z[0] == "p")
            result += $"{arguments[0]} = {variables[arguments[0]]}\n";
        // Increment statement
        else if (z[0] == "i")
            variables[arguments[0]]++;
        // Decrement statement
        else if (z[0] == "d")
            if (variables[arguments[0]] > 0)
                variables[arguments[0]]--;
            else
                return false;
        else
        {
            // Get the line number to jump to
            var y = statements[z[0]];

            // Execute A ? B : C
            return Execute(y + 1, arguments) ? Execute(y + 2, arguments) : Execute(y + 3, arguments);
        }

        // If we reach this point, it's from a 'p', 'i' or 'd' statement which has succeeded
        return true;
    }
}

Kullanmak için, sınıfı başlatmanız ve R()yöntemi çağırmanız yeterlidir , örneğin:

string prindealText = new StreamReader("prindeal.txt").ReadToEnd();
Console.WriteLine(new P().R(prindealText));

3

Ortak Lisp, 758 646 619

(progn(set-macro-character #\#(get-macro-character #\;))(setf(readtable-case *readtable*):invert)(#3=defun v(s)(if(boundp s)(eval s)0))(#3# i(s)(set s(1+ (v s))))(#3# d(s)(and(plusp(v s))(set s(1-(v s)))))(#3# p(s)(format t"~A = ~A~%"s(v s)))(defmacro a(n . p)`(#3#,(cadr n)(&rest g)(if,@p)))(#3# k(s)(typecase s(integer`(nth,(1- s)g))(symbol `',s)(t(list*(car s)(mapcar 'k(cdr s))))))(#3# r()(prog(l p q)$(setf p()l(make-string-input-stream(or(read-line()()())(return))))@(when(setf p(read l()()))(push p q)(go @))(if q(return(k(reverse q)))(go $))))(do ((x(r)(r)))((not x))(eval(if(eq(car x)'a)`(,@x,(r),(r),(r))x))))

Bunu içine koy file.lispve örneğin sbcl --script file.lisp; giriş standart giriş akışından okunur.

Bu sürüm ayrıştırır üst kümesini Prindeal ait: pek zorluklar olmadan, bir Prindeal kaynağından tüm Common Lisp erişebilirler. Bunu , intepreter'in bir özelliği olarak görüyorum .

Yorumlanan sürüm

;; copy-readtable is only used during development, so that I do not 
;; mess with my running environment. The real code starts with the
;; progn below, which is superfluous of course inside a let.
(let ((*readtable* (copy-readtable)))

  ;; I use PROGN in the golfed version so that I can have the whole
  ;; program as a unique tree. This allows me to define reader 
  ;; variables like #3=defun in order to gain a few bytes by writing
  ;; #3# instead of defun. Reader variables are removed in
  ;; this human-friendly version.
  (progn
    ;; Let # point to the same reader function as ;
    ;; Of course, ; is still usable as a comment delimiter
    (set-macro-character #\#
                         (get-macro-character #\;))

    ;; :invert does what is necessary to enable case-sensitive reading
    ;; and printing of symbols
    (setf (readtable-case *readtable*) :invert)

    ;; value of symbol, or zero
    (defun v(s)(if(boundp s)(eval s)0))

    ;; increment
    (defun i(s)(set s(1+ (v s))))

    ;; decrement
    (defun d(s)(and(plusp(v s))(set s(1-(v s)))))

    ;; print
    (defun p(s)(format t"~A = ~A~%"s(v s)))

    ;; alias: wrap an "if" inside a "defun".
    ;; YES, that means you can redefine ANY lisp function with "a" !
    ;; A safer version would properly intern symbols in a dedicated package.
    ;;
    ;; Notice the G variable.  We take advantage of the "unhygienic"
    ;; (what a bad adjective) nature of macros to create a context
    ;; where G is bound to the argument list. The same G is referenced
    ;; implicitely later.
    (defmacro a(n . p)`(defun,(cadr n)(&rest g)(if,@p)))

    ;; Canonicalize expressions:
    ;;
    ;; - if s is a symbol, return s quoted. All functions manipulate
    ;; symbols in order to allow the undeclared use of variables. With
    ;; symbols, we can check for boundness.
    ;;
    ;; - if s is an integer, then we are inside an alias definition. The
    ;; integer is replaced by an access to the s'th element of the
    ;; implicit argument list G using (nth (1- s) g). G will be bound
    ;; when the expressions is injected in the defun corresponding to
    ;; the alias, or else an error will be signaled: either because G
    ;; is unbound, or because you defined a variable named G which is
    ;; by construction not a list. Since we do not sanitize properly
    ;; the input, you could bind G globally to a list, but that would be
    ;; nasty.
    ;; 
    ;; - Finally, if s is a list, apply k to all but the first
    ;; elements of s.  The first element is a symbol but we do not
    ;; need to quote it because we want to call the function
    ;; associated with the symbol. Due to the Lisp-2-ness
    ;; of Common Lisp, functions and variables can coexist
    ;; with the same name.
    ;;
    (defun k(s)(typecase s
                 (integer`(nth,(1- s)g))
                 (symbol`',s)
                 (t(list*(car s)(mapcar #'k(cdr s))))))

    ;; Reader function
    (defun r()
      (prog (l ; current line, as an input-stream reading a string
             p ; current read form
             q ; whole line and return value, as a list
             )

         ;; PROG includes an implicit TAGBODY. Below, $ and @ are
         ;; labels for GO statements (gotos).

       $ (setf
          ;; emtpy p
          p ()

          ;; Read a whole line and if we do not fail, build an input
          ;; stream to read from it.
          l (make-string-input-stream
             (or (read-line()()()) ;; try to read a line,
                 (return)          ;; but return from prog if we reach
                                   ;; the end of file.
                 )))
       @ (when (setf p (read l()()))
           ;; Read a lisp expression, put it in p and if p is not nil
           ;; push it into q.  A nil could happen at the end of the
           ;; line or if someone (you know who) inserted an empty list
           ;; in the file being read.
           ;; 
           ;; Thanks to the readtable which now handles comments
           ;; and spaces for us, nothing needs to be done here to
           ;; preprocess the input.

           (push p q) (go @))

         ;; If we read an empty line, q can be nil. In this case, go
         ;; back to $ and read another line. If q is not nil, reverse
         ;; it (we pushed, remember), canonicalize it and return the
         ;; result.
         (if q (return(k(reverse q))) (go $)))
      )

    ;; Read/eval loop.  When reading "(a name)", we read the three
    ;; next lines and append them to the first so that it builds a
    ;; call the the alias definition macro a. Otherwise, just eval x.
    (do((x(r)(r))((not x))
      (eval (if (eq(car x'a))
                `(,@x,(r),(r),(r))
                x)))))

Örnek

~$ sbcl --script file.lisp < testfile

A = 0
B = 0
C = 0
____ = 0
A = 1
B = 1
C = 2
____ = 0
A = 1
B = 3
C = 2
____ = 0
d = 6
____ = 0
d = 18
____ = 0
d = 0
____ = 0
A = 8
B = 3
C = 2
____ = 0
A = 9
B = 3
C = 2
____ = 0
A = 9
B = 3
C = 729

Biz değiştirirseniz evaltarafından printokuma / eval döngüde, o zaman biz değerlendirilmektedir görebilirsiniz:

(a 's (i '_) (d '_) (d '_)) 
(a 'f (d '_) (d '_) (d '_)) 
(a 'z (d (nth 0 g)) (z (nth 0 g)) (s)) 
(a 'n (z (nth 0 g)) (i (nth 0 g)) (s)) 
(a 'move (moveH (nth 0 g) (nth 1 g)) (move (nth 0 g) (nth 1 g)) (s)) 
(a 'moveH (d (nth 0 g)) (i (nth 1 g)) (f)) 
(a 'dupe (dupeH1 (nth 0 g) (nth 1 g) (nth 2 g))
   (dupe (nth 0 g) (nth 1 g) (nth 2 g)) (s)) 
(a 'dupeH1 (d (nth 0 g)) (dupeH2 (nth 1 g) (nth 2 g)) (f)) 
(a 'dupeH2 (i (nth 0 g)) (i (nth 1 g)) (s)) 
(a 'copy (z (nth 1 g)) (copyH (nth 0 g) (nth 1 g)) (s)) 
(a 'copyH (dupe (nth 0 g) (nth 1 g) '_copy) (move '_copy (nth 0 g)) (s)) 
(a 'addTo (copy (nth 1 g) '_add) (move '_add (nth 0 g)) (s)) 
(a 'add (z (nth 0 g)) (addH (nth 0 g) (nth 1 g) (nth 2 g)) (s)) 
(a 'addH (addTo (nth 0 g) (nth 1 g)) (addTo (nth 0 g) (nth 2 g)) (s)) 
(a 'mul (mulH1 (nth 0 g) (nth 1 g)) (mulH2 (nth 0 g) (nth 2 g)) (s)) 
(a 'mulH1 (z (nth 0 g)) (copy (nth 1 g) '_mul) (s)) 
(a 'mulH2 (mulH3 (nth 0 g) (nth 1 g)) (mulH2 (nth 0 g) (nth 1 g)) (s)) 
(a 'mulH3 (d '_mul) (addTo (nth 0 g) (nth 1 g)) (f)) 
(a 'mulBy (mul '_mulBy (nth 0 g) (nth 1 g)) (copy '_mulBy (nth 0 g)) (s)) 
(a 'pow (powH1 (nth 0 g) (nth 2 g)) (powH2 (nth 0 g) (nth 1 g)) (s)) 
(a 'powH1 (n (nth 0 g)) (copy (nth 1 g) '_pow) (s)) 
(a 'powH2 (powH3 (nth 0 g) (nth 1 g)) (powH2 (nth 0 g) (nth 1 g)) (s)) 
(a 'powH3 (d '_pow) (mulBy (nth 0 g) (nth 1 g)) (f)) 
(p 'A) 
(p 'B) 
(p 'C) 
(n 'A) 
(n 'B) 
(add 'C 'A 'B) 
(p '____) 
(p 'A) 
(p 'B) 
(p 'C) 
(add 'B 'A 'C) 
(p '____) 
(p 'A) 
(p 'B) 
(p 'C) 
(mul 'd 'B 'C) 
(p '____) 
(p 'd) 
(mulBy 'd 'B) 
(p '____) 
(p 'd) 
(d 'A) 
(mulBy 'd 'A) 
(p '____) 
(p 'd) 
(pow 'A 'C 'B) 
(p '____) 
(p 'A) 
(p 'B) 
(p 'C) 
(pow 'A 'B 'C) 
(p '____) 
(p 'A) 
(p 'B) 
(p 'C) 
(pow 'C 'A 'B) 
(p '____) 
(p 'A) 
(p 'B) 
(p 'C)

Macroexpansion

Aşağıdaki takma adı tanımını seçersek:

(a 'powH2 (powH3 (nth 0 g) (nth 1 g)) (powH2 (nth 0 g) (nth 1 g)) (s))

... gsözlükte bulunabilecek hiçbir yerde bulunmayan değişkene referanslar görebiliriz . Ancak makro genişlemeden sonra, değerlendirilen gerçek kod:

(defun powH2 (&rest g)
  (if (powH3 (nth 0 g) (nth 1 g))
      (powH2 (nth 0 g) (nth 1 g))
      (s))) 

Şimdi, gtanımlanmakta olan fonksiyonun argüman listesine atıfta bulunmaktadır.


2

Python 2,486 bayt

Bu daha çok golf oynadığım referans çözümdür (şu anda -98 bytes).

import sys;sys.setrecursionlimit(2000)
def r(s):
 n=s[0]
 if n in A:f=lambda i:r([s[int(t)]if'0'<t[0]<':'else t for t in A[n][i]]);return f(1+(f(0)or 0))
 k=s[1]
 if'i'<n:print k,'=',V.get(k,0)
 elif'd'<n:V[k]=-~V[k]if k in V else 1
 elif'a'<n:
    if~-(k in V)or V[k]<1:return 1
    V[k]-=1
 else:A[k]=s[2:]
A={};V={};c=filter(bool,([l,l[:l.find('#')]]['#'in l]for l in input().split('\n')))
while c:
 s=c[0].split();c=c[1:]
 if'a'!=s[0]:r(s)
 else:r(['a',s[1]]+map(str.split,c[:3]));c=c[3:]

Değişiklikler (hatırladığım):

  • otomatik boolean integer dönüşümü ([l,l[:l.find('#')]]['#'in l] ).
  • bir açıklamada küme veya artış (V[k]=-~V[k]if k in V else 1 )
  • daha uzun ifadelere daha fazla takma ad (k=s[1] )
  • Ana döngüde sayaç yok, bunun yerine giriş listesini temizleyin
  • printotomatik olarak boşluk ekleyerek ( print k,'=',V.get(k,0))
  • 1-9 ( '0'<t[0]<':') rakamlarını kontrol etme
  • s değerini döndürmek için ryaklaşık dönüş değerlerini çevirmekreturn
  • dilimleme ve bölme tekrarının kaldırılması ( map(str.split,c[:3])))

1

Python 3, 1322 bayt

golfed:

import re,sys;sys.setrecursionlimit(2000);F,L=filter,list
class P:
 N,O,F=0,{},{}
 def __init__(S,c):
  S.B,S.E={"p":S.P,"i":S.I,"d":S.D,"a":S.L},dict(enumerate(F(None,[i.split('#')[0].rstrip()for i in c.splitlines()])))
  while S.N in S.E:S.X(S.E[S.N])
 def V(S, v, y, z=0):
  if re.match("[\w_][\d\w_]*",v):
   if not v in y:
    if z is not None:y[v]=z
    else:return False
   return True
  return False
 def A(S):S.N+=1
 def P(S,v):
  if S.V(v,S.O):print("{0} = {1}".format(v, S.O[v]));return True
  return False
 def I(S,v):
  if S.V(v, S.O):S.O[v]+=1;return True
  return False
 def D(S,v):
  if S.V(v,S.O)and S.O[v]>0:S.O[v]-=1;return True
  return False
 def L(S,v):
  e=[]
  if S.V(v,S.F,e):
   for i in range(3):S.A();e.append(S.E[S.N].lstrip())
   return True
  return False
 def C(S,c,v):
  def R(Z,v):
   for i in re.findall("\s(\d+)", Z):Z=Z.replace(" %s"%i," %s"%v[int(i)-1])
   return Z
  Q,m,f=map(lambda l:R(l,v),S.F[c])
  if S.X(Q,False):return S.X(m,False)
  return S.X(f,False)
 def X(S,Z,C=True):
  u=re.match("\s?([\w_][\d\w_]*)\s?([\w_][\d\w ]*)?",Z)
  if u:
   c,v=map(lambda i:''if i is None else i,u.groups());v=L(F(None,v.split(' ')))
   if S.V(c,S.F,None):
    T=S.C(c, v)
    if C:S.A()
   elif S.V(c,S.B,None):
    T=S.B[c](*v)
    if C:S.A()
   else:return False
   return T
  return False

Ungolfed:

import re

class Prindeal:
    iline = 0
    local = {}
    udef = {}
    content  = {}

    def __init__(self, c):
        self.built = {
            "p": self.print,
            "i": self.increment,
            "d": self.decrement,
            "a": self.alias,
        }
        self.content = dict(enumerate(filter(None, [i.split('#')[0].rstrip()for i in c.splitlines()])))
        while self.iline in self.content:
            self.execute_line(self.content[self.iline])

    def validate_name(self, varname, stack, default=0):
        if re.match("[\w_][\d\w_]*", varname):
            if not varname in stack:
                if default is not None:
                    stack[varname] = default
                else:
                    return False
            return True
        return False

    def advance_stack(self):
        self.iline += 1

    def print(self, varname):
        if self.validate_name(varname, self.local):
            print("{0} = {1}".format(varname, self.local[varname]))
            return True
        return False

    def increment(self, varname):
        if self.validate_name(varname, self.local):
            self.local[varname] += 1
            return True
        return False

    def decrement(self, varname):
        if self.validate_name(varname, self.local) and self.local[varname] > 0:
            self.local[varname] -= 1
            return True
        return False

    def alias(self, aliasname):
        indexed_lines = []
        if self.validate_name(aliasname, self.udef, indexed_lines):
            for i in range(3):
                self.advance_stack()
                indexed_lines.append(self.content[self.iline].lstrip())
            return True
        return False

    def execute_alias(self, cmd, variables):
        def parse_args(line, variables):
            for i in re.findall("\s(\d+)", line):
                line = line.replace(" %s" % i, " %s" % variables[int(i) - 1])
            return line
        init, success, failure = map(lambda l: parse_args(l, variables), self.udef[cmd])
        if self.execute_line(init, False):
            return self.execute_line(success, False)
        return self.execute_line(failure, False)

    def execute_line(self, line, cont=True):
        valid_execution = re.match("\s?([\w_][\d\w_]*)\s?([\w_][\d\w ]*)?", line)
        if valid_execution:
            cmd, variables = map(lambda i: '' if i is None else i, valid_execution.groups())
            variables = list(filter(None, variables.split(' ')))
            if self.validate_name(cmd, self.udef, None):
                temp = self.execute_alias(cmd, variables)
                if cont:
                    self.advance_stack()
            elif self.validate_name(cmd, self.built, None):
                temp = self.built[cmd](*variables)
                if cont:
                    self.advance_stack()
            else:
                return False
            return temp
        return False

Kullanımı:

P(c)

cMetin içeriği nerede .

Örnekler:

Tek satırlı dizeler kabul edilir:

  • P("p cat")
  • P("p dog\ni dog\np dog")

Çok çizgili dizeler de kabul edilir:

P("""
p dog
i dog
p dog
""")

Veya:

P("""p dog
i dog
p dog""")

Vb.

Notlar:

Bu, tüm test durumları için doğru şekilde çalışır, ancak aşağıdaki durumlarda yineleme sınırına ulaşır:

pow C A B   #C = A ^ B = 9 ^ 3 = 729

Dolayısıyla sys.setrecursionlimit(2000).


1
Bazı baytları kullanır, ancak bunun pow alias ile düzgün çalışmasını sağlamak için sys.setrecursionlimit () yöntemini kullanamaz mıydınız?
Corwin

Yapabilirdim, ancak OP Python gibi dillerin (özyineleme sınırları olan) olduğu gibi kabul edildiğini belirtti. Ancak, OP tarafından istenirse düzeltmeyi ekleyeceğim. @Corwin
Zach Gates

Yeterince adil. Spesifikasyonda bunu kaçırdım. @ZachGates
Corwin

1

Python - 695 688 bayt

def p(v):print v,"=",w.get(v,0)
def i(v):w[v]=w.get(v,0)+1
def d(v):
 if v in w:
<TAB>w[v]-=1
<TAB>if not w[v]:del w[v]
 else:return 1
def a(n,b,d,h):
 def g(*a):
<TAB>i=1;f=b;s=d;t=h
<TAB>for v in a:v=q+v+q;k=q+j(i)+q;f=c(f,k,v);s=c(s,k,v);t=c(t,k,v);i+=1
<TAB>y=u(t,e)if u(f,e)else u(s,e);i=1;return y
 e[n]=g
q="'";w=x={};u=eval;e={'a':a,'d':d,'i':i,'p':p};import sys;l=sys.stdin.readlines();r="";j=str;c=j.replace;sys.setrecursionlimit(2000)
for h in l:
 h = h.strip()
 if not h:continue
 l = h.split();f=l[0];n=f+"("
 if "#" in f:continue
 for g in l[1:]:
<TAB>b=g.find("#")+1
<TAB>if b:g=g[:b-1]
<TAB>if g:n+="'%s',"%g
<TAB>if b:break
 if x:x-=1;d+='"%s)",'%n
 else:x=(f=="a")*3;d=n
 if not x:d+=")\n";r+=d
exec r in e

<TAB> değişmez bir sekme karakteridir.


1

C ++, 1111 bayt

Bu bir C ++ - yapabildiğim kadar aptal.
Bu, daha fazla C ++ yapmak anlamına gelir - ish ve daha az C-ish.
Bu aynı zamanda eşdeğer C programından daha büyük olduğu anlamına gelir.
C ++ ayrıntılı standart kütüphane için Java ile rakip olduğunu düşünüyorum.
VS2013 ve g ++ 4.9.2 ile derlenir (-std = c ++ 11 ile)

#include<array>
#include<iostream>
#include<map>
#include<regex>
#include<sstream>
#include<stack>
#define B std::
#define a first
#define b second
#define c(s);else if(x.a==s)
#define d(n)B getline(B cin,r##n)
#define e(n)r##n=B regex_replace(r##n,q,"$1");
#define f(n)do{d(n);e(n)}while(r##n.empty());
#define g B string
#define h B istream_iterator<g>
#define i p.top().a
#define j p.empty()
#define k B pair
#define u continue;
#define w B back_inserter
typedef B vector<g>s;typedef B array<g,3>A;typedef k<k<long,A>,s>t;B map<g,A>m;B map<g,long>n;B stack<t>p;B regex q("^ *(.*?) *(#.*)?$");int main(){g r0,r1,r2,r3;while(d(0)){e(0)if(r0.empty())u p.push(t{{0,{{r0,"",""}}},{}});bool z;while(!j){k<g,s>x;B istringstream ss(i.b[i.a]);ss>>x.a;B copy(h(ss),h(),w(x.b));s o;B transform(B begin(x.b),B end(x.b),w(o),[](g y){int v=atoi(y.c_str());return v>0?p.top().b[v-1]:y;});z=true;if(0)c("")c("p")B cout<<o[0]<<" = "<<n[o[0]]<<B endl c("i")n[o[0]]++c("d")n[o[0]]-=(z=n[o[0]])c("a"){f(1)f(2)f(3)m.insert(B make_pair(o[0],A{{r1,r2,r3}}));}else{p.push(t{{0,m[x.a]},o});u}while(!j&&i.a)p.pop();if(!j)i.a+=1+!z;}}}

Orijinali aşağıdadır. Herhangi biri aynı anda daha aptalca ve daha kısa hale getirmenin bir yolunu düşünebilecek olursa, lütfen bana bildirin.

#include <array>
#include <iostream>
#include <map>
#include <regex>
#include <sstream>
#include <stack>

typedef std::vector<std::string> List;
typedef std::pair<std::string, List> Statement;
typedef std::array<std::string, 3> Alias;
typedef std::pair<long, Alias> IndexedAlias;
typedef std::pair<IndexedAlias, List> Item;

std::map<std::string, Alias> aliases;
std::map<std::string, long> variables;
std::stack<Item> stack;
std::regex re("^ *(.*?) *(#.*)?$");

int main()
{
    std::string line, line1, line2, line3;
    while (std::getline(std::cin, line)) // control-Z to exit
    {
        line = std::regex_replace(line, re, "$1");
        if (line.empty()) continue;
        stack.push(Item{ { 0, { { line, "", "" } } }, {} });

        bool flag;
        while (!stack.empty())
        {
            Statement statement;
            std::istringstream ss(stack.top().first.second[stack.top().first.first]);
            ss >> statement.first;
            std::copy(std::istream_iterator<std::string>(ss), std::istream_iterator<std::string>(), std::back_inserter(statement.second));

            List arguments;
            std::transform(std::begin(statement.second), std::end(statement.second), std::back_inserter(arguments),
                [](std::string arg){ int i = atoi(arg.c_str()); return i > 0 ? stack.top().second[i - 1] : arg; });

            flag = true;
            if (statement.first == "")
                ;
            else if (statement.first == "p")
                std::cout << arguments[0] << " = " << variables[arguments[0]] << std::endl;
            else if (statement.first == "i")
                variables[arguments[0]]++;
            else if (statement.first == "d")
                variables[arguments[0]] -= (flag = variables[arguments[0]]);
            else if (statement.first == "a")
            {
                do { std::getline(std::cin, line1); line1 = std::regex_replace(line1, re, "$1"); } while (line1.empty());
                do { std::getline(std::cin, line2); line2 = std::regex_replace(line2, re, "$1"); } while (line2.empty());
                do { std::getline(std::cin, line3); line3 = std::regex_replace(line3, re, "$1"); } while (line3.empty());
                aliases.insert(std::make_pair(arguments[0], Alias{ { line1, line2, line3 } }));
            }
            else
            {
                stack.push(Item{ { 0, aliases[statement.first] }, arguments });
                continue;
            }

            while (!stack.empty() && stack.top().first.first) stack.pop();
            if (!stack.empty()) stack.top().first.first += 1 + !flag;
        }
    }

    std::cout << "-- Variables --" << std::endl;
    std::transform(std::begin(variables), std::end(variables), std::ostream_iterator<std::string>(std::cout, "\n"),
        [](std::map<std::string, long>::value_type pair){ std::ostringstream ss; ss << pair.first << " = " << pair.second; return ss.str(); });
    std::cout << "-- Aliases --" << std::endl;
    std::transform(std::begin(aliases), std::end(aliases), std::ostream_iterator<std::string>(std::cout, "\n"),
        [](std::map<std::string, Alias>::value_type pair){ std::ostringstream ss; ss << pair.first << " = [1]:" << pair.second[0] << " [2]:" << pair.second[1] << " [3]:" << pair.second[1]; return ss.str(); });
    std::cout << "---------------" << std::endl;

    return 0;
}

0

Haskell, 1009

Golf oynamak için elimden geleni yaptım; unungolfed kodum 3.000'den fazla karakterden oluşuyordu. Bu noktada tüm fonksiyonların ne yaptığını hatırlayamıyorum, bu yüzden golf oynamak onu neyin kırıp neyin kırmayacağını tahmin etmek anlamına geliyor.

import qualified Data.Map as M
import Control.Monad.State.Lazy
import Data.List
type A=M.Map String
data P=P(A Int)(A([String]->StateT P IO Int))
a f=evalStateT f(P M.empty$M.fromList[("i",\(b:_)->(+1)%b),("d",\(b:_)->pred%b),("p",\(b:_)->i b>>= \v->liftIO(putStrLn$b++"="++show v)>>q 1)])
e(k:l)=do{(P v a)<-get;put.P v$M.insert k(m l)a;q 1}
g t s f= \a->t a>>= \b->if b>0then s a else f a
f%k=f<$>i k>>= \v->if v<0then k#0>>q 0else k#v>>q 1
i k=get>>= \(P v _)->q$M.findWithDefault 0 k v
k#v=get>>= \(P b a)->put$P(M.insert k v b)a
l k=get>>= \(P _ a)->q$a M.!k
f s=let(f:a)=r s in($a)<$>l f>>=id
m(t:s:f:_)=g(k t)(k s)(k f)
k s=let(f:b)=r s in\a->($(map((\y z->if all(\c->c>'/'&&c<':')z then y!!(read z-1)else z)a)b))<$>l f>>=id
n=dropWhileEnd(==' ').takeWhile(not.(=='#')).dropWhile(==' ')
o[]=[]
o(l:ls)|(head.r$l)=="a"=(l:take 3 ls):(o$drop 3 ls)|1>0=[l]:o ls
p s|length s>1=e$(n.tail.head$s):tail s|1>0=f.head$s
q=return
main=join$a.(\s->mapM_ p(o.filter(not.null).map n.lines$s))<$>getContents
r=words
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.