整数としての括弧と括弧の評価


20

()[]これらのポイントを満たす4文字の文字列を取り込むプログラムを作成します。

  • すべての左括弧(には対応する右括弧があり)ます。
  • すべての左角括弧に[は、対応する右角括弧があり]ます。
  • 括弧とブラケットの一致するペアは重複しません。たとえば[(])、一致するかっこが一致するかっこに完全に含まれておらず、逆も同様であるため、無効です。
  • 最初と最後の文字は、一致する括弧または括弧のペアです。したがって([]([]))[[]([])]有効ですが、無効です[]([])

(入力形式の文法<input> ::= [<input>*] | (<input>*)です。)

一致する括弧と括弧の各ペアは、負でない整数に評価されます。

  • 一致する括弧内のペアの値はすべて合計されます。空の一致に()はvalueがあります0
  • 一致する括弧内のペアの値はすべて乗算されます。空の一致に[]はvalueがあります1

(1つの数値の合計またはは、その同じ数値です。)

たとえば、次の([](())([][])[()][([[][]][][])([][])])ように分類して評価できます9

([](())([][])[()][([[][]][][])([][])])    <input>
(1 (0 )(1 1 )[0 ][([1 1 ]1 1 )(1 1 )])    <handle empty matches>
(1 0   2     0   [(1     1 1 )2     ])    <next level of matches>
(1 0   2     0   [3           2     ])    <and the next>
(1 0   2     0   6                   )    <and the next>
9                                         <final value to output>

もう一つの例:

[([][][][][])([][][])([][][])(((((([][]))))))]    <input>
[(1 1 1 1 1 )(1 1 1 )(1 1 1 )((((((1 1 ))))))]
[5           3       3       (((((2     )))))]
[5           3       3       ((((2       ))))]
[5           3       3       (((2         )))]
[5           3       3       ((2           ))]
[5           3       3       (2             )]
[5           3       3       2               ]
90                                                <output>

プログラムは、入力文字列全体で表される整数を評価して出力する必要があります。入力が有効であると想定できます。バイト単位の最短コードが優先されます。

プログラムの代わりに、文字列を取り込んで整数を出力または返す関数を作成できます。


Pythonの提出に代わって説明を求める:プログラムのみ、または関数/戻り値は大丈夫ですか?
Sp3000

質問を編集するのがいいかもしれません。前の質問で、質問に「プログラムを書く」と書かれている場合、関数は無効であると言われました。
レトコラディ

回答:


11

CJam、23

q"])(""1]:*0]:+["4/ers~

デニスへの大きなクレジットで!オンラインで試す

説明:

プログラムは入力をCJam式に変換してから評価します。
[…]なる[…1]:*(追記1及び乗算)は、
(…)となる[…0]:+(追記0と追加)

q              read input
"])("          characters we want to replace
"1]:*0]:+["    replacement strings, concatenated
4/             split into strings of length 4: ["1]:*" "0]:+" "["]
er             replace (transliterate) the 3 characters with the 3 strings
s              convert the result (mixed characters and strings) to string
~              evaluate

1
音訳は4バイトを節約します。– q"])(""1]:*0]:+["4/ers~
デニス

2
@Dennis whaaa!それは非常識です、あなたはそれを行うことができますか?
-aditsu

3
あなた私に尋ねていますか?:P
デニス

4
@Dennis CJamの作成者は、そのような機能の存在をどのように知っていますか??
オプティマイザー

8

Common Lisp-98

(lambda(s)(eval(read-from-string(#1=ppcre:regex-replace-all"\\["(#1#"]"(#1#"\\("s"(+")")")"(*"))))
  1. 交換する(ことにより、(+
  2. 交換する[ことにより、(*
  3. 交換する]ことにより、)
  4. 文字列から読み取る
  5. 評価

これには、cl-ppcreライブラリを現在のLispイメージにロードする必要があります。

説明

関数*+は可変個であり、引数を指定しないと中立値を返します。例として、評価されたlispフォームは次のとおりです。

(+ (*) (+ (+)) (+ (*) (*)) (* (+)) (* (+ (* (*) (*)) (*) (*)) (+ (*) (*))))
=> 9

そして

(* (+ (*) (*) (*) (*) (*)) (+ (*) (*) (*)) (+ (*) (*) (*))
   (+ (+ (+ (+ (+ (+ (*) (*))))))))
=> 90

正規表現なし-183バイト

(lambda(s)(do(r(x(coerce s'list))c)((not x)(eval(read-from-string(coerce(reverse r)'string))))(setq c(pop x))(push(case c(#\[ (push #\* r)#\()(#\] #\))(#\( (push #\+ r) #\()(t c))r)))

C'mon、Lisp-16バイト(実験的)

+((<r*([<r)]<rRE

他の言語は非常に簡潔なので、文字列操作を短くするために、Common Lispに基づいて独自のゴルフ言語を作成したいと思います。現在、仕様はなく、eval関数は次のとおりです。

(defun cmon-lisp (expr &rest args)
  (apply
   (lambda (s)
     (let (p q)
       (loop for c across expr
             do (case c
                  (#\< (push (pop p) q))
                  (#\r
                   (let ((a1 (coerce q 'string)) (a2 (coerce p 'string)))
                     (setf p nil
                           q nil
                           s
                             (cl-ppcre:regex-replace-all
                              (cl-ppcre:quote-meta-chars a1) s a2))))
                  (#\R
                   (setf s
                           (if (string= s "")
                               nil
                               (read-from-string s))))
                  (#\E (setf s (eval s)))
                  (t (push c p))))
       s))
   args))

テスト:

(cmon-lisp "+((<r*([<r)]<rRE" "([] [] ([] []))")
=> 4
  • という暗黙の引数sと2つのスタックがpありqます。
  • ソースコード内の文字はにプッシュされpます。
  • <:からポップしpてプッシュしqます。
  • rsin qを文字in から文字in に置き換えます(文字列でなければなりません)p。結果はs;に保存されます。pそしてq空になります。
  • R:文字列から読み取り、s結果を変数に格納しますs
  • E:評価形式s、結果をs

1
ここでかっこを使って何かを行うためにlispがどのように使用されるかを示します。
シド・カーコーフ

@SydKerckhoveあなたのコメントは、適切なClojureの答えを考えさせてくれます。どうもありがとう!
コアダンプ

6

Pyth、35 34 33バイト

L?*F+1yMbqb+YbsyMbyvsXzJ"])"+R\,J

デモンストレーション。

@ジャクベのおかげで1バイト。

入力を解析することから始めます。入力形式はPythonに近いですが、完全ではありません。括弧で囲まれたグループまたは括弧で囲まれた各グループの後にコンマが必要です。括弧で囲まれたグループの末尾のコンマは不要ですが、無害です。これを達成するために、次のコードを使用します。

vsXzJ"])"+R\,J
  X               Translate
   z              in the input
     "])"         the characters "])"
    J             which we will save to J to
             J    J
         +R\,     with each character mapped to itself plus a ",".
 s                Combine the list to a string.
v                  Evaluate as a Python literal.

これ,により、文字列の最後に余分な部分が残り、オブジェクト全体がタプルでラップされますが、これは無害です。タプルが合計され、その要素に等しい値を持つためです。

文字列が解析されたので、その値を見つける必要があります。これはy、解析されたオブジェクトで呼び出されるユーザー定義関数を使用して行われます。関数は次のように定義されます。

L?*F+1yMbqb+YbsyMb
L                     Define a function, y(b), which returns the following:
 ?       qb+Yb        We form a ternary whose condition is whether the input, b,
                      equals the inputplus the empty list, Y. This is true if
                      and only if b is a list.
      yMb             If so, we start by mapping y over every element of b.
  *F+1                We then take the product of these values. The +1 ensures
                      that the empty list will return 1.
                yMb   Otherwise, we start by mapping y over every element of b.
               s      Then, we sum the results.

@ジャクベ右、単項加算は効果がありません。
isaacg

3

Emacs lisp、94

この形式は非常に見栄えが良いので、単純な変換が機能する可能性があると考えました。

(defun e()(format-replace-strings'(("("."(+")("["."(*")("]".")")))(eval(read(buffer-string))))

中間形式は次のようになります(質問の例):

(+(*)(+(+))(+(*)(*))(*(+))(*(+(*(*)(*))(*)(*))(+(*)(*))))

加算と乗算は、空の引数リストで必要なことをすでに実行しているという事実に助けられています。

Degolfed、インタラクティブ、あなたの喜びを再生するため:

(defun paren_eval()
  (interactive "*")
  (format-replace-strings '(("(" . "(+")
                            ("[" . "(*")
                            ("]" . ")")))
  (eval (read (buffer-string)))
)

もっと詳しく読む必要があります-Common Lispソリューションはまったく同じアプローチを取ります!
トビースパイト

1
さらにEmacs Lispの回答が必要です!ところで、私は数えませんでしたが、ラムダを使用して、文字列をパラメータとして取り、interactive (バッファ文字列の代わりに、文字列からの読み取りを使用して)削除することでもう少しゴルフできます。
コアダンプ

2

網膜、111バイト

[\([](1+x)[]\)]
$1
\[]
1x
\(\)
x
(\[a*)1(?=1*x1*x)
$1a
a(?=a*x(1*)x)
$1
(\[1*x)1*x
$1
)`(\(1*)x(?=1*x)
$1
[^1]
<empty line>

単項で出力します。

各行は独自のファイルに移動する必要がありますが、-sフラグを使用してコードを1つのファイルとして実行できます。例えば:

> retina -s brackets <input_1
111111111

後で説明します。


2

Java、349文字

単純な再帰的アプローチ。文字列が、プログラムの呼び出しに使用される最初の引数になることを期待します。

import java.util.*;class K{int a=0,b;String c;public static void main(String[]a){K b=new K();b.c=a[0];System.out.print(b.a());}int a(){switch(c.charAt(a++)){case'(':b=0;for(int a:b())b+=a;break;case'[':b=1;for(int a:b())b*=a;}a++;return b;}List<Integer>b(){List d=new ArrayList();char c;while((c=this.c.charAt(a))!=']'&&c!=')')d.add(a());return d;}}

拡張:

import java.util.*;

class K {
    int a =0, b;
    String c;
    public static void main(String[] a){
        K b = new K();
        b.c = a[0];
        System.out.print(b.a());
    }
    int a(){
        switch (c.charAt(a++)){
            case '(':
                b =0;
                for (int a : b())
                    b += a;
                break;
            case '[':
                b =1;
                for (int a : b())
                    b *= a;
        }
        a++;
        return b;
    }
    List<Integer> b(){
        List d = new ArrayList();
        char c;
        while ((c= this.c.charAt(a)) != ']' && c != ')')
            d.add(a());
        return d;
    }
}

2

Perl 5、108

書き換えと評価ではなく、インタプリタとして行われます。素晴らしいショーではありませんが、とにかく書くのは楽しいです。

push@s,/[[(]/?[(ord$_&1)x2]:do{($x,$y,$z,$t)=(@{pop@s},@{pop@s});
[$t?$x*$z:$x+$z,$t]}for<>=~/./g;say$s[0][0]

ゴルフをしていない:

# For each character in the first line of stdin
for (<> =~ /./g) {
    if ($_ eq '[' or $_ eq '(') {
        # If it's an opening...
        # ord('[') = 91 is odd, ord('(') = 40 is even
        push @stack, [ ( ord($_) & 1) x 2 ];
        # so we will push [1, 1] on the stack for brackets and [0, 0] for parens.
        # one of these is used as the flag for which operator the context is, and
        # the other is used as the initial (identity) value.
    } else {
        # otherwise, assume it's a closing
        ($top_value, $top_oper) = @{ pop @stack };
        ($next_value, $next_oper) = @{ pop @stack };
        # merge the top value with the next-to-top value according to the
        # next-to-top operator. The top operator is no longer used.
        $new_value = $next_oper
            ? $top_value * $next_value
            : $top_value + $next_value
        push @stack, [ $new_value, $next_oper ];
    }
}

say $stack[0][0]; # print the value remaining on the stack.

2

Python、99

さまざまな方法を試してみましたが、得られた最短の時間は基本的には単なる交換と評価でした。,Pythonが解析でき[1,2,]、最後の末尾のコンマがタプルにすべてを入れるので、すべての末尾のsを残すことができることに気がついて驚きました。唯一の他の非直接的な部分は次のようになりますord(c)%31%7別の文字を区切るために(それは評価に2310のために()[]それぞれ)

F=lambda s:eval(''.join(["],1),","reduce(int.__mul__,[","sum([","]),"][ord(c)%31%7]for c in s))[0]

1
これはプログラムとして動作しませんか?質問はプログラムを要求するので、機能を提供することは要件を満たしていないと思います。少なくとも、それが質問で「プログラム」と言ったときに関数を送信したときに、私に言ったことです。:)
レトコラディ

1

Java、301

TheNumberOneの答えとは少し異なるアプローチですが、私の場合も本質的に再帰的です。入力はコマンドラインから取得されます。voidメソッドは、不要になった文字を削除するときに数バイトを節約します。

enum E{I;String n;public static void main(String[]r){I.n=r[0];System.out.print(I.e());}int e(){int v=0;if(n.charAt(0)=='('){for(s("(");n.charAt(0)!=')';)v+=e();s(")");}else if(n.charAt(0)=='['){v=1;for(s("[");n.charAt(0)!=']';)v*=e();s("]");}return v;}void s(String c){n=n.substring(1+n.indexOf(c));}}

展開された:

enum EvaluatingParenthesesAndBrackets{
    AsIntegers;
    String input;
    public static void main(String[]args){
        AsIntegers.input=args[0];
        System.out.print(AsIntegers.evaluate());
    }
    int evaluate(){
        int value=0;
        if(input.charAt(0)=='('){
            for(substringAfterChar("(");input.charAt(0)!=')';)
                value+=evaluate();
            substringAfterChar(")");
        }
        else if(input.charAt(0)=='['){
            value=1;
            for(substringAfterChar("[");input.charAt(0)!=']';)
                value*=evaluate();
            substringAfterChar("]");
        }
        return value;
    }
    void substringAfterChar(String character){
        input=input.substring(1+input.indexOf(character));
    }
}

1

Python、117 110 109バイト

def C(s,p=[0]):
 m=r=s[p[0]]=='[';p[0]+=1
 while s[p[0]]in'[(':t=C(s,p);r=r*t*m+(r+t)*(1-m)
 p[0]+=1;return r

私が苦労していた1つの側面は、関数が基本的に2つの戻り値を持っているということです:製品/合計、および文字列内の新しい位置。しかし、結果のみを返す関数が必要なので、タプルを返すことはできません。このバージョンでは、「参照」引数(1つの要素を持つリスト)を使用して、関数から位置を返します。

位置にグローバル変数を使用する短いバージョン(103バイト)があります。しかし、それは最初の呼び出しでのみ機能します。そして、一度しか機能しない機能は少し怪しいように思えます。コードゴルフに適しているかどうかはわかりません。

アルゴリズムは単純な再帰です。製品/合計を更新する式のバリエーションをいくつか試しました。まったく同じ長さのバージョンをいくつか考え出しましたが、どれも短くなりませんでした。

これを評価される式に変えるアプローチがおそらく勝つと期待しています。しかし、彼らが言うように:「反復することは人間であり、神を再帰することです。」


機能が明示的に許可されるようになりました:)
カルビンの趣味

@ Calvin'sHobbies私が一般的に疑問に思っていたルールの質問がありましたが、それはここで出てくるかもしれません:ソリューションが関数として実装されている場合、これは関数が1回の実行で複数回呼び出されることを意味しますか?たとえば、最初の呼び出しでのみ正しく初期化されるグローバル変数を使用した場合、それは...間違っていますか?
レトコラディ

@Retroはい、そうです、間違っています。この関数は、再解釈せずに何度でも動作するはずです。
カルビンの趣味

1

Clojure-66バイト

これ([] (()) ([] []) [()] [([[] []] [] []) ([] [])])は有効なClojureフォームであることに注意してください。そう:

#(letfn[(g[x](apply(if(list? x)+ *)(map g x)))](g(read-string %)))
  • これは、文字列を受け取り、それを読み取り、に渡す匿名関数gです。
  • ローカルg関数が適用され+、または*の呼び出しの結果をg引数のサブ要素に。
  • 再帰の基本ケースは少し微妙xです。空のシーケンスのときに到達します。(map g x)を返しnilapply操作のニュートラル値を返します。

0

JavaScript(ES6)、116バイト

s=>+[...s].reduce((t,c)=>((x=c==']')||c==')'?t[1].push(t.shift().reduce((a,b)=>x?a*b:a+b,+x)):t.unshift([]),t),[[]])
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.