式をパンフィックス表記に変換する


19

私はesolangsを閲覧し、その言語に応じ偶然ました:https://github.com/catseye/Quylthulg

この言語の興味深い点の1つは、プレフィックス、ポストフィックス、またはインフィックスを使用せず、3つすべてを使用して、「パンフィックス」表記法と呼ぶことです。

以下に例を示します。1+2panfixで通常の中置記号を表す場合、次のようになります+1+2+。演算子がオペランドの前、中間、後の両方にあることに注意してください。別の例は(1+2)*3です。これはになり*+1+2+*3*ます。*オペランド+1+2+とに関して、3つの場所すべてがどのようになっているかに再び注目してください3

チャレンジ

ご想像のとおり、この課題でのタスクは、式を中置からパンフィックスに変換することです。

いくつかの説明:

  • 次の4つの基本操作のみを処理する必要があります。 +-*/
  • それらの単項バージョンを扱う必要はありません、バイナリのみ
  • あなたは括弧に対処する必要があります
  • */thenの通常の優先順位ルールを想定し、+-それらすべてに対して結合性を残します。
  • 数値は非負の整数になります
  • オプションで、入力と出力の両方にスペースを含めることができます

テストケース

1+2  ->  +1+2+
1+2+3  ->  ++1+2++3+
(1+2)*3  ->  *+1+2+*3*
10/2*5  ->  */10/2/*5*
(5+3)*((9+18)/4-1)  ->  *+5+3+*-/+9+18+/4/-1-*

これはなので、バイト単位の最短コードが勝ちです!

回答:


3

JavaScript(ES6)、160バイト

f=(s,t=s.replace(/[*-/]/g,"'$&'"),u=t.replace(/^(.*?)([*-9]+)'([*/])'([*-9]+)|([*-9]+)'([+-])'([*-9]+)|\(([*-9]+)\)/,"$1$3$2$3$4$3$6$5$6$7$6$8"))=>t==u?t:f(s,u)

すべての演算子(前に文字コードを与える)を引用し、*利用可能な操作'*'または'/'操作、'+'または'-'操作または()sを探し、最初をそのパンフィックス表記で置き換えることにより機能します。例:

(5+3)*((9+18)/4-1)
(5'+'3)'*'((9'+'18)'/'4'-'1)
(+5+3+)'*'((9'+'18)'/'4'-'1)
+5+3+'*'((9'+'18)'/'4'-'1)
+5+3+'*'((+9+18+)'/'4'-'1)
+5+3+'*'(+9+18+'/'4'-'1)
+5+3+'*'(/+9+18+/4/'-'1)
+5+3+'*'(-/+9+18+/4/-1-)
+5+3+'*'-/+9+18+/4/-1-
*+5+3+*-/+9+18+/4/-1-*

3

JavaScript(ES6)、285 282 281 267 251 243 241 238 234 232 231バイト

Neilのおかげで最大15バイト。

f=(I,E=I.match(/\d+|./g),i=0)=>(J=T=>T.map?T.map(J).join``:T)((R=(H,l=(P=_=>(t=E[i++])<")"?R(0):t)(),C,F)=>{for(;(C=P())>")"&&(q=C>"*"&&C<"/")*H-1;)F=q+H?l=[C,l,C,P(),C]:F?l[3]=[C,l[3],C,R(1),C]:l=R(1,l,i--)
i-=C>")"
return l})(0))

JavaScriptでは、これはMathematicaよりも少し難しいです。これは、基本的に、過剰に専門化された、ゴルフのオペレーター優先パーサーです。

無効な入力でスタックオーバーフローが発生します。

デモ

非ゴルフ

convert = input => {
  tokens = input.match(/\d+|./g);
  i = 0;
  parse_token = () => (token = tokens[i++]) == "(" ? parse_tree(false) : token;
  parse_tree = (mul_div_mode, left = parse_token()) => {
    while ((oper = parse_token()) != ")" && !((is_plus_minus = oper == "+" || oper == "-") && mul_div_mode)) {
      if (is_plus_minus || mul_div_mode)
        left = [oper, left, oper, parse_token(), oper];
      else if (non_first)
        left[3] = [oper, left[3], oper, parse_tree(true), oper];
      else
        left = parse_tree(true, left, i--);
      non_first = true;
    }
    if (oper != ")")
      i--;
    return left;
  };
  format_tree = tree => tree.map ? tree.map(format_tree).join("") : tree;
  return format_tree(parse_tree(false));
}

S.split``である必要がありますが[...S]、実際には前もって一致し/\d+|./gて、代わりに作業するのに役立つ場合があります。
ニール

@ニールありがとう。それについて見ていきます。
-PurkkaKoodari

2

Mathematica、 203 195バイト

これはおそらく効率的ではありませんが、仕事をしているようです。

Function[f,ReleaseHold[(Inactivate@f/._[Plus][a_,b_/;b<0]:>a~"-"~-b//Activate@*Hold)//.a_/b_:>a~"/"~b/.{a_Integer:>ToString@a,Plus:>"+",Times:>"*"}]//.a_String~b_~c_String:>b<>a<>b<>c<>b,HoldAll]

これは、実際の式を受け取り、パンフィックス表記の文字列を返す匿名関数です。Mathematicaは評価時ではなく解析時に演算子の優先順位を整理するので、ネストは自動的に正しいはずです。少なくともテストケースは期待どおりに機能します。

説明:次のように、式全体をツリーとして解釈するのは簡単です。

木

この段階では、演算子(リーフではないすべてのノード)はもはや演算子ではなく、実際にはなどの文字列に変換されています"+"。整数も文字列にキャストされます。次に、繰り返される置換ルールは、正確に2つのリーフを持つすべてのノードをpanfixに変換しparent-leaf1-parent-leaf2-parentます。いくつかの反復の後、ツリーは単一の文字列になります。

バイトカウントの主な損失は、Mathematicaが解釈することです

5 - 4 -> 5 + (-4)
9 / 3 -> 9 * (3^(-1))

また、これは解析時にも発生します。

パターンa_/b_もとして解釈されるため、少し下がったa_ * (b_)^(-1)。また、他の場所でいくつかのマイナーな最適化。


1

プロローグ、87バイト

x(T)-->{T=..[O,A,B]}->[O],x(A),[O],x(B),[O];[T].
p:-read(T),x(T,L,[]),maplist(write,L).

これは関数です(ほとんどの場合、完全なプログラムを書くとPrologに悪夢のようなレベルのボイラープレートがあります。通常、プログラムをコンパイルしても、実行時にREPLが生成されます)p。標準入力から入力を受け取り、標準出力に出力します。入力にピリオドを追加する必要があることに注意してください。これは、Prologの入力ルーチンの動作の不幸な結果です(他の言語が改行を使用するのとほぼ同じ方法で入力にピリオドを使用します)。それは答えを失格にするかもしれないし、しないかもしれません。

説明

Prologの算術演算子は通常、タプルコンストラクターとして解釈されます。ただし、それらは、基にしている実際の算術演算子と同じ優先順位の規則に従います。あなたは中置記法でタプルを形成し、できる+-バインド少ないしっかり以上*および/グループ内の左から右へ優先取られて、。これはまさに質問が求めるものです。したがって、入力からネストされたタプル全体を読み取ることができ、すでに正しい構造を持っています。それがそうpです。

次に、これをパンフィックス表記に変換する必要があります。x変換コンストラクタと整数のpanfixedリストに入力され、ほとんど直接英語の文章として読むことができます:「xT次の場合T、コンストラクタを持つタプルですOと引数ABそれから、OxAOxBO他に、T」。最後に、セパレータなしでリストを印刷するだけです(つまり、リストの各要素maplistを呼び出すためwriteに使用します)。

これをテストするためにSWI-Prologを使用しました。これは、GNU Prologのバージョンがmaplistまだ(明らかに新しいバージョンに追加されていないため)ですが、一般にProlog実装間でかなり移植性があるはずです。

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