Đánh giá dấu ngoặc đơn và dấu ngoặc là số nguyên


20

Viết chương trình lấy một chuỗi gồm bốn ký tự ()[]thỏa mãn các điểm sau:

  • Mỗi dấu ngoặc trái (có dấu ngoặc đơn bên phải ).
  • Mỗi khung bên trái [có một khung bên phải phù hợp ].
  • Các cặp dấu ngoặc đơn và dấu ngoặc sẽ không trùng nhau. ví dụ: [(])không hợp lệ vì dấu ngoặc phù hợp không được chứa đầy đủ trong dấu ngoặc đơn, cũng không phải ngược lại.
  • Các ký tự đầu tiên và cuối cùng là một cặp dấu ngoặc hoặc dấu ngoặc phù hợp. Vì vậy ([]([]))[[]([])]có giá trị nhưng []([])không.

(Một ngữ pháp cho định dạng đầu vào là <input> ::= [<input>*] | (<input>*).)

Mỗi cặp dấu ngoặc đơn và dấu ngoặc khớp ước tính thành một số nguyên không âm:

  • Các giá trị của các cặp bên trong dấu ngoặc phù hợp đều được tính tổng . Trận đấu trống ()có giá trị 0.
  • Các giá trị của các cặp trong dấu ngoặc phù hợp đều được nhân lên . Trận đấu trống []có giá trị 1.

( Tổng hoặc tích của một số là cùng một số đó.)

Ví dụ: ([](())([][])[()][([[][]][][])([][])])có thể được chia nhỏ và đánh giá là 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>

Một vi dụ khac:

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

Chương trình của bạn cần đánh giá và in số nguyên được biểu thị bằng toàn bộ chuỗi đầu vào. Bạn có thể giả sử đầu vào là hợp lệ. Mã ngắn nhất tính bằng byte thắng.

Thay vì một chương trình, bạn có thể viết một hàm lấy một chuỗi và in hoặc trả về số nguyên.


Yêu cầu thay mặt trình đệ trình Python để làm rõ: Chỉ chương trình, hoặc các hàm / giá trị trả về có ổn không?
Sp3000

Có thể là tốt để chỉnh sửa câu hỏi sau đó. Trong một câu hỏi trước đây, tôi đã nói rằng các hàm không hợp lệ nếu nó nói "viết chương trình" trong câu hỏi.
Reto Koradi

Câu trả lời:


11

CJam, 23

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

Với các khoản tín dụng LỚN cho Dennis! Dùng thử trực tuyến

Giải trình:

Chương trình chuyển đổi đầu vào thành biểu thức CJam sau đó đánh giá nó.
[…]trở thành […1]:*(nối 1 và nhân)
(…)trở thành […0]:+(nối 0 và thêm)

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
Chuyển ngữ lưu 4 byte:q"])(""1]:*0]:+["4/ers~
Dennis

2
@Dennis whaaa! Điều đó thật điên rồ, bạn có thể làm điều đó ??
aditsu

3
Bạn đang hỏi tôi ? : P
Dennis

4
@Dennis Làm thế nào để người tạo ra CJam biết về sự tồn tại của tính năng như vậy ??
Tối ưu hóa

8

Lisp thường gặp - 98

(lambda(s)(eval(read-from-string(#1=ppcre:regex-replace-all"\\["(#1#"]"(#1#"\\("s"(+")")")"(*"))))
  1. Thay thế ( bằng(+
  2. Thay thế [ bằng(*
  3. Thay thế ] bằng)
  4. Đọc từ chuỗi
  5. Eval

Điều này đòi hỏi cl-ppcre thư viện phải được tải trong hình ảnh hiện tại.

Giải trình

Các hàm *+là biến đổi và trả về giá trị trung tính của chúng khi không có đối số. Đối với ví dụ của bạn, mẫu lisp được đánh giá là những mẫu sau:

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

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

Không có biểu thức chính - 183 byte

(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 byte (thử nghiệm)

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

Các ngôn ngữ khác rất ngắn gọn đến nỗi tôi muốn tạo ra ngôn ngữ chơi gôn của riêng mình dựa trên Common Lisp, cho các thao tác chuỗi ngắn hơn. Hiện tại không có thông số kỹ thuật và chức năng eval là một chức năng sau:

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

Các xét nghiệm:

(cmon-lisp "+((<r*([<r)]<rRE" "([] [] ([] []))")
=> 4
  • có một đối số ngầm được gọi svà hai ngăn xếp, pq.
  • các ký tự trong mã nguồn được đẩy tới p.
  • <: bật từ pvà đẩy đến q.
  • r: thay thế trong s(phải là một chuỗi) từ các ký tự qthành các biểu đồ trong p; kết quả được lưu trữ trong s; pqđược làm trống
  • R: đọc từ chuỗi s, lưu kết quả trong biến s.
  • E: hình thức eval s, kết quả lưu trữ trong s.

1
Funyy làm thế nào lisp được sử dụng để làm một cái gì đó với dấu ngoặc ở đây.
Syd Kerckhove

@SydKerckhove Bạn nhận xét chỉ cần làm cho tôi nghĩ về một câu trả lời Clojure thích hợp. Cảm ơn rất nhiều!
coredump

6

Pyth, 35 34 33 byte

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

Trình diễn.

1 byte nhờ @Jakube.

Chúng tôi bắt đầu bằng cách phân tích cú pháp đầu vào. Định dạng đầu vào gần với Python, nhưng không hoàn toàn. Chúng ta cần dấu phẩy sau mỗi nhóm được ngoặc đơn hoặc ngoặc. Dấu phẩy ở cuối nhóm có dấu ngoặc là không cần thiết, nhưng vô hại. Để thực hiện điều này, chúng tôi sử dụng mã này:

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.

Điều này sẽ để lại một phần thừa ,ở cuối chuỗi, nó sẽ bao bọc toàn bộ đối tượng trong một tuple, nhưng điều này là vô hại, bởi vì tuple sẽ được tính tổng, và do đó có giá trị bằng với phần tử của nó.

Bây giờ chuỗi được phân tích cú pháp, chúng ta phải tìm giá trị của nó. Điều này được thực hiện bằng cách sử dụng một hàm do người dùng định nghĩa y, được gọi trên đối tượng được phân tích cú pháp. chức năng được định nghĩa như sau:

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.

@Jakube Đúng vậy, tổng kết đơn phương không có hiệu lực.
isaacg

3

Emacs lisp, 94

Định dạng trông rất lố lăng, vì vậy tôi nghĩ rằng một phép biến đổi đơn giản có thể hoạt động:

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

Định dạng trung gian trông giống như (ví dụ trong câu hỏi):

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

Chúng tôi được giúp đỡ bởi thực tế là phép cộng và phép nhân đã làm những gì chúng ta muốn với một danh sách đối số trống.

Degolfed, và tương tác, cho bạn chơi niềm vui:

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

Tôi nên đọc kỹ hơn - giải pháp Lisp chung có cách tiếp cận chính xác!
Toby Speight

1
Chúng tôi cần thêm câu trả lời Emacs Lisp!. Btw, tôi không tính nhưng bạn có thể đánh gôn thêm một chút bằng cách sử dụng lambda, lấy một chuỗi làm tham số và loại bỏ interactive (thay vì chuỗi đệm, sử dụng đọc từ chuỗi).
coredump

2

Võng mạc , 111 byte

[\([](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>

Cung cấp đầu ra trong unary.

Mỗi dòng nên đi đến tệp riêng của nó nhưng bạn có thể chạy mã dưới dạng một tệp có -scờ. Ví dụ:

> retina -s brackets <input_1
111111111

Giải thích đến sau.


2

Java, 349 ký tự

Một cách tiếp cận đệ quy đơn giản. Dự kiến ​​chuỗi là đối số đầu tiên được sử dụng để gọi chương trình.

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

Mở rộng:

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

Thực hiện như một thông dịch viên chứ không phải viết lại và eval. Không phải là một chương trình tuyệt vời, nhưng dù sao cũng vui để viết.

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]

Chưa chơi gôn:

# 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

Con trăn, 99

Tôi đã thử nhiều phương pháp khác nhau nhưng ngắn nhất tôi có thể nhận được về cơ bản chỉ là thay thế và đánh giá. Tôi đã rất ngạc nhiên khi thấy rằng tôi có thể để lại tất cả các dấu ,, vì Python có thể phân tích cú pháp [1,2,]và dấu phẩy cuối cùng chỉ đặt toàn bộ trong một tuple. Phần không đơn giản chỉ khác sẽ là ord(c)%31%7để tách ra các nhân vật khác nhau (nó để đánh giá 2, 3, 1, 0cho (, ), [, ]tương ứng)

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

1
Điều này không hoạt động như một chương trình, phải không? Câu hỏi yêu cầu một chương trình, vì vậy tôi không nghĩ việc cung cấp một chức năng đáp ứng các yêu cầu. Ít nhất đó là những gì mọi người nói với tôi lần trước tôi đã gửi một chức năng khi nó nói "chương trình" trong câu hỏi. :)
Reto Koradi

1

Java, 301

một chút cách tiếp cận khác với câu trả lời của TheNumberOne, mặc dù bản chất của tôi cũng là đệ quy. Đầu vào được lấy từ dòng lệnh. Phương thức void lưu một vài byte khi loại bỏ các ký tự không còn cần thiết.

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

mở rộng:

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 byte

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

Một khía cạnh tôi đã đấu tranh là về cơ bản hàm có hai giá trị trả về: sản phẩm / tổng và vị trí mới trong chuỗi. Nhưng tôi cần một hàm chỉ trả về kết quả, vì vậy trả về một tuple không hoạt động. Phiên bản này sử dụng đối số "tham chiếu" (danh sách có một phần tử), để chuyển vị trí trở lại từ hàm.

Tôi có một phiên bản ngắn hơn (103 byte) sử dụng biến toàn cục cho vị trí. Nhưng điều đó sẽ chỉ hoạt động trên cuộc gọi đầu tiên. Và một chức năng chỉ hoạt động một lần có vẻ hơi tanh. Không chắc chắn nếu nó sẽ được chấp nhận cho mã golf.

Thuật toán là đệ quy đơn giản. Tôi đã thử một số biến thể cho biểu thức cập nhật sản phẩm / tổng. Tôi đã đưa ra một vài phiên bản có cùng độ dài, nhưng không có phiên bản nào ngắn hơn.

Tôi dự đoán rằng cách tiếp cận biến điều này thành một biểu thức được đánh giá có thể sẽ thắng. Nhưng như họ nói: "Lặp đi lặp lại là con người, để tái diễn thần thánh".


Các chức năng hiện được cho phép rõ ràng :)
Sở thích của Calvin

@ Calvin'sHobbies Có một câu hỏi về quy tắc mà tôi thường thắc mắc, nhưng điều đó có thể xuất hiện ở đây: Nếu một giải pháp được triển khai như một hàm, điều này có nghĩa là hàm này có thể được gọi nhiều lần trong một lần chạy không? Ví dụ: nếu nó sử dụng một biến toàn cục chỉ được khởi tạo chính xác trong cuộc gọi đầu tiên, điều đó có ... sai không?
Reto Koradi

@Retro Tôi muốn nói có, nó sai. Hàm sẽ hoạt động với số lần bất kỳ mà không diễn giải lại.
Sở thích của Calvin

1

Clojure - 66 byte

Lưu ý rằng đó ([] (()) ([] []) [()] [([[] []] [] []) ([] [])])là một hình thức Clojure hợp lệ. Vì thế:

#(letfn[(g[x](apply(if(list? x)+ *)(map g x)))](g(read-string %)))
  • Đây là một hàm ẩn danh lấy một chuỗi, đọc nó và đưa cho g .
  • Hàm cục bộ gáp dụng +hoặc *cho kết quả của việc gọi các gphần tử con của các đối số của nó.
  • Trường hợp cơ bản của đệ quy là một chút tinh tế: nó đạt được khi xtrong một chuỗi trống; (map g x)trả về nilapplytrả về giá trị trung tính cho thao tác.

0

JavaScript (ES6), 116 byte

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),[[]])
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.