การประเมินวงเล็บและวงเล็บเป็นจำนวนเต็ม


20

เขียนโปรแกรมที่รับสายอักขระสี่ตัว()[]ที่ตรงกับจุดเหล่านี้:

  • ทุกวงเล็บมีวงเล็บจับคู่ที่เหมาะสม()
  • ทุกวงเล็บซ้ายมีวงเล็บขวาจับคู่[]
  • การจับคู่วงเล็บและวงเล็บจะไม่ทับซ้อนกัน เช่น[(])ไม่ถูกต้องเนื่องจากวงเล็บที่ตรงกันไม่ได้บรรจุอยู่ในวงเล็บที่ตรงกันอย่างสมบูรณ์หรือในทางกลับกัน
  • อักขระตัวแรกและตัวสุดท้ายเป็นคู่ของวงเล็บหรือวงเล็บ ดังนั้น([]([]))และ[[]([])]ถูกต้อง แต่[]([])ไม่ใช่

( ไวยากรณ์สำหรับรูปแบบอินพุตคือ<input> ::= [<input>*] | (<input>*))

วงเล็บและวงเล็บที่จับคู่แต่ละคู่จะประเมินเป็นจำนวนเต็มที่ไม่เป็นลบ:

  • ค่าของคู่ในวงเล็บที่ตรงกันทั้งหมดสรุป การแข่งขันที่ว่างเปล่ามีค่า()0
  • ค่าของคู่ในวงเล็บที่ตรงกันทั้งหมดคูณ การแข่งขันที่ว่างเปล่ามีค่า[]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

อาจจะดีในการแก้ไขคำถามแล้ว ในคำถามก่อนหน้านี้ฉันได้รับแจ้งว่าฟังก์ชั่นไม่ถูกต้องหากมันระบุว่า "เขียนโปรแกรม" ในคำถาม
Reto Koradi

คำตอบ:


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

2
@Dennis whaaa! นั่นมันบ้าคุณสามารถทำสิ่งนั้นได้ ??
aditsu

3
คุณจะถามฉัน ? : P
Dennis

4
@Dennis ผู้สร้าง CJam จะรู้ได้อย่างไรเกี่ยวกับการมีอยู่ของคุณสมบัติดังกล่าว ??
เครื่องมือเพิ่มประสิทธิภาพ

8

เสียงกระเพื่อมสามัญ - 98

(lambda(s)(eval(read-from-string(#1=ppcre:regex-replace-all"\\["(#1#"]"(#1#"\\("s"(+")")")"(*"))))
  1. แทนที่(ด้วย(+
  2. แทนที่[ด้วย(*
  3. แทนที่]ด้วย)
  4. อ่านจากสตริง
  5. Eval

สิ่งนี้ต้องการcl-ppcreโหลดไลบรารีในอิมเมจ lisp ปัจจุบัน

คำอธิบาย

ฟังก์ชั่น*และ+เป็นตัวแปรและส่งกลับค่าที่เป็นกลางเมื่อไม่มีข้อโต้แย้ง สำหรับตัวอย่างของคุณรูปแบบเสียงกระเพื่อมที่ประเมินคือสิ่งต่อไปนี้:

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

และ

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

ไม่มี regexes - 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และสองกองและpq
  • pตัวอักษรในรหัสที่มาจะผลักให้
  • <: ปรากฏจากและผลักดันไปpq
  • r: แทนที่ในs(ต้องเป็นสตริง) จากตัวละครในqการ charactes ในp; ผลจะถูกเก็บไว้ในs; pและqถูกทำให้ว่างเปล่า
  • Rอ่านจากสตริงผลการจัดเก็บในตัวแปรss
  • E: แบบฟอร์ม EVAL เก็บผลในการss

1
Funyy วิธี lisp ใช้ทำบางสิ่งบางอย่างด้วยวงเล็บที่นี่
Syd Kerckhove

@SydKerckhove คุณแสดงความคิดเห็นเพียงแค่ทำให้ฉันคิดว่าคำตอบ Clojure ที่เหมาะสม ขอบคุณมาก!
coredump

6

Pyth, 35 34 33 ไบต์

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

สาธิต.

1 ไบต์ต้องขอบคุณ @Jakube

เราเริ่มต้นด้วยการแยกวิเคราะห์อินพุต รูปแบบอินพุตใกล้กับ 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.

@Jakube ถูกต้องการรวมเป็นหนึ่งไม่มีผลใด ๆ
isaacg

3

Emacs lisp, 94

รูปแบบดูอ่อนมากดังนั้นฉันคิดว่าการแปลงอย่างง่ายอาจใช้งานได้:

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

รูปแบบสื่อกลางดูเหมือนว่า (สำหรับตัวอย่างในคำถาม):

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

เราได้รับความช่วยเหลือจากข้อเท็จจริงที่ว่าการเพิ่มและการคูณทำสิ่งที่เราต้องการด้วยรายการอาร์กิวเมนต์ว่าง

เสื่อมโทรมและโต้ตอบสำหรับคุณที่จะเล่น:

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

ฉันควรอ่านให้ละเอียดยิ่งขึ้น - ทางออก Common Lisp ใช้แนวทางเดียวกันทุกประการ!
Toby Speight

1
เราต้องการ Emacs Lisp มากกว่าคำตอบ! Btw ฉันไม่ได้นับ แต่คุณสามารถตีมันได้อีกเล็กน้อยโดยใช้แลมบ์ดารับสตริงเป็นพารามิเตอร์และลบinteractive (แทนที่จะเป็นบัฟเฟอร์ - สตริงใช้อ่านจากสตริง)
coredump

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>

ให้เอาต์พุตใน unary

แต่ละบรรทัดควรไปที่ไฟล์ของตัวเอง แต่คุณสามารถเรียกใช้รหัสเป็นไฟล์เดียวที่มีการ-sตั้งค่าสถานะ เช่น:

> 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,]และเครื่องหมายจุลภาคต่อท้ายสุดท้ายทำให้สิ่งทั้งหมดเป็นสิ่งอันดับ ส่วนที่ไม่ตรงไปตรงมาเท่านั้นอื่น ๆ จะเป็นord(c)%31%7ที่จะแยกออกจากตัวอักษรที่แตกต่างกัน (มันประเมิน2, 3, 1, 0สำหรับ(, ), [, ]ตามลำดับ)

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

1
มันไม่ทำงานเป็นโปรแกรมใช่ไหม? คำถามถามหาโปรแกรมดังนั้นฉันไม่คิดว่าการจัดหาฟังก์ชั่นตรงตามข้อกำหนด อย่างน้อยนั่นคือสิ่งที่ผู้คนบอกฉันครั้งสุดท้ายที่ฉันส่งฟังก์ชั่นเมื่อมันบอกว่า "โปรแกรม" ในคำถาม :)
Reto Koradi

1

Java, 301

วิธีการที่แตกต่างจากคำตอบของ TheNumberOne ถึงแม้ว่าฉันจะเป็นแบบวนซ้ำในธรรมชาติ อินพุตถูกนำมาจากบรรทัดคำสั่ง วิธีการโมฆะบันทึกสองสามไบต์เมื่อลบอักขระที่ไม่ต้องการอีกต่อไป

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

แง่มุมหนึ่งที่ฉันดิ้นรนคือฟังก์ชั่นนั้นมีค่าที่ส่งคืนสองค่าคือผลิตภัณฑ์ / ผลรวมและตำแหน่งใหม่ในสตริง แต่ฉันต้องการฟังก์ชั่นที่คืนเฉพาะผลลัพธ์ดังนั้นการคืนค่า tuple จึงไม่ทำงาน รุ่นนี้ใช้อาร์กิวเมนต์ "อ้างอิง" (รายการที่มีองค์ประกอบเดียว) เพื่อส่งผ่านตำแหน่งกลับจากฟังก์ชัน

ฉันมีรุ่นที่สั้นกว่า (103 ไบต์) ที่ใช้ตัวแปรกลางสำหรับตำแหน่ง แต่นั่นจะทำงานเฉพาะในสายแรก และฟังก์ชั่นที่ใช้งานได้เพียงครั้งเดียวดูเหมือนว่าจะคาวเล็กน้อย ไม่แน่ใจว่ามันจะเป็นที่ยอมรับสำหรับรหัสกอล์ฟหรือไม่

อัลกอริทึมเป็นการเรียกซ้ำแบบตรงไปตรงมา ฉันลองชุดรูปแบบจำนวนมากสำหรับนิพจน์ที่อัปเดตผลิตภัณฑ์ / ผลรวม ฉันมากับรุ่นไม่กี่รุ่นที่มีความยาวเท่ากัน แต่ไม่มีสั้นกว่าเลย

ฉันคาดหวังว่าวิธีที่เปลี่ยนสิ่งนี้ให้เป็นนิพจน์ที่ได้รับการประเมินอาจเป็นชัยชนะ แต่อย่างที่พวกเขาพูดว่า: "การย้ำคือมนุษย์เพื่อชดเชยสิ่งศักดิ์สิทธิ์"


ตอนนี้ฟังก์ชั่นอนุญาตอย่างชัดเจน :)
งานอดิเรกของ Calvin

@ Calvin'sHobbies มีคำถามเกี่ยวกับกฎที่ฉันมักจะสงสัย แต่ก็อาจเข้ามาเล่นได้ที่นี่: หากวิธีการแก้ปัญหาถูกนำมาใช้เป็นฟังก์ชั่นนี่หมายความว่าฟังก์ชั่นนั้นสามารถเรียกได้มากกว่าหนึ่งครั้ง ตัวอย่างเช่นหากใช้ตัวแปรโกลบอลที่กำหนดค่าเริ่มต้นอย่างถูกต้องในการโทรครั้งแรกนั่นจะเป็น ... ผิดหรือเปล่า?
Reto Koradi

@ เรโทรฉันจะบอกว่าใช่มันผิด ฟังก์ชั่นควรทำงานหลาย ๆ ครั้งโดยไม่ต้องตีความซ้ำ
งานอดิเรกของ Calvin

1

Clojure - 66 ไบต์

ขอให้สังเกตว่า([] (()) ([] []) [()] [([[] []] [] []) ([] [])])เป็นรูปแบบ Clojure ที่ถูกต้อง ดังนั้น:

#(letfn[(g[x](apply(if(list? x)+ *)(map g x)))](g(read-string %)))
  • gนี่คือฟังก์ชั่นที่ไม่ระบุชื่อการสตริงอ่านมันและให้กับ
  • gใช้ฟังก์ชันท้องถิ่น+หรือ*กับผลของการภาวนาของgในองค์ประกอบย่อยของการขัดแย้ง
  • กรณีพื้นฐานของการเรียกซ้ำเป็นเพียงเล็กน้อย: มันจะถึงเมื่อxอยู่ในลำดับที่ว่างเปล่า; (map g x)ส่งคืนnilและapplyส่งคืนค่าที่เป็นกลางสำหรับการดำเนินการ

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.