括弧でくくられた中置に対する修正


16

Quylthulgは、Chris Presseyによる言語で、panfixと呼ばれるものを使用して中置表記法の問題を解決しようとします。

postfixと同様に、panfixは、デフォルトの演算子の優先順位をオーバーライドするために、括弧などの不可解な仕掛けを展開する必要はありません。同時に、パンフィックスは、インフィックスと同じ順序と方法で用語を指定することを可能にします。


接頭辞または接尾辞の曖昧さとともに、挿入記法の便利さをどのように取得しますか?もちろん、3つすべてを使用してください!

=y=+*3*x*+1+=

より正式には、letを+演算子、and ab式にします。その後(a+b)、有効な(括弧で囲まれた)中置式であり、その式のパンフィックス表現はです+a+b+。ここで、並置は連結を表します。

あなたの目標は、パンフィックス文字列を取得し、それを完全に括弧で囲まれたインフィックスに変換することです:

(y=((3*x)+1))

簡単にするために、次の変更を行います。

  • 演算子は2つの一意の文字のみで構成できます(いずれかを選択できますが、ここでは*andを使用します+)。
  • リテラルは1つだけで、別の個別の文字で構成されます(いずれかを選択できますが、ここではを使用します_)。
  • 入力は整形式のパンフィックス式になります。

以下のために複雑、私たちは以下の変更を行います:

  • 演算子は、1つだけでなく、任意の正数の文字で構成できます。

これは、文字列の残りの部分を見ることなく、演算子文字の特定の部分文字列がどのように分割されるかを必ずしも決定できないため、挑戦をより困難にします。

これは、@ user202729の好意によるチャレンジのリファレンス実装です。

テストケース

format: input -> output
+*+_*+_*+++_+*+_*+_*+++ -> ((_*+_)+(_+(_*+_)))
**++*+***++_+_++_+*++*+***_*++*+*****_**_*_*** -> ((((_+_)+_)*++*+***_)*(_*(_*_)))
***_**_***_* -> ((_**_)*_)
+_+_+ -> (_+_)
*+*+++**+***+++++_*+*+++**+***+++++_*+*+++**+***+++++ -> (_*+*+++**+***+++++_)
*++++*+*_*_*+*+++****+_++****+_++****++*+*+++_*+++ -> (((_*_)+*+(_++****+_))*+++_)
+**+_*+_*+*_*+*_*+*_+*_+**+ -> (((_*+_)*_)+(_*(_+*_)))
+**+++++_+++++_+++++*_*+*+_++++++_+++++_+++++++* -> (((_+++++_)*_)+*(_+(_+++++_)))
+*+*+_+*+_+*+*_*+*_*+*+_+*+_+*+*+ -> (((_+*+_)*_)+(_*(_+*+_)))
**_**_**_*_****_* -> ((_*(_*(_*_)))*_)

私はこのプログラムを使用し、このチャレンジの挿入文字列を生成しました(パンフィックスへの変換は簡単ですが、逆変換は簡単ではありません)。




6
推奨されるテストケース:**_**_**_*_****_*。私がテストした答えはすべてこれに失敗しました。
ニトロドン

1
たとえば、出力に余分なスペースを入れることはできます(_ + _)か?
トンホスペル

2
@TonHospel確かに。
エソランジングフルーツ

回答:


6

プロローグ(SWI)194 163バイト

このヒントを使用して0 'から31バイトを保存しました!

[C|T]/O/R:-C\=x,(T/P/R,concat(C,P,O);O=C,R=T).
[x|R]-x-R.
L-X-R:-L/O/A,A-Y-B,B/O/C,C-Z-D,D/O/R,atomics_to_string(['(',Y,O,Z,')'],X).
X^P:-string_chars(X,L),L-P-[].

演算子^は、左引数にパンフィックス式を含む文字列を取り、右引数を対応する括弧付きのインフィックス式を含む文字列に設定します。のx代わりにリテラルとして使用し_ます。

オンラインでお試しください!

説明

Prologは宣言型言語であるため、パンフィックスと括弧で囲まれた式の関係を記述する必要があります。

説明では、このわずかに未使用のバージョンを使用しています。

oper([C|T],O,R) :- C\=x, oper(T,P,R), concat(C,P,O).
oper([C|T],C,T).

expr([x|R],x,R).
expr(L,X,R) :- oper(L,O,A), expr(A,Y,B), oper(B,O,C), expr(C,Z,D), oper(D,O,R),
               atomics_to_string(['(',Y,O,Z,')'],X).

parenthesize(X,P) :- string_chars(X,L), expr(L,P,[]).

私たちの主な製品はparenthesizeX文字列としてパンフィックス式を受け取り、対応する括弧でくくられた中置式Pを文字列として送信します。これは、使用するstring_chars文字のリストに入力された文字列を変換すると、単純に渡しますexpr

expr文字のリストを取り入れて、Lそれが見つけた最初のパンフィックス式を分析Lして、括弧で囲まれた同等物Xと文字のリストの残りを送り出しますR。次の2種類の式があります。

  • 最初の文字が場合Lx、その式がありx、残りは後のすべてですx
  • それ以外の場合は、演算子を解析しますOoper以下を参照)。式を解析しますYO再度解析します。別の式を解析しますZO3回目の解析。残りはの3番目のインスタンスの後のすべてですO。発現は、接合の結果であるYOZ文字列に、括弧で囲まれました、。

oper文字のリストを取ります。最初の文字はCで、残りの文字はT;です。演算子(つまり、1つ以上の演算子文字の実行)を解析し、演算子Oと文字リストの残りを送信しRます。演算子を形成するには、文字Cx; 以外でなければなりません。また、

  • 演算子Pはから解析可能でなければならずT、残りはR; この場合、Oの連結であるCP。または、
  • Oは単一の文字Cです。この場合、RはだけTです。

実例

入力+*+x+x++*x+*を例に取りましょう。

  • から式を解析し+*+x+x++*x+*ます。これはで始まらないxので、最初から演算子を解析します。
  • oper可能な限り大きな演算子を解析するため、を試み+*+ます。
    • 次に、から式を解析しx+x++*x+*ます。これはする必要がありますx
    • 次に+*+、から同じ演算子を解析しようとします+x++*x+*。ただし、これは失敗します
  • そこで、バックトラックして、+*代わりに演算子の解析を試みます。
    • から式を解析し+x+x++*x+*ます。これはで始まらないxため、演算子を解析する必要があります。
    • 唯一の可能性は+です。
    • 次に、から部分式を解析しx+x++*x+*ます。これはする必要がありますx
    • +から再度解析し+x++*x+*ます。
    • 次に、から別の部分式を解析しx++*x+*ます。これはする必要がありますx
    • 最後に、+から再度解析し++*x+*ます。
    • 式は正常に解析されました。文字列を返します(x+x)
  • 前の再帰レベルに+*戻り、から演算子を再度解析し+*x+*ます。
  • 次に、から別の部分式を解析しx+*ます。これはする必要がありますx
  • 最後に、+*から再度解析し+*ます。
  • 式は正常に解析されました。文字列を返します((x+x)+*x)

これ以上文字が残っていないため、式の翻訳に成功しました。


4

Perl、78 60 58 57 50バイト

含み+1のためにp

1for +および2forの使用*(または実際、どの演算子でも任意の数字が機能します)

perl -pe 's/\b((\d+)((?1)|_)\2((?3))\2)\b/($3 $2 $4)/&&redo' <<< 22_22_22_2_2222_2

与えられた例と比較した便利なテストのために、あなたはあなたのために翻訳とスペース除去をするこれを使うことができます:

perl -pe 'y/+*/12/;s/\b((\d+)((?1)|_)\2((?3))\2)\b/($3 $2 $4)/&&redo;y/ //d;y/12/+*/' <<< "**_**_**_*_****_*"

3

クリーン200 192 189バイト

import StdEnv,Text
f"_"=["_"]
f l=["("+a+p+b+")"\\p<-[l%(0,i)\\i<-[0..indexOf"_"l]|endsWith(l%(0,i))l],t<-[tl(init(split p l))],n<-indexList t,a<-f(join p(take n t))&b<-f(join p(drop n t))]

オンラインでお試しください!

結果を内部に持つシングルトンをf取得Stringして返す関数を定義します[String]

素敵なもの:

  • 正規表現を使用しません
  • 演算子を除く任意の文字で動作します_

3

Retina 0.8.2、138バイト

.+
($&)
+`\((\d+)(_|((?<i>(?<i>\d+))|_(?<-i>\k<i>)+)+(?(i)(?!)))\1(_|((?<i>(?<i>\d+))|_(?<-i>\k<i>)+)+(?(i)(?!)))\1\)
(($2)$1($4))
\(_\)
_

オンラインでお試しください!リンクには、より高速なテストケースが含まれています。説明:正規表現エンジンは、バックトラッキングを使用して文字列をトークンに分割し、トークンをiバランシンググループにプッシュまたはポップします。最初の変数の前に、少なくとも1つの演算子が常に開始時に実行されます。変数の後に、少なくとも1つの演算子がポップされます。その時点で、プッシュされた演算子の実行または別の変数が有効です。オペレーターは、グループに正しくプッシュされるため、重複してグループにプッシュされます。例:

Input           Stack
Push *          * *
Push *++*+***   * * *++*+*** *++*+***
Push +          * * *++*+*** *++*+*** + +
Push +          * * *++*+*** *++*+*** + + + +
Variable _
Pop +           * * *++*+*** *++*+*** + + +
Variable _
Pop +           * * *++*+*** *++*+*** + +
Pop +           * * *++*+*** *++*+*** +
Variable _
Pop +           * * *++*+*** *++*+***
Pop *++*+***    * * *++*+***
Variable _
Pop *++*+***    * *
Pop *           *
Push *          * * *
Variable _
Pop *           * *
Push *          * * * *
Variable _
Pop *           * * *
Variable _
Pop *           * *
Pop *           *
Pop *

残念ながら、これは結果をまとめてまとめるために結果をキャプチャするのに役立ちません。したがって、外部演算子は手動で照合されます。ブラケットは外側から内側に追加されるため、最初のステージは式全体をブラケットで囲み、最後のステージは変数に伝搬されたためそれらを削除します。


1
これもに失敗し**_**_**_*_****_*ます。
user202729

@ user202729今働いていますか?
ニール

@Neilはい、動作しています。
Οurous

1

Haskell167 166バイト

head.e
e('_':r)=["_",r]
e(x:r)=[x]%r
e _=[]
o%t@(c:r)|[x,u]<-e t,n<-length o,[y,v]<-e$drop n u,all((==o).take n)[u,v]=['(':x++o++y++")",drop n v]|p<-o++[c]=p%r
o%_=[]

オンラインでお試しください!使用例:head.e "**_**_**_*_****_*"yields ((_*(_*(_*_)))*_)。以外のすべての文字_は演算子として解釈され、_それ自体が識別子を示します。


0

Python 3、226バイト

from re import*
P=r'([*+]+)'+r'(\(.+?\)|_)\1'*2;R=lambda i,J=lambda i,o:i[:o]+sub(P,lambda o:'('+o[2]+o[1]+o[3]+')',i[o:],1),s=search:s(P,i)and R([J(i,o)for o in range(len(i))if s(P,J(i,o))or J(i,o)[0]+J(i,o)[-1]=='()'][0])or i

という名前の匿名関数を定義しますR

オンラインでお試しください!


以外の任意の文字を使用できることに注意してください_*+。これらは例で使用されたものです。これを使用して、正規表現をゴルフすることができます(例:の\d代わりに使用[*+])。
エソランジングフルーツ
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.