Entre parenthèses une expression

20

Récemment, j'ai écrit un nouveau langage , pour éviter d'avoir à gérer l' ordre des opérations , j'ai simplement mis correctement entre parenthèses chaque expression pour éviter cela complètement.

Parce que les parenthèses sont aux codes de caractères 40-41, votre code devra être aussi court que possible.


Exemples

1+2*3
(1+(2*3))

2*(3+4)
(2*(3+4))

2*3/4+3
(((2*3)/4)+3)

342*32/8
((342*32)/8)

Règles

Les seules opérations que vous devrez gérer sont: *(multiplication), /(division), +(addition) et -(soustraction).

  • L' ordre des opérations est le suivant:
    • Parenthèse
    • Multiplication, division
    • Adition, soustraction
  • Vous devriez préférer aller de gauche à droite
  • Les nombres entrés seront toujours des entiers positifs (voir bonus)

Bonus

-20% si vous gérez la négation:

3+-5
(3+(-5))

-5% si vous autorisez le placement d'espaces à l'intérieur de l'entrée:

3  + 4
(3+4)

-10% si vous pouvez gérer les décimales en entrée:

1+.12
(1+.12)
1+0.21/3
(1+(0.21/3))

Bounty 500: si vous parvenez à écrire une réponse dans Sans nom / Blocs

Downgoat
la source
25
"Parce que les parenthèses sont aux codes de caractères 40-41, votre code devra être aussi court que possible." OK, maintenant tu es juste ridicule. ; P
ETHproductions
3
Et c'est plus facile que la notation préfixe (polonaise) parce que?
wizzwizz4
3
Possible double .
flawr
8
@flawr Je l'ai vu, mais c'est très différent dans le fait que cette question vous fait sortir toutes les manières entre parenthèses une expression. Ici, vous devez prendre en compte l'ordre des opérations, ce qui, je pense, est une différence significative car le code ne peut pas être modifié de manière triviale pour ce défi
Downgoat
3
Cas de test important: 1+2+3+4(dont certaines solutions pourraient être entre parenthèses ((1+2)+(3+4)))
Martin Ender

Réponses:

2

Python, 153 * 0,9 = 137,7 octets

def p(e):
 for o in"+-*/":
    for i,c in enumerate(e):
        if(c==o)*(0==sum([(d=="(")-(d==")")for d in e[:i]])):return"("+p(e[:i])+o+p(e[i+1:])+")"
 return e

Ce programme gère la saisie décimale.

La deuxième ligne commence par un espace, la seconde commence par une tabulation, la troisième avec deux tabulations et la troisième avec un espace. Cela a sauvé un octet. Voici un hexdump ( xxdpp):

0000000: 6465 6620 7028 6529 3a0a 2066 6f72 206f  def p(e):. for o
0000010: 2069 6e22 2b2d 2a2f 223a 0a09 666f 7220   in"+-*/":..for 
0000020: 692c 6320 696e 2065 6e75 6d65 7261 7465  i,c in enumerate
0000030: 2865 293a 0a09 0969 6628 633d 3d6f 292a  (e):...if(c==o)*
0000040: 2830 3d3d 7375 6d28 5b28 643d 3d22 2822  (0==sum([(d=="("
0000050: 292d 2864 3d3d 2229 2229 666f 7220 6420  )-(d==")")for d 
0000060: 696e 2065 5b3a 695d 5d29 293a 7265 7475  in e[:i]])):retu
0000070: 726e 2228 222b 7028 655b 3a69 5d29 2b6f  rn"("+p(e[:i])+o
0000080: 2b70 2865 5b69 2b31 3a5d 292b 2229 220a  +p(e[i+1:])+")".
0000090: 2072 6574 7572 6e20 650a                  return e.

Voici un programme que j'ai utilisé pour les tests: (Enregistrez le programme ci-dessus sous paren.py)

import paren

cases = {
        "2+3*4": "(2+(3*4))", 
        "(2+3)*4": "((2+3)*4)", 
        "1+2+3+4": "(1+(2+(3+4)))", 
        "3/2+5": "((3/2)+5)", 
        "1+2-3": "(1+(2-3))", 
        "2-1+2": "((2-1)+2)",
        "3+-5": "(3+(-5))",
        "1+.12": "(1+.12)",
        "1+0.21/3": "(1+(0.21/3))",
}


for num, case in enumerate(cases):
    print "\n\n\033[1m\033[38;5;14mCase #%d: %s" % (num + 1, case)
    result = paren.p(case)
    print "\033[38;5;4mParenthesize returned: %s" % (result)
    solution = cases[case]
    if result == solution:
        print "\033[38;5;76mCorrect!"
    else:
        print "\033[38;5;9mNot correct!"

Assurez-vous que votre terminal utilise le \033[38;5;<COL>mcode d'échappement pour les couleurs.

Loovjo
la source
* quatrième avec un espace?
Element118
1
Ce programme ne fonctionne pas prefer to go left-right. Essayez le cas de test 3 dans l'OP, votre résultat n'est pas correct. Cela peut être un vrai problème par exemple avec l'arithmétique entière ((2*(3/4))+3)(((2*3)/4)+3)
:!
1
@ user12365 Ne pas utiliser l' arithmétique entière (en C ou C ++ par exemple) 3/4 == 0, donc ((2 * (3/4)) + 3) vaut 3, tandis que (((2 * 3) / 4) + 3) est le 4
edc65
3

JavaScript (ES6) 179 (263-20% -5% -10%)

(x,W=[],Q=['('],z=1,w=v='',h=p=>'*/+-))('.indexOf(p)|1,C=n=>{for(;h(q=Q.pop())<=h(n);)W[0]=`(${W[1]+q+W.shift()})`;z&&Q.push(q,n)})=>(x+')').replace(/[\d.]+|\S/g,t=>t>'('?t>')'?~h(t)?z?(w+='('+t,v+=')'):C(t,z=1):W=[w+t+v,...W,z=w=v='']:C(t,z=0):z=Q.push(t))&&W[0]

Comme les deux autres réponses sont actuellement erronées, je posterai la mienne. C'est une variante de l'analyseur d'expression que j'ai utilisé ici et ici et ailleurs. Regardez là pour des explications plus détaillées sur l'algorithme.

C'est assez volumineux mais ça devrait marcher.

Extrait de test

f=(x,W=[],Q=['('],z=1,w=v='',h=p=>'*/+-))('.indexOf(p)|1,C=n=>{for(;h(q=Q.pop())<=h(n);)W[0]=`(${W[1]+q+W.shift()})`;z&&Q.push(q,n)})=>(x+')').replace(/[\d.]+|\S/g,t=>t>'('?t>')'?~h(t)?z?(w+='('+t,v+=')'):C(t,z=1):W=[w+t+v,...W,z=w=v='']:C(t,z=0):z=Q.push(t))&&W[0]

// More readable
x=(x,W=[],Q=['('],z=1,w=v='',
  h=p=>'*/+-))('.indexOf(p)|1,
  C=n=>{
    for(;h(q=Q.pop())<=h(n);)W[0]=`(${W[1]+q+W.shift()})`;
    z&&Q.push(q,n)
  }
)=>(
  (x+')')
  .replace(/[\d.]+|\S/g,t=> 
       t>'('    
       ?t>')'
       ?~h(t)
       ?z
       ?(w+='('+t,v+=')')
       :C(t,z=1)
       :W=[w+t+v,...W,z=w=v=''] // overfill W to save 2 chars ()
       :C(t,z=0)
       :z=Q.push(t)
  ),
  W[0]
)

console.log=(...x)=>O.textContent+=x.join` `+'\n'

// TEST
;[
  ['1+2*3','(1+(2*3))'],['2*(3+4)','(2*(3+4))'],['2*3/4+3','(((2*3)/4)+3)'],['342*32/8','((342*32)/8)'],
  ['3+-5','(3+(-5))'],['-3+-4*7','((-3)+((-4)*7))'], // bonus 20%
  ['3  + 4','(3+4)'], // bonus 5%
  ['1+.12','(1+.12)'],['1+0.21/3','(1+(0.21/3))'] // bonus 10%
].forEach(t=>{var k=t[1],i=t[0],r=f(i); console.log(i+' : '+r+(r==k? ' OK':' Fail expecting '+k))})
<pre id=O></pre>

edc65
la source
1

Python, 241 * 0,8 * 0,95 * 0,9 = 164,84 caractères

J'utilise la bibliothèque ast (Abstract Syntax Trees) et un dict de remplacement de chaîne homebrew. Le remplacement de la chaîne coûte cher, mais le bonus aide à maintenir le score un peu bas. Peut-être (la pièce de rechange de la chaîne) peut-il être joué plus loin.

Notez que cette solution ajoute un jeu supplémentaire de parenthèses autour de chaque nombre, mais je pense que cela est dans l'esprit de la question

import ast;def p(e):
 r,s={"Module([":"",")])":"","Expr(":"","BinOp":"","Num":"",", Add(), ":"+",", Sub(), ":"-",", Div(), ":"/",", Mult(), ":"*"},ast.dump(ast.parse(e),annotate_fields=False)
 for f,t in r.iteritems():s=s.replace(f,t)
 return s

Suite de tests:

cases = {
    "2+3*4", 
    "(2+3)*4", 
    "1+2+3+4", 
    "3/2+5", 
    "1+2-3", 
    "2-1+2",
    "3+-5",
    "1+.12",
    "1+0.21/3"
}

for num,case in enumerate(cases):
    result = p(case)
    print "Case {}: {:<16} evaluates to: {}".format(num+1,case,result)

Sortie de la suite de tests:

Case 1: 3+-5             evaluates to: ((3)+(-5))
Case 2: 3/2+5            evaluates to: (((3)/(2))+(5))
Case 3: 2+3*4            evaluates to: ((2)+((3)*(4)))
Case 4: 1+2+3+4          evaluates to: ((((1)+(2))+(3))+(4))
Case 5: 1+0.21/3         evaluates to: ((1)+((0.21)/(3)))
Case 6: (2+3)*4          evaluates to: (((2)+(3))*(4))
Case 7: 2-1+2            evaluates to: (((2)-(1))+(2))
Case 8: 1+.12            evaluates to: ((1)+(0.12))
Case 9: 1+2-3            evaluates to: (((1)+(2))-(3))
toujours
la source
Manquant import astdans votre code
edc65
Et ce n'est pas la bonne façon de compenser le bonus en pourcentage. Si vous obtenez une remise de 50% et en plus de 50%, vous ne payez pas 0. Votre score devrait être de 157,32 (quelque chose de plus après l'ajout de la ligne d'importation). C'est un bon score - je voterai si vous apportez le correctif
edc65
Bon point. Ajout de l'importation. 241 caractères maintenant. Je ne sais pas comment calculer le bonus. Si je comprends bien votre commentaire, l'ordre dans lequel le bonus est soustrait compte ...
agtoever
Le bonus n'est pas soustrait (c'est une multiplication) et l'ordre n'a pas d'importance. 241 * (1-20%) * (1-5%) * (1-10%) => 241 * 0,8 * 0,95 * 0,9 =>
164,84
@ edc65 Ah. Droite. Ne pensait pas bien. Merci.
agtoever