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.