印刷、増分、減分、エイリアス-Prindealの解釈


30

Prindeal(顕著PRIN-ディー-ALは)新しいある難解:4つのつのみコマンド有するプログラミング言語PR INTを crement crement、そして IAS。4つのコマンドを巧みに組み合わせることにより、Prindealで複雑な数学演算を最小限に抑えることができます。

このゴルフのチャレンジの課題は、Prindealコードを実行できる最短のプログラムを作成することです。

仕様は長いですが、できる限り明確にしようとしました。Prindealを学習するための努力をすれば、非常にエレガントであることがわかります。


Prindealの解釈

前処理

Prindealプログラムを解釈する前に、これらのことを次の順序で削除する必要があります。

  1. #記号の後にある行の最後までのすべてと、#それ自体。(これらはコメントです。)
  2. 任意の行の末尾の空白。
  3. 完全に空の行。

たとえば、Prindealプログラム

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

#p mouse

前処理されます

p cat
p dog

ここからは、この前処理ステップが完了したと仮定します。

変数

変数の使用方法を示す前に、変数をすばやく定義する必要があります。

変数(および変数への参照)は、Prindealコマンドの引数に渡されるものです。変数は常にグローバルであるため、変数の変更は、それらがどこで発生しても、どこにでも反映されます。

各変数は、負でない任意精度の整数(0、1、2、3、...)を保持します。変数は事前に初期化する必要はありません-変数は、最初に使用または呼び出されるときに常に値0で始まります。

変数名は、数字[a-zA-Z_][0-9a-zA-Z_]*正規表現で始まらない、英数字とアンダースコアの空でない文字列です。これらは大文字と小文字が区別されるためspiny_lumpsuck3rSpiny_lumpsuck3r異なる変数です。

実行

Prindealは命令型プログラミング言語です。Prindealプログラムが実行されると、ステートメントが上から下の順に実行され、プログラムが終了します。

Prindealプログラムのインデントされていない行はすべて、引数を取る場合と受け取らない場合がある単一のコマンドの実行を伴うステートメントです。

インデントされた行は、エイリアスコマンドの後にのみ発生します。具体的には、すべてのエイリアスコマンドの後に、単一のスペースでインデントされた正確に3行が発生し 、その一部と見なされます。したがって、別名ステートメントは実際には4行の長さです。(1行にすることもできますが、4行は読みやすいだけです。)

エイリアスステートメント

aliasを除き、Prindealプログラムのすべてのステートメントの形式は次のとおりです。

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

任意の数の引数がある場合があります(まったくない場合もあります)。各引数は常に変数または(エイリアスについて説明するときに説明します)変数への参照です

実行が完了すると、エラーが発生したかどうかに応じて、各ステートメントに失敗または成功のフラグが立てられます。(これは、aliasの使用に取り掛かる場合にのみ本当に重要です。)

組み込みのprintincrement、およびdecrementは、上記の形式のステートメントです。彼らがすることは次のとおりです。

  1. printにはコマンド名がpあり、1つの引数を取ります。渡された変数の名前とその値(10進数)を "="で区切り、次に改行を出力します。常に成功としてフラグが付けられます。

    たとえば、Prindealプログラム

    p _MyVariable_321
    p screaming_hairy_armadillo
    

    出力します

    _MyVariable_321 = 0
    screaming_hairy_armadillo = 0
    

    すべての変数が0から始まるためです(等号の前後にスペースが必要です)。

  2. incrementはコマンド名iを持ち、1つの引数を取ります。渡された変数の値を1増やします。常に成功のフラグが立てられます。

    たとえば、プログラム

    i alpaca
    p alpaca
    i alpaca
    p alpaca
    

    出力します

    alpaca = 1
    alpaca = 2
    

    alpaca以前にアクセスされたことがない場合でも、どのように0から1にインクリメントされたかに注意してください。

  3. デクリメントにはコマンド名がdあり、1つの引数を取ります。渡された変数がゼロ以外の場合、その値は1ずつ減分され、ステートメントに成功のフラグが立てられます。渡された変数が0の場合、何も実行されず、ステートメントに失敗のフラグが立てられます。

    たとえば、プログラム

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

    出力します

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

    値が0の変数をデクリメントすることが失敗を生成する唯一の方法であることに注意してください。

エイリアスステートメントとエイリアスコマンド

エイリアスコマンドは、特別な構文を持っており、新しいコマンドを定義するために使用することができますので、最も強力です。エイリアスコマンド名があるa、エイリアスの文の形式は次のとおりです。

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

ここで、それぞれ[statement X]は非エイリアスステートメント、つまりの形式の何かを表します[command name] [argument 1] [argument 2] [argument 3] ...

エイリアスコマンドの名前[name of new command][a-zA-Z_][0-9a-zA-Z_]*、正規表現で数字で始まらない英数字とアンダースコアの空でない文字列です。

(これは変数と同じ名前のセットですが、エイリアス化されたコマンドと変数は異なる場所で使用されるものが異なります。変数はコマンドと同じ名前で、悪影響はありません。)

とき別名文が実行され、新しいコマンドは、元の4一緒に追加されp i d aたコマンド。新しいコマンドは[command name]inステートメントとして使用でき、他の非エイリアスコマンドと同様に引数で呼び出すことができます。

エイリアス化されたコマンド名を持つステートメントが実行されると、元のエイリアスステートメントからさらに2つのステートメントが実行されます。

  • [statement A] 常に実行されています
  • [statement B]成功した場合[statement A]に実行されます
  • [statement C]失敗した場合[statement A]に実行されます

ステートメントA、B、およびCは常に遅延して実行されます。つまり、実行時にその場で評価されます。

実行が完了すると、エイリアス化されたコマンドには、ステートメントBまたはCのいずれか実行された方と同じ成功または失敗フラグが立てられます。(別名ステートメント自体は、その内部で発生することはできないため、フラグを立てる必要はありません。)

エイリアスの例1

変数をfrog2回インクリメントする新しいコマンドが必要だとします。このエイリアスステートメントはそれを実現します:

a increment_frog_twice
 i frog
 i frog
 d frog

ステートメントAは、( i frog)は、常に実行して、いつものようにフラグが設定され、成功 ステートメントB(これi frogも常に実行される)と、変数はfrog ので、2ずつ増えているincrement_frog_twiceコマンドはいつものようにフラグが立てられ、成功ステートメントBが常に実行されるためとBが常にあります成功。ステートメントC(d frog)は実行されません。

したがって、出力は

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

だろう

frog = 0
frog = 2

この例を一般化して、エイリアス化されたコマンドに引数を与えることにより、任意の変数を2回インクリメントできるようにすることができます。

エイリアスステートメント内で、正の整数1、2、3などは、エイリアスコマンドに渡される1番目、2番目、3番目などの引数を表します。(これらの引数は、単純な変数または変数自体への参照である可能性があります。)これらの数値は、別名ステートメントのステートメントA、B、およびCの引数内にのみ表示できます。彼らが他の場所に現れるのは意味がありません。

エイリアスの例2

これは最後の例を一般化します-渡された変数は、渡された最初の引数への参照であるincrement_twiceため、2ずつ増加します1

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

このプログラムの出力は次のようになります

toad = 0
toad = 2

次に、2つの引数を取り、increment_twice両方の引数を呼び出す別のコマンドをエイリアスできます。

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

ここでの出力は次のようになります

platypus = 2
duck = 2

エイリアスされたコマンドは再帰的である可能性があることを理解することが重要です。たとえば、渡された変数を0に設定するコマンドを作成できます。

エイリアスの例3

このset_to_zeroコマンドは1つの引数を取り、その変数を0に設定し、完了すると成功のフラグが立てられます。

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

このプログラムの出力は次のようになります

oryx = 3
oryx = 0

何が起こっているのかは、set_to_zero oryx実行されると、3から2にd 1正常に減少oryxし、その後set_to_zero 1呼び出さset_to_zero oryxれます。これは、再度呼び出すのと同じです。プロセスを繰り返すようになるまでには、d 1ある故障、再帰を停止し、インクリメント_dummy_して変数を成功が生成されます。


チャレンジ

上記のとおり、Prindealコードを実行できるプログラムを作成します。Prdinealコードを、stdin、コマンドライン、またはテキストファイルとして受け取ります。Prindealプログラムの出力をstdoutまたは使用している言語の最も近い代替物に出力します。

または、コードを文字列として受け取り、出力文字列を出力または返す関数を作成できます。

さらに、次のことを想定できます。

  • 入力Prindealコードには、改行と印刷可能なASCIIのみが含まれ、オプションで空行で終了します。
  • 入力コードは有効なPrindealになります-整形式で構文的に正しいです。
  • コードを実行しても、無限ループや、定義されていないコマンドや指定されていない引数への無効な参照は生成されません。
  • コマンド名はpid、およびaオーバーエイリアスされることはありません。(変数にこれらの名前がないと仮定することはできません。)

また、変数値が実際に任意精度の整数でない場合でも、約1000未満の数値のみがテストされるため、問題ではありません。また、言語に再帰制限(Pythonなど)がある場合でも、以下のテストプログラムが機能する限り、より複雑なPrindealプログラムが遭遇する可能性があります。

テストプログラム

これは、ダミー変数(_慣例により開始)と多くのヘルパーエイリアスを使用して、加算、乗算、べき乗の演算を構築する大きなPrindealプログラムです。

#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

(このコードで遊んでいる場合、同じ変数が引数として複数回与えられるとコマンドの多くが失敗することに注意してください。これは簡単に修正できますが、結果のコードは長くなります。)

Prindealインタープリターは、正確な出力を生成できるはずです。

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

得点

バイト単位の最短コードが優先されます。Tiebreakerは以前の提出に進みます。

ブラウニーボーナス:Prindealでクールなプログラムを作成します。加算と乗算を実装しましたが、減算または除算はできますか?


ああ、私は一度Pythを放っておいて、Lispを引き出すと思います!1つの質問-関数と変数はまったく異なる名前空間に住んでいますよね?だからp、増分し、それからp p、1を印刷するでしょうか?
orlp

@orlp正解。(そこにいくつかのメモがあります。)
カルビンの趣味

2
言語名を見たときにPRNDLを考えるのは私だけではありません。
ダウンゴート

エイリアスコマンドに渡される引数の最大数はありますか?
ザックゲイツ

@ZachGatesいいえ
カルビンの趣味

回答:


9

Pyth、162 136バイト

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

デモンストレーション。

変数をインライン化してから変更することで、26個の文字からGolfed IEベースの制御フローに?.xベースの制御フロー。

初めて、Pythの変数が不足しました。Pyth(bdkGHNTYおよびJK)のすべての変数が使用中でありb、改行として使用したかった。幸いなことに、私はNプログラムのさまざまな部分でまったく異なる2つのことを意味するために使用することができたので、それでも機能します。

Ungolfed(-mで実行):

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
私はまだそれがungolfedさえして何をするかわかりませんどのように愛する...
ジェリーエレミヤ

... Pythは非チューリング完全であると結論さて、
エリックOutgolfer

8

Pythonの2、600の 584 397 373バイト

これは私自身のゴルフ参照ソリューションです。属性が与えられている限り、誰でもそれを改善するか、独自の答えでその論理に従うことを歓迎します。

それについてのきちんとした部分は、再帰が行われないため、Pythonの再帰制限で問題が発生することはありません。たとえば、Spの Countup Prindealプログラムは無期限に実行できます。

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

これは、改行をエスケープして引用符で囲まれたプログラム文字列を取り込むプログラムです
'p _MyVariable_321\np screaming_hairy_armadillo'

SpPietuの回答からさまざまなゴルフの合図を取りました。みんなありがとう :)


6

Python 3、345 336 335 328バイト

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のおかげで6バイト)

まだゴルフ。プログラムがという名前のファイルに保存されていると仮定しますP

呼び出しをfラムダ内に置くとd数バイト節約できますが、最後のテストケースが最大再帰深度に達する可能性があります。

いくつかのPrindealプログラム

無駄な減算プログラム

これは役に立たない減算プログラムです。正しく減算しても、それに応じて成功/失敗を返さないため、役に立たない。

出力は次のようになります。

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

カウントアップ

a helper
 p 1
 countup 1
 i success

a countup
 i 1
 helper 1
 d failure

countup n

上向きにカウントし、n永遠に印刷します。おそらくインタープリターの速度のテストとして機能する可能性があります(キーボード割り込みでの長いトレースバックに注意してください)。


2
この質問の誰もがこのゴルフを見逃しました。なぜかわかりません。l[:(l+"#").find("#")]そして、そのすべてのバリエーションを単純なに置き換えることができますl.split('#')[0]
orlp

@orlpは非常に集中しfindていたのでsplit#sがなくてもあなたができることを忘れていました。ありがとう:)
Sp3000

6

JavaScript(ES6)、273 258

修正されたバグを編集し、実際のテストスイートを追加しました。

先頭のスペースと改行をカウントしません。

きっともう少しゴルフできます。

説明を書くのにうんざりしているので、一時的な値(パラメーター)を維持するためにクロージャーを使用する良い例だと思います。

EcmaScript 6に準拠したブラウザーでスニペットを実行してテストします(MSIEではなくChromeが顕著です。Firefoxでテストしたところ、Safari 9でも可能です)

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>


テストプログラムにコメントを追加しましたが、コードが機能しなくなったようです。
カルビンの趣味

@ Calvin'sHobbies最初のクイックパッチ
edc65

3

C#6、653バイト

Pythonの海に囲まれた私のエントリを次に示します...

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;}}

展開およびコメント:

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;
    }
}

それを使用するには、単にクラスをインスタンス化し、R()メソッドを呼び出します。例:

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

3

Common 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))))

これを入れて、file.lispたとえば呼び出しsbcl --script file.lispます。入力は標準入力ストリームから読み取られます。

このバージョンは、Prindealのスーパーセットを解析します。PrindealのソースからすべてのCommon Lispに簡単にアクセスできます。これは通訳者の特徴だと思います。

コメント版

;; 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)))))

~$ 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

read / evalループでevalby を置き換えるprintと、何が評価されているかがわかります。

(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)

マクロ展開

次のエイリアス定義を選択した場合:

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

...という名前の変数への参照を見ることができますが、gこれはレキシカルスコープ内でどこにも見つかりません。しかし、マクロ展開後、評価される実際のコードは次のとおりです。

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

ここで、g定義されている関数の引数リストを参照します。


2

Python 2、486バイト

これは、私がもっとゴルフしたリファレンスソリューションです(現在は-98バイト)。

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:]

変更点(覚えている):

  • 自動ブール整数変換([l,l[:l.find('#')]]['#'in l])。
  • 1つのステートメントで設定またはインクリメント(V[k]=-~V[k]if k in V else 1
  • より長い式へのより多くのエイリアス(k=s[1]
  • メインループにカウンターがなく、代わりに入力リストをクリアする
  • printスペースの自動追加(print k,'=',V.get(k,0)
  • 1〜9の数字をチェックする('0'<t[0]<':'
  • raround の戻り値を反転してreturns を保存する
  • スライスと分割の繰り返しを削除(map(str.split,c[:3]))

1

Python 3、1322バイト

ゴルフ:

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

ゴルフをしていない:

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

使用法:

P(c)

cテキストコンテンツはどこにありますか。

例:

単一行の文字列が受け入れられます。

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

複数行の文字列も使用できます。

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

または:

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

等。

ノート:

これはすべてのテストケースで正常に機能しますが、次の再帰制限に達します。

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

したがってsys.setrecursionlimit(2000)


1
それはいくつかのバイトを使い果たしますが、sys.setrecursionlimit()を使用してこれをpowエイリアスで適切に動作させることができませんでしたか?
コーウィン

私はできましたが、OPは、Pythonのような言語(再帰の制限がある)はそのまま受け入れられると述べました。ただし、OPから要求された場合は修正を追加します。@Corwin
ザック・ゲイツ

けっこうだ。スペックでは見落としていました。@ZachGates
Corwin

1

Python- 695 688バイト

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> リテラルのタブ文字です。


1

C ++、1111バイト

これはC ++です-私がそれを作ることができるのと同じくらい慣用的です。
つまり、C ++に近づけ、Cに近づけないということです。
また、同等のCプログラムよりも大きいことも意味します。
C ++は冗長な標準ライブラリでJavaに匹敵すると思います。
VS2013およびg ++ 4.9.2(-std = c ++ 11を使用)でコンパイルします

#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;}}}

以下はオリジナルです。誰かがそれをより慣用的で短くする方法を同時に考えられるなら、私に知らせてください。

#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

ハスケル、1009

ゴルフにベストを尽くしました。私の未使用コードは3,000以上の文字で構成されていました。この時点では、すべての機能が何をしているのか覚えていないので、ゴルフをすることは、何が壊れるか、何が壊れないかを推測することを意味します。

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
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.