Tra parentesi un'espressione


20

Recentemente ho scritto una nuova lingua , per evitare di dover gestire l' ordine delle operazioni , ho semplicemente parentesi ogni espressione correttamente per evitarlo del tutto.

Poiché le parentesi si trovano ai codici char 40-41, il codice dovrà essere il più breve possibile.


Esempi

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)

Regole

Le uniche operazioni che dovrai gestire sono: *(moltiplicazione), /(divisione), +(addizione) e -(sottrazione).

  • L' ordine delle operazioni è:
    • Parentesi
    • Moltiplicazione, divisione
    • Adizione, sottrazione
  • Dovresti preferire andare a sinistra a destra
  • I numeri di input saranno sempre numeri interi positivi (vedi bonus)

bonus

-20% se gestisci la negazione:

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

-5% se si consente di posizionare spazi all'interno dell'input:

3  + 4
(3+4)

-10% se riesci a gestire i decimali nell'input:

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

500 bounty: se riesci a scrivere una risposta in Senza nome / Blocchi


25
"Dato che le parentesi sono nei codici char 40-41, il tuo codice dovrà essere il più breve possibile." OK, ora sei semplicemente ridicolo. ; P
— Produzioni ETH il

3
E questo è più facile della notazione del prefisso (polacco) perché?
— wizzwizz4,

3
Possibile duplicato .
— flawr

8
@flawr L'ho visto, ma è molto diverso dal fatto che quella domanda ti abbia prodotto in tutti i modi tra parentesi un'espressione. Qui devi prendere in considerazione l'ordine delle operazioni che penso sia una differenza significativa poiché il codice non può essere banalmente modificato per questa sfida
— Downgoat,

3
Caso di test importante: 1+2+3+4(che alcune soluzioni potrebbero essere tra parentesi ((1+2)+(3+4)))
— Martin Ender,

Risposte:


2

Python, 153 * 0.9 = 137.7 byte

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

Questo programma gestisce l'input decimale.

La seconda riga inizia con uno spazio, la seconda inizia con una scheda, la terza con due schede e la terza con uno spazio. Questo ha salvato un byte. Ecco 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.

Ecco un programma che ho usato per i test: (Salva il programma sopra come 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!"

Assicurati che il tuo terminale usi il \033[38;5;<COL>mcodice di escape per i colori.


* quarto con uno spazio?
— Element118,

1
Questo programma no prefer to go left-right. Prova il test case 3 nell'OP, il tuo risultato non è corretto. Questo può essere un vero problema, ad esempio con l'aritmetica dei numeri interi ((2*(3/4))+3)(((2*3)/4)+3)
— :!

1
@ user12365 Non usare l' aritmetica intera (ad esempio in C o C ++) 3/4 == 0, quindi ((2 * (3/4)) + 3) è 3, mentre (((2 * 3) / 4) + 3) è 4
— edc65, il

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]

Poiché le altre due risposte sono attualmente entrambe sbagliate, posterò la mia. Si tratta di una variante del parser espressione che ho usato qui e qui e da qualche altra parte. Guarda lì per spiegazioni più dettagliate sugli algoritmi.

È piuttosto ingombrante ma dovrebbe funzionare.

Test snippet

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>


1

Python, 241 * 0,8 * 0,95 * 0,9 = 164,84 caratteri

Sto usando la libreria ast (Abstract Syntax Trees) e un dict di sostituzione di stringa homebrew. La sostituzione della stringa costa molto, ma il bonus aiuta a mantenere il punteggio un po 'basso. Forse (la parte di sostituzione della stringa) può essere ulteriormente golfato.

Nota che questa soluzione aggiunge un ulteriore set di parentesi attorno a ciascun numero, ma penso che sia nello spirito della domanda

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 di test:

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)

Output della suite di test:

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

Manca il import asttuo codice
— edc65, il

E questo non è il modo giusto di rimborsare il bonus percentuale. Se ricevi uno sconto del 50% e, in aggiunta, un altro sconto del 50%, non stai pagando 0. Il tuo punteggio dovrebbe essere 157.32 (qualcosa in più dopo aver aggiunto la riga di importazione). Questo è un buon punteggio - voterò se farai la correzione
— edc65 il

Buon punto. Aggiunta l'importazione. 241 caratteri ora. Non sono sicuro di come calcolare il bonus. Se capisco correttamente il tuo commento, l'ordine in cui viene sottratto il bonus è importante ...
— agtoever

Il bonus non viene sottratto (è una moltiplicazione) e l'ordine non ha importanza. 241 * (1-20%) * (1-5%) * (1-10%) => 241 * 0.8 * 0.95 * 0.9 => 164.84
— edc65

@ edc65 Ah. Giusto. Non pensavo bene. Grazie.
— agtoever il
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.