Setzen Sie einen Ausdruck in Klammern

20

Kürzlich habe ich eine neue Sprache geschrieben , um die Reihenfolge der Operationen nicht zu ändern. Ich setze einfach die einzelnen Ausdrücke in Klammern, um dies vollständig zu vermeiden.

Da sich die Klammern bei den Zeichencodes 40-41 befinden, muss Ihr Code so kurz wie möglich sein.


Beispiele

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)

Regeln

Die einzigen Operationen, die Sie ausführen müssen, sind: *(Multiplikation), /(Division), +(Addition) und -(Subtraktion).

  • Die Reihenfolge der Operationen ist:
    • Klammer
    • Multiplikation, Division
    • Addition, Subtraktion
  • Sie sollten es vorziehen, von links nach rechts zu gehen
  • Die eingegebenen Zahlen sind immer positive ganze Zahlen (siehe Boni)

Boni

-20% bei Negation:

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

-5%, wenn Sie Leerzeichen innerhalb der Eingabe zulassen:

3  + 4
(3+4)

-10%, wenn Sie Dezimalstellen in der Eingabe verarbeiten können:

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

500 Kopfgeld: Wenn Sie es schaffen, eine Antwort in Unbenannt / Blöcke zu schreiben

Downgoat
quelle
25
"Da Klammern die Zeichencodes 40-41 haben, muss Ihr Code so kurz wie möglich sein." OK, jetzt bist du einfach nur lächerlich. ; P
ETHproductions
3
Und das ist einfacher als Präfixnotation (polnisch) weil?
wizzwizz4
3
Möglicherweise doppelt .
Fehler
8
@flawr Ich habe das gesehen, aber es ist sehr anders, weil Sie bei dieser Frage alle Möglichkeiten haben, einen Ausdruck in Klammern zu setzen. Hier muss die Reihenfolge der Operationen berücksichtigt werden, die meiner Meinung nach einen signifikanten Unterschied darstellt, da Code für diese Herausforderung nicht einfach modifiziert werden kann
Downgoat
3
Wichtiger Testfall: 1+2+3+4(welche bestimmten Lösungen könnten in Klammern stehen ((1+2)+(3+4)))
Martin Ender

Antworten:

2

Python 153 * 0,9 = 137,7 Bytes

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

Dieses Programm verarbeitet die Dezimaleingabe.

Die zweite Zeile beginnt mit einem Leerzeichen, die zweite mit einem Tabulator, die dritte mit zwei Tabulatoren und die dritte mit einem Leerzeichen. Dies sparte ein Byte. Hier ist ein 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.

Hier ist ein Programm, das ich zum Testen verwendet habe: (Speichern Sie das Programm oben als 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!"

Stellen Sie sicher, dass Ihr Terminal den \033[38;5;<COL>mEscape-Code für Farben verwendet.

Loovjo
quelle
* viertens mit einem Leerzeichen?
Element118
1
Dieses Programm funktioniert nicht prefer to go left-right. Probieren Sie den Testfall 3 im OP aus, Ihr Ergebnis ist nicht korrekt. Dies kann beispielsweise bei Ganzzahlarithmetik ein echtes Problem sein ((2*(3/4))+3)(((2*3)/4)+3)
:!
1
@ user12365 Ohne ganzzahlige Arithmetik (in C oder C ++ zum Beispiel) 3/4 == 0, also ist ((2 * (3/4)) + 3) 3, während (((2 * 3) / 4) + 3) ist 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]

Da die beiden anderen Antworten derzeit beide falsch sind, werde ich meine posten. Es ist eine Variation des Ausdrucksparsers, den ich hier und hier und woanders verwendet habe. Hier finden Sie genauere Erklärungen zu den Algorithmen.

Es ist ziemlich sperrig, aber es sollte funktionieren.

Testschnipsel

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
quelle
1

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

Ich verwende die ast-Bibliothek (Abstract Syntax Trees) und ein Homebrew-String-Ersetzungsdiktat. Das Ersetzen der Saiten kostet viel, aber der Bonus hilft dabei, die Punktzahl etwas niedrig zu halten. Vielleicht kann (das Saitenersatzteil) weiter Golf gespielt werden.

Beachten Sie, dass diese Lösung jeder Zahl einen zusätzlichen Satz von Klammern hinzufügt, aber ich denke, dass dies dem Sinn der Frage entspricht

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

Testsuite:

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)

Ausgabe der Testsuite:

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))
wie auch immer
quelle
Fehlt import astin Ihrem Code
edc65
Und das ist nicht der richtige Weg, um einen Prozentbonus zu erhalten. Wenn Sie einen Rabatt von 50% und einen weiteren von 50% erhalten, zahlen Sie keine 0. Ihre Punktzahl sollte 157,32 betragen (etwas mehr, nachdem Sie die Importzeile hinzugefügt haben). Das ist eine gute Punktzahl - ich stimme zu, wenn Sie das Update machen
edc65
Guter Punkt. Import hinzugefügt. Jetzt 241 Zeichen. Nicht sicher, wie man den Bonus berechnet. Wenn ich Ihren Kommentar richtig verstehe, ist die Reihenfolge, in der der Bonus abgezogen wird, von Bedeutung ...
bis zum
Der Bonus wird nicht abgezogen (es ist eine Multiplikation) und die Reihenfolge spielt keine Rolle. 241 * (1-20%) * (1-5%) * (1-10%) => 241 * 0,8 * 0,95 * 0,9 => 164,84
edc65
@ edc65 Ah. Recht. Dachte nicht gerade. Vielen Dank.
Am