Klammern und Klammern als ganze Zahlen auswerten

20

Schreiben Sie ein Programm, das eine Zeichenfolge aus vier Zeichen enthält ()[], die diese Punkte erfüllt:

  • Jede linke Klammer (hat eine passende rechte Klammer ).
  • Jede linke Klammer [hat eine passende rechte Klammer ].
  • Übereinstimmende Paare von Klammern und Klammern überlappen sich nicht. zB [(])ist ungültig, weil die passenden Klammern nicht vollständig in den passenden Klammern enthalten sind und umgekehrt.
  • Das erste und das letzte Zeichen sind übereinstimmende Klammernpaare. Also ([]([]))und [[]([])]gültig ist das aber []([])nicht.

(Eine Grammatik für das Eingabeformat ist <input> ::= [<input>*] | (<input>*).)

Jedes Paar übereinstimmender Klammern und Klammern ergibt eine nicht negative ganze Zahl:

  • Die Werte von Paaren in übereinstimmenden Klammern werden alle summiert . Das leere Match ()hat Wert 0.
  • Die Werte von Paaren in übereinstimmenden Klammern werden alle multipliziert . Das leere Match []hat Wert 1.

(Die Summe oder das Produkt einer Zahl ist dieselbe Zahl.)

Beispielsweise ([](())([][])[()][([[][]][][])([][])])kann aufgeschlüsselt und ausgewertet werden als 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>

Ein anderes Beispiel:

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

Ihr Programm muss die ganze Zahl auswerten und drucken, die durch die gesamte Eingabezeichenfolge dargestellt wird. Sie können davon ausgehen, dass die Eingabe gültig ist. Der kürzeste Code in Bytes gewinnt.

Anstelle eines Programms können Sie auch eine Funktion schreiben, die eine Zeichenfolge aufnimmt und die Ganzzahl ausgibt oder zurückgibt.

Calvins Hobbys
quelle
Fragen im Namen der Python-Übermittlung zur Klärung: Nur Programm, oder sind Funktionen / Rückgabewert in Ordnung?
Sp3000,
Könnte dann gut sein, die Frage zu bearbeiten. In einer früheren Frage wurde mir gesagt, dass Funktionen nicht gültig sind, wenn in der Frage "Programm schreiben" steht.
Reto Koradi

Antworten:

11

CJam, 23

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

Mit GROSSEN Credits an Dennis! Probieren Sie es online aus

Erläuterung:

Das Programm konvertiert die Eingabe in einen CJam-Ausdruck und wertet ihn dann aus.
[…]wird […1]:*(1 anhängen und multiplizieren)
(…)wird […0]:+(0 anhängen und addieren)

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
aditsu
quelle
1
Transliteration spart 4 Bytes:q"])(""1]:*0]:+["4/ers~
Dennis
2
@ Tennis whaaa! Das ist verrückt, kannst du das machen?
Aditsu
3
Du fragst mich ? : P
Dennis
4
@Dennis Wie würde der Schöpfer von CJam von der Existenz eines solchen Features erfahren?
Optimierer
8

Common Lisp - 98

(lambda(s)(eval(read-from-string(#1=ppcre:regex-replace-all"\\["(#1#"]"(#1#"\\("s"(+")")")"(*"))))
  1. Ersetzen (durch(+
  2. Ersetzen [durch(*
  3. Ersetzen ]durch)
  4. Aus Zeichenfolge lesen
  5. Eval

Dazu muss die cl-ppcreBibliothek in das aktuelle Lisp-Bild geladen werden.

Erläuterung

Funktionen *und +sind variabel und geben ihren neutralen Wert zurück, wenn keine Argumente angegeben werden. Für Ihre Beispiele sind die ausgewerteten Lisp-Formulare die folgenden:

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

und

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

Ohne reguläre Ausdrücke - 183 Bytes

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

Komm schon, Lisp - 16 Bytes (experimentell)

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

Andere Sprachen sind so knapp, dass ich versucht bin, meine eigene Golfsprache basierend auf Common Lisp für kürzere Saitenmanipulationen zu entwickeln. Derzeit gibt es keine Spezifikation und die Bewertungsfunktion ist die folgende:

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

Tests:

(cmon-lisp "+((<r*([<r)]<rRE" "([] [] ([] []))")
=> 4
  • Es gibt ein implizites Argument namens sund zwei Stapel pund q.
  • Zeichen im Quellcode werden an verschoben p.
  • <: knallt ab pund drückt auf q.
  • r: Ersetzt in s(muss ein String sein) von Zeichen in qbis Zeichen in p; Ergebnis wird gespeichert in s; pund qwerden geleert.
  • R: Aus String lesen s, Ergebnis in Variable speichern s.
  • E: Auswertungsform s, Ergebnis speichern in s.
Core-Dump
quelle
1
Funyy, wie Lispel verwendet wird, um hier etwas mit Klammern zu tun.
Syd Kerckhove
@SydKerckhove Ihr Kommentar lässt mich nur an eine passende Clojure-Antwort denken. Vielen Dank!
Coredump
6

Pyth, 35 34 33 Bytes

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

Demonstration.

1 Byte danke an @Jakube.

Wir beginnen mit der Analyse der Eingabe. Das Eingabeformat ist ähnlich wie bei Python, aber nicht ganz. Wir brauchen Kommas nach jeder Gruppe in Klammern oder Klammern. Das Komma am Ende einer Gruppe in Klammern ist unnötig, aber harmlos. Um dies zu erreichen, verwenden wir diesen Code:

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.

,Am Ende der Zeichenfolge verbleibt ein Extra , das das gesamte Objekt in ein Tupel einwickelt. Dies ist jedoch harmlos, da das Tupel summiert wird und daher einen Wert aufweist, der dem Element entspricht.

Nachdem die Zeichenfolge analysiert wurde, müssen wir ihren Wert finden. Dies geschieht mit einer benutzerdefinierten Funktion y, die für das analysierte Objekt aufgerufen wird. Die Funktion ist wie folgt definiert:

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
quelle
@Jakube Richtig, die unäre Summierung hat keine Auswirkung.
Isaacg
3

Emacs lisp, 94

Das Format sieht sehr lispy aus, daher dachte ich, dass eine einfache Transformation funktionieren könnte:

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

Das Zwischenformat sieht ungefähr so ​​aus (für das Beispiel in der Frage):

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

Wir werden durch die Tatsache unterstützt, dass Addition und Multiplikation bereits mit einer leeren Argumentliste das tun, was wir wollen.

Entgolft und interaktiv für Ihr Spielvergnügen:

(defun paren_eval()
  (interactive "*")
  (format-replace-strings '(("(" . "(+")
                            ("[" . "(*")
                            ("]" . ")")))
  (eval (read (buffer-string)))
)
Toby Speight
quelle
Ich hätte es genauer lesen sollen - die Common-Lisp-Lösung geht genauso vor!
Toby Speight
1
Wir brauchen mehr Antworten von Emacs Lisp !. Übrigens, ich habe nicht gezählt, aber Sie könnten ein bisschen mehr Golf spielen, indem Sie ein Lambda verwenden, einen String als Parameter nehmen und entfernen interactive (anstelle von Buffer-String Read-from-String verwenden).
Coredump
2

Netzhaut , 111 Bytes

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

Gibt eine unäre Ausgabe aus.

Jede Zeile sollte in eine eigene Datei gehen, aber Sie können den Code als eine Datei mit dem -sFlag ausführen . Z.B:

> retina -s brackets <input_1
111111111

Erklärung kommt später.

randomra
quelle
2

Java, 349 Zeichen

Ein einfacher rekursiver Ansatz. Erwartet, dass der String das erste Argument ist, mit dem das Programm aufgerufen wird.

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

Erweitert:

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;
    }
}
Die Nummer eins
quelle
2

Perl 5, 108

Als Dolmetscher gemacht, statt neu zu schreiben und zu bewerten. Keine großartige Show, aber es macht trotzdem Spaß zu schreiben.

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]

Nicht golfen:

# 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.
hobbs
quelle
2

Python, 99

Ich habe verschiedene Methoden ausprobiert, aber die kürzeste, die ich bekommen konnte, war im Grunde nur ein Ersatz und eine Bewertung. Ich war angenehm überrascht, als ich feststellte, dass ich alle abschließenden Zeichen belassen konnte ,, da Python analysieren kann [1,2,]und das letzte abschließende Komma nur das Ganze in ein Tupel setzt. Die einzige andere nicht einfach Teil wäre das ord(c)%31%7die verschiedenen Charaktere zu trennen out (es ausgewertet 2, 3, 1, 0für (, ), [, ]respectively)

F=lambda s:eval(''.join(["],1),","reduce(int.__mul__,[","sum([","]),"][ord(c)%31%7]for c in s))[0]
KSab
quelle
1
Das funktioniert nicht als Programm, oder? In der Frage wird nach einem Programm gefragt, daher glaube ich nicht, dass die Bereitstellung einer Funktion den Anforderungen entspricht. Zumindest haben mir die Leute das letzte Mal erzählt, als ich eine Funktion eingereicht habe, in der "Programm" in der Frage stand. :)
Reto Koradi
1

Java, 301

Ein etwas anderer Ansatz als die Antwort von TheNumberOne, obwohl meine auch rekursiver Natur ist. Die Eingabe erfolgt über die Befehlszeile. Die Methode void spart einige Bytes, wenn die nicht mehr benötigten Zeichen entfernt werden.

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

erweitert:

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));
    }
}
Jack Ammo
quelle
1

Python, 117 110 109 Bytes

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

Ein Aspekt, mit dem ich zu kämpfen hatte, ist, dass die Funktion im Grunde zwei Rückgabewerte hat: das Produkt / die Summe und die neue Position in der Zeichenfolge. Ich benötige jedoch eine Funktion, die nur das Ergebnis zurückgibt, sodass das Zurückgeben eines Tupels nicht funktioniert. Diese Version verwendet ein "Referenz" -Argument (Liste mit einem Element), um die Position von der Funktion zurückzugeben.

Ich habe eine kürzere Version (103 Bytes), die eine globale Variable für die Position verwendet. Das funktioniert aber nur beim ersten Anruf. Und eine Funktion, die nur einmal funktioniert, scheint ein bisschen faul zu sein. Ich bin mir nicht sicher, ob es für Code-Golf akzeptabel wäre.

Der Algorithmus ist eine einfache Rekursion. Ich habe eine Reihe von Variationen für den Ausdruck ausprobiert, der das Produkt / die Summe aktualisiert. Ich hatte ein paar Versionen, die genau gleich lang waren, aber keine kürzer.

Ich habe irgendwie erwartet, dass der Ansatz, der daraus einen Ausdruck macht, der bewertet wird, wahrscheinlich gewinnen wird. Aber wie sie sagen: "Iterieren ist menschlich, göttlich wiederverwenden."

Reto Koradi
quelle
Funktionen jetzt explizit erlaubt :)
Calvins Hobbys
@ Calvin'sHobbies Habe eine Regelfrage, über die ich mich im Allgemeinen gewundert habe, aber die könnte hier ins Spiel kommen: Wenn eine Lösung als Funktion implementiert wird, bedeutet dies, dass die Funktion mehr als einmal in einem Lauf aufgerufen werden kann? Wenn es zum Beispiel eine globale Variable verwendet, die nur beim ersten Aufruf korrekt initialisiert wird, wäre das ... falsch?
Reto Koradi
@ Retro Ich würde ja sagen, es ist falsch. Die Funktion sollte beliebig oft funktionieren, ohne sie neu zu interpretieren.
Calvins Hobbys
1

Clojure - 66 Bytes

Beachten Sie, dass ([] (()) ([] []) [()] [([[] []] [] []) ([] [])])es sich um ein gültiges Clojure-Formular handelt. So:

#(letfn[(g[x](apply(if(list? x)+ *)(map g x)))](g(read-string %)))
  • Dies ist eine anonyme Funktion, die eine Zeichenfolge aufnimmt, liest und gibt g.
  • Die lokale gFunktion gilt +oder *für das Ergebnis des Aufrufs von gUnterelementen ihrer Argumente.
  • Der Grundfall der Rekursion ist etwas subtil: Er wird xin einer leeren Sequenz erreicht; (map g x)zurückkehrt nil, und applyden neutralen Wert für den Betrieb zurückkehrt.
Core-Dump
quelle
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),[[]])
Ry-
quelle