괄호와 대괄호를 정수로 평가


20

()[]다음 사항을 만족 하는 네 개의 문자열로 구성된 프로그램을 작성하십시오 .

  • 모든 왼쪽 괄호 (에는 일치하는 오른쪽 괄호가 )있습니다.
  • 모든 왼쪽 브래킷 [에는 일치하는 오른쪽 브래킷이 ]있습니다.
  • 일치하는 괄호와 괄호 쌍은 겹치지 않습니다. 예를 들어 [(]), 일치하는 괄호가 일치하는 괄호 안에 완전히 포함되지 않았거나 그 반대이기 때문에 유효하지 않습니다.
  • 첫 문자와 마지막 문자는 일치하는 괄호 또는 괄호 쌍입니다. 그래서 ([]([]))하고는 [[]([])]유효하지만, []([])하지 않습니다.

( 입력 형식 의 문법<input> ::= [<input>*] | (<input>*)입니다.)

일치하는 괄호와 대괄호 쌍은 음이 아닌 정수로 평가됩니다.

  • 일치하는 괄호 안에있는 쌍의 값은 모두 합산 됩니다. 빈 일치 ()값은 value 0입니다.
  • 일치하는 대괄호 안에있는 쌍의 값은 모두 곱해 집니다. 빈 일치 []값은 value 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 2016

답변:


11

CJam, 23

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

Dennis에게 큰 크레딧을 제공합니다! 온라인으로 사용해보십시오

설명:

프로그램은 입력을 CJam 표현식으로 변환 한 후 평가합니다.
[…]진다 […1]:*(곱셈 APPEND 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을 만든 사람은 그러한 기능의 존재를 어떻게 알 수 있을까요?
Optimizer

8

커먼 리스프-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두 개의 스택, p그리고 q.
  • 소스 코드의 문자가로 푸시됩니다 p.
  • <:에서 튀어 p나옵니다 q.
  • r:에서 대체합니다 s문자에서의 (문자열이어야합니다) q에있는 Charactes에 p; 결과는 다음에 저장됩니다 s. p그리고 q비워진다.
  • R: 문자열 s에서 읽고 결과를 변수에 저장합니다 s.
  • E: 평가 양식 s, 결과 저장 s.

1
Funyy는 lisp가 괄호로 무언가를하는 데 어떻게 사용되는지 여기에 있습니다.
Syd Kerckhove 2016

@SydKerckhove 당신은 저에게 적절한 Clojure 답변을 생각하게 만듭니다. 고마워요!
코어 덤프

6

Pyth, 35 34 33 바이트

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

데모.

@Jakube 덕분에 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.

@Jakube 맞아, 단항 합산은 효과가 없다.
isaacg 2016 년

3

이맥스 리스프, 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 (버퍼 문자열 대신 문자열에서 읽기 사용) 있습니다.
코어 덤프

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플래그를 사용하여 코드를 하나의 파일로 실행할 수 있습니다 . 예 :

> retina -s brackets <input_1
111111111

나중에 설명하겠습니다.


2

자바, 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

펄 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

파이썬, 99

나는 다양한 방법을 시도했지만 얻을 수있는 가장 짧은 것은 기본적으로 단지 교체와 평가였습니다. ,파이썬이 구문 분석 할 수 [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 2016

1

자바, 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

파이썬 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

내가 어려움을 겪고있는 한 가지 측면은 함수가 기본적으로 두 가지 반환 값, 즉 제품 / 합계와 문자열의 새로운 위치를 가지고 있다는 것입니다. 그러나 결과 만 반환하는 함수가 필요하므로 튜플을 반환해도 작동하지 않습니다. 이 버전은 함수에서 위치를 다시 전달하기 위해 "참조"인수 (한 요소가있는 목록)를 사용합니다.

위치에 전역 변수를 사용하는 더 짧은 버전 (103 바이트)이 있습니다. 그러나 그것은 첫 번째 전화에서만 작동합니다. 그리고 한 번만 작동하는 기능은 약간 비린 것처럼 보입니다. 코드 골프에 적합한 지 확실하지 않습니다.

알고리즘은 간단한 재귀입니다. 제품 / 합계를 업데이트하는 표현식에 대해 여러 변형을 시도했습니다. 나는 정확히 같은 길이의 몇 가지 버전을 만들었지 만 더 짧은 버전은 없었습니다.

나는 이것을 평가되는 표현으로 바꾸는 접근법이 아마 이길 것이라고 예상했다. 그러나 그들이 말한대로 : "반복하는 것은 인간이며, 재귀하는 것입니다."


기능은 이제 명시 적으로 허용되었습니다 :)
Calvin 's Hobbies

@ Calvin'sHobbies 일반적으로 궁금했던 규칙 질문이 있지만 여기서 효과가있을 수 있습니다. 솔루션이 함수로 구현 된 경우 단일 실행에서 함수를 두 번 이상 호출 할 수 있습니까? 예를 들어, 첫 번째 호출에서만 올바르게 초기화 된 전역 변수를 사용했다면 ... 잘못된 것입니까?
Reto Koradi

@Retro 예라고 대답했습니다. 잘못되었습니다. 이 함수는 해석하지 않고 여러 번 작동해야합니다.
Calvin 's Hobbies

1

클로저-66 바이트

공지 사항 ([] (()) ([] []) [()] [([[] []] [] []) ([] [])])유효한 Clojure의 양식입니다. 그래서:

#(letfn[(g[x](apply(if(list? x)+ *)(map g x)))](g(read-string %)))
  • 이것은 문자열을 가져 와서주는 익명의 함수입니다. g 입니다.
  • 로컬 g함수 는 다음의 호출 결과에 적용 +되거나*g 인수의 하위 요소.
  • 재귀의 기본 사례는 약간 미묘합니다. x 빈 시퀀스 일 합니다. (map g x)반환 nilapply운영을위한 중립 값을 반환합니다.

0

자바 스크립트 (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.