Évaluation des parenthèses et des parenthèses en tant que nombres entiers


20

Écrivez un programme qui accepte une chaîne de quatre caractères ()[]qui satisfait ces points:

  • Chaque parenthèse gauche (a une parenthèse droite correspondante ).
  • Chaque support gauche [a un support droit correspondant ].
  • Les paires de parenthèses et de parenthèses correspondantes ne se chevaucheront pas. eg [(])n'est pas valide car les crochets correspondants ne sont pas entièrement contenus dans les parenthèses correspondantes, ni vice-versa.
  • Le premier et le dernier caractère sont une paire de parenthèses ou de crochets correspondants. Donc ([]([]))et [[]([])]sont valides mais []([])ne le sont pas.

(Une grammaire pour le format d'entrée est <input> ::= [<input>*] | (<input>*).)

Chaque paire de parenthèses et de crochets correspondants correspond à un entier non négatif:

  • Les valeurs des paires entre parenthèses correspondantes sont toutes additionnées . La correspondance vide ()a une valeur 0.
  • Les valeurs des paires entre parenthèses correspondantes sont toutes multipliées . La correspondance vide []a une valeur 1.

(La somme ou le produit d'un nombre est ce même nombre.)

Par exemple, ([](())([][])[()][([[][]][][])([][])])peut être décomposé et évalué comme 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>

Un autre exemple:

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

Votre programme doit évaluer et imprimer l'entier représenté par la chaîne d'entrée entière. Vous pouvez supposer que l'entrée est valide. Le code le plus court en octets gagne.

Au lieu d'un programme, vous pouvez écrire une fonction qui prend une chaîne et imprime ou renvoie l'entier.


Demander au nom de la soumission Python des éclaircissements: programme uniquement, ou les fonctions / valeur de retour sont-elles correctes?
Sp3000

Cela pourrait être bon de modifier la question alors. Dans une question précédente, on m'a dit que les fonctions ne sont pas valides si on dit "écrire un programme" dans la question.
Reto Koradi

Réponses:


11

CJam, 23

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

Avec de GRANDS crédits à Dennis! Essayez-le en ligne

Explication:

Le programme convertit l'entrée en une expression CJam puis l'évalue.
[…]devient […1]:*(ajouter 1 et multiplier)
(…)devient […0]:+(ajouter 0 et ajouter)

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
La translittération économise 4 octets:q"])(""1]:*0]:+["4/ers~
Dennis

2
@Dennis whaaa! C'est fou, tu peux le faire ??
aditsu

3
Tu me demandes ? : P
Dennis

4
@Dennis Comment le créateur de CJam pourrait-il connaître l'existence d'une telle fonctionnalité ??
Optimizer

8

Lisp commun - 98

(lambda(s)(eval(read-from-string(#1=ppcre:regex-replace-all"\\["(#1#"]"(#1#"\\("s"(+")")")"(*"))))
  1. Remplacer (par(+
  2. Remplacer [par(*
  3. Remplacer ]par)
  4. Lire à partir d'une chaîne
  5. Eval

Cela nécessite que la cl-ppcrebibliothèque soit chargée dans l'image lisp actuelle.

Explication

Les fonctions *et +sont variadiques et renvoient leur valeur neutre lorsqu'aucun argument n'est donné. Pour vos exemples, la forme lisp évaluée est la suivante:

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

et

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

Sans regexes - 183 octets

(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 octets (expérimental)

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

Les autres langues sont tellement laconiques que je suis tenté de créer mon propre langage de golf basé sur Common Lisp, pour des manipulations de cordes plus courtes. Actuellement, il n'y a pas de spécification et la fonction eval est la suivante:

(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
  • il y a un argument implicite appelé set deux piles, pet q.
  • les caractères du code source sont poussés vers p.
  • <: sort pet pousse vers q.
  • r: remplace dans s(doit être une chaîne) des caractères dans qles caractères dans p; le résultat est stocké dans s; pet qsont vidés.
  • R: lire à partir d'une chaîne s, stocker le résultat dans une variable s.
  • E: formulaire eval s, stocker le résultat dans s.

1
Funyy comment lisp est utilisé pour faire quelque chose avec des crochets ici.
Syd Kerckhove

@SydKerckhove Vos commentaires me font juste penser à une réponse appropriée de Clojure. Merci beaucoup!
coredump

6

Pyth, 35 34 33 octets

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

Manifestation.

1 octet grâce à @Jakube.

Nous commençons par analyser l'entrée. Le format d'entrée est proche de Python, mais pas tout à fait. Nous avons besoin de virgules après chaque groupe entre parenthèses ou entre crochets. La virgule à la fin d'un groupe entre crochets est inutile, mais inoffensive. Pour ce faire, nous utilisons ce 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.

Cela laissera un extra ,à la fin de la chaîne, ce qui enveloppera tout l'objet dans un tuple, mais cela est inoffensif, car le tuple sera additionné, et aura donc une valeur égale à son élément.

Maintenant que la chaîne est analysée, nous devons trouver sa valeur. Cela se fait à l'aide d'une fonction définie par l'utilisateur y, qui est appelée sur l'objet analysé. la fonction est définie comme suit:

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 À droite, la sommation unaire n'a aucun effet.
isaacg

3

Emacs lisp, 94

Le format est très vif, j'ai donc pensé qu'une simple transformation pourrait fonctionner:

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

Le format intermédiaire ressemble à quelque chose (pour l'exemple de la question):

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

Nous sommes aidés par le fait que l'addition et la multiplication font déjà ce que nous voulons avec une liste d'arguments vide.

Dégolfé et interactif, pour vous faire plaisir:

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

J'aurais dû lire de plus près - la solution Common Lisp adopte exactement la même approche!
Toby Speight

1
Nous avons besoin de plus de réponses Emacs Lisp !. Btw, je n'ai pas compté mais vous pouvez le jouer un peu plus en utilisant un lambda, en prenant une chaîne comme paramètre et en la supprimant interactive (au lieu de buffer-string, utilisez read-from-string).
coredump

2

Rétine , 111 octets

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

Donne la sortie en unaire.

Chaque ligne doit aller dans son propre fichier mais vous pouvez exécuter le code comme un seul fichier avec l' -sindicateur. Par exemple:

> retina -s brackets <input_1
111111111

L'explication vient plus tard.


2

Java, 349 caractères

Une approche récursive simple. Attend que la chaîne soit le premier argument utilisé pour appeler le programme.

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

Étendu:

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

Fait en tant qu'interprète plutôt que de réécrire et d'évaluer. Pas une grande projection, mais amusant à écrire quand même.

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]

Non-golfé:

# 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

J'ai essayé une variété de méthodes, mais la plus courte que j'ai pu obtenir était essentiellement un remplacement et une évaluation. J'ai été agréablement surpris de constater que je pouvais laisser tous les ,s [1,2,]finaux , car Python peut analyser et la virgule finale finale met juste le tout dans un tuple. La seule autre partie non simple serait la ord(c)%31%7pour séparer les différents personnages (il évalue à 2, 3, 1, 0pour (, ), [, ]respectivement)

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

1
Cela ne fonctionne pas comme un programme, n'est-ce pas? La question demande un programme, donc je ne pense pas que fournir une fonction réponde aux exigences. C'est du moins ce que les gens m'ont dit la dernière fois que j'ai soumis une fonction quand elle disait "programme" dans la question. :)
Reto Koradi

1

Java, 301

une approche un peu différente de la réponse de TheNumberOne, bien que la mienne soit également de nature récursive. L'entrée provient de la ligne de commande. La méthode void enregistre quelques octets lors de la suppression des caractères qui ne sont plus nécessaires.

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

étendu:

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 octets

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

Un aspect avec lequel je me débattais est que la fonction a essentiellement deux valeurs de retour: le produit / somme et la nouvelle position dans la chaîne. Mais j'ai besoin d'une fonction qui ne renvoie que le résultat, donc retourner un tuple ne fonctionne pas. Cette version utilise un argument "référence" (liste avec un élément), pour retransmettre la position de la fonction.

J'ai une version plus courte (103 octets) qui utilise une variable globale pour la position. Mais cela ne fonctionnera que lors du premier appel. Et une fonction qui ne fonctionne qu'une seule fois semble un peu louche. Je ne sais pas si ce serait acceptable pour le golf de code.

L'algorithme est une récursivité simple. J'ai essayé un certain nombre de variantes pour l'expression qui met à jour le produit / somme. J'ai proposé quelques versions qui étaient exactement de la même longueur, mais aucune n'était plus courte.

Je m'attendais en quelque sorte à ce que l'approche qui transforme cela en une expression qui soit évaluée gagnerait probablement. Mais comme on dit: "Itérer est humain, récuser divin".


Fonctions désormais explicitement autorisées :)
Calvin's Hobbies

@ Calvin'sHobbies Vous avez une question de règles que je me posais généralement, mais qui pourrait entrer en jeu ici: si une solution est implémentée en tant que fonction, cela implique-t-il que la fonction peut être appelée plus d'une fois en une seule fois? Par exemple, s'il utilisait une variable globale qui n'est initialisée correctement qu'au premier appel, serait-ce ... faux?
Reto Koradi

@Retro Je dirais que oui, c'est faux. La fonction doit fonctionner un certain nombre de fois sans la réinterpréter.
Calvin's Hobbies

1

Clojure - 66 octets

Notez qu'il ([] (()) ([] []) [()] [([[] []] [] []) ([] [])])s'agit d'un formulaire Clojure valide. Donc:

#(letfn[(g[x](apply(if(list? x)+ *)(map g x)))](g(read-string %)))
  • Il s'agit d'une fonction anonyme qui prend une chaîne, la lit et la donne g.
  • La gfonction locale s'applique +ou *au résultat de l'invocation de gsur des sous-éléments de ses arguments.
  • Le cas de base de la récursivité est un peu subtil: il est atteint lorsqu'il est xdans une séquence vide; (map g x)renvoie nilet applyrenvoie la valeur neutre de l'opération.

0

JavaScript (ES6), 116 octets

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),[[]])
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.