Lösen Sie einen mathematischen Ausdruck von abwechselnden Seiten

9

Erstellen Sie ein Programm, das einen mathematischen Ausdruck unter Verwendung der Elemente von abwechselnden Seiten des Ausdrucks löst. Anstatt von links nach rechts zu lesen, lesen Sie das erste Zeichen, dann das letzte, dann das zweite, dann das vorletzte usw. Dies gibt Ihnen einen neuen Ausdruck, den Sie auswerten und ausgeben müssen.

a*b/c+d-e
135798642  <-- Order you read the expression in
ae*-bd/+c  <-- Order of operation. 

Beispiel:

1*3/2+4-5
15*-34/+2 = -255

Wenn der Ausdruck nicht «funktioniert», 1muss a an den erforderlichen Stellen eingefügt werden, damit er funktioniert.

Einige Beispiele werden es wahrscheinlich besser veranschaulichen:

Input: 1+1+1+1+1
Result: 23     // Because 1+1+1+1+1 -> 11++11++1 -> 23

Input: 1+2-3+12-5
Result: -19    // Because 1+2-3+12-5 -> 15+-22-13+ -> 15+-22-13+1 -> -19
               //                                 |
               //                                 Not valid expression

Input: 2*2*2*2*2
Result: 968    // Because 2*2*2*2*2 -> 22**22**2 -> 22*1*22*1*2 -> 968
               //                        ||  ||
               //                        Not valid, 1 must be inserted

Input: 17/2
Output: 127    // Because 17/2 = 127/ -> 127/1 -> 127

Die Operatoren, die unterstützt werden müssen, sind + - * /. Es wird keine Klammern geben. Es werden normale mathematische Regeln und "Syntax" verwendet, was beispielsweise **keine Exponentiation bedeutet. a++++1ist äquivalent zu a+1(dh MATLAB-Stil, nicht C ++).

Im Zweifelsfall sind einige gültige Operationen:

-a
+a
a++b
a+-b
a*-b
a*+b
a*++b
a/b
a/-b
a/+b
-a/--b

Alle folgenden sind nicht gültig. Es wird gezeigt, durch was sie ersetzt werden sollten:

a+      | a+1
a-      | a-1
a++++   | a++++1   (This is equivalent to a+1)
a*+++   | a*+++1   (This is equivalent to a*1)
a**b    | a*1*b
a*/b    | a*1/b
a/*b    | a/1*b
a*      | a*1
*a      | 1*a
***a    | 1*1*1*a

Regeln:

  • Der Code kann eine Funktion oder ein vollständiges Programm sein
  • Die Eingabe kann STDIN oder Funktionsargument sein
  • Die Eingabe muss ein gültiger mathematischer Ausdruck ohne Anführungszeichen sein ''oder"" .
  • Die Ausgabe sollte die Antwort auf den neuen Ausdruck sein, als Ganzzahl, Dezimalzahl oder vereinfachter Bruch.
  • Es müssen mindestens drei Stellen nach dem Komma unterstützt werden. Also 1/3 = 0.333nicht 0.33. 0.333333333ist akzeptiert.
  • ans = ... ist akzeptiert.
  • Führende und nachfolgende Zeilenumbrüche und Leerzeichen werden akzeptiert.
  • Die Eingabe besteht nur aus ganzen Zahlen
  • Die Division durch Null kann zu einem Fehler, NaN, Inf usw. führen. Die Ausgabe einer Zahl wird nicht akzeptiert.

Wie immer gewinnt der kürzeste Code in Bytes. Ein Gewinner wird eine Woche nach dem Tag ausgewählt, an dem die Herausforderung veröffentlicht wurde. Später veröffentlichte Antworten können immer noch gewinnen, wenn sie kürzer als der aktuelle Anführer sind.

Stewie Griffin
quelle
Gibt es eine maximale Länge für die Eingabezeichenfolge oder die Anzahl der eingegebenen Operatoren / Ganzzahlen? Muss ich auch Mathe bis zu unterstützen 2^64, und sollte es Fehler oder Wrap geben, wenn Sie darüber nachdenken?
Katze
"Die Ausgabe sollte die Antwort sein [ ... ] vereinfachter Bruch ..." Kann ich also einfach zurückkehren, 0/0wenn der Ausdruck zu einer ganzzahligen Division oder einem Modulo durch Null wird?
Katze
2
Wenn die Antwort eine Division durch Null ergibt, x/0ist dies eine gültige Ausgabe. Solange keine falsche Antwort ausgegeben wird, ist dies in Ordnung. Fehler und "Keine Zahl" ist per Definition korrekt, und Unendlichkeit ist "richtig genug"
Stewie Griffin
Nur um sicher zu gehen - eval kann verwendet werden, oder?
Orlp
Ja, eval ist ok.
Stewie Griffin

Antworten:

3

Perl, 108 100 Bytes

$_="";while(@F){$_.=shift@F;$_.=pop@F}s@(\*|/)\1+@\1@g;s@^[*/]@1$&@;s@\D$@$&1@;s@\D@$&@g;$_=eval

Der Code ist 96 Byte plus 4 für das Befehlszeilenargument -pF//, wobei

  • -pEinsätze while (<>) { .. } continue { print }und
  • -F//teilt den Eingang und fügt ihn ein @F.

Beachten Sie, dass die Eingabe keinen nachgestellten Zeilenumbruch haben sollte. Verwenden Sie daher /bin/echo -n 'formula' | perl ...

Weniger Golf:

$_='';              # reset $_
while(@F) {         # reorder input
   $_.=shift @F;    # take first element off of @_
   $_.=pop @F       # idem for last; if @F is empty, undef is appended
}

s@(\*|/)\1+@\1@g;   # replace 2 or more '*' or '/' with just one: *1 and /1 = nop
s@^[*/]@1$&@;       # if expression starts with * or / prepend a 1
s@\D$@$&1@;         # if expression doesn't end with a number, append 1
s@\D@$& @g;         # eval doesn't like '++1': add spaces after operators
$_ = eval           # set $_ to 3v1l, so the `-p` will print the new value

Testen

Fügen Sie das Obige in eine aufgerufene Datei 114.plund das folgende Testskript in eine Datei daneben ein:

%test = (
    '1+1+1+1+1' =>   23,
    '1*3/2+4-5' => -255,
    '1+2-3+12-5'=>  -19,
    '2*2*2*2*2' =>  968,
    '17/2'      =>  127,
    '--/-1-2-'  =>   -2,
    '**2*'      =>    2,
    '++1++'     =>    1,
    '/2/'       =>  0.5,
    '10/'       =>   '',
);

printf "%-20s -> %5s: %5s\n", $_, $test{$_}, `/bin/echo -n '$_' | perl -pF// 114.pl`
for keys %test;

Beim Ausführen werden folgende Ausgaben ausgeführt:

++1++                ->     1:     1
**2*                 ->     2:     2
17/2                 ->   127:   127
10/                  ->      :
1+1+1+1+1            ->    23:    23
1*3/2+4-5            ->  -255:  -255
2*2*2*2*2            ->   968:   968
1+2-3+12-5           ->   -19:   -19
--/-1-2-             ->    -2:    -2
/2/                  ->   0.5:   0.5

Beachten Sie, 1/0dass dies einen Fehler durch Division durch Null verursacht: die evalAusgaben undef, die durch die leere Zeichenfolge dargestellt werden.

Kenney
quelle
Noch ein paar Testfälle! Ich werde sie benutzen
edc65
3

JavaScript ES6, 105 106

Bearbeiten Gespeichert 1 Byte thx @Kenney

t=>eval("for(t=[...t],p=o='';c=t.reverse().pop();p=c)o+=p<'0'?(c=='/'|c<'+'||' ')+c:c;eval(p<'0'?o+1:o)")

// Less golfed
t=>{
  for(t = [...t], p = o = '';
      c = t.reverse().pop();
      p = c)
    o += p<'0' 
     ? (c=='/' | c=='*' || ' ')+c  // '1' or ' '
     : c;
  return eval(p<'0' ? o+1 : o)
}

Testschnipsel

f=t=>eval("for(t=[...t],p=o='';c=t.reverse().pop();p=c)o+=p<'0'?(c=='/'|c<'+'||' ')+c:c;eval(p<'0'?o+1:o)")

console.log=x=>O.innerHTML+=x+'\n'

function test() { console.log(I.value + ' -> '+f(I.value)) }

;['1+1+1+1+1', '1*3/2+4-5', '1+2-3+12-5', '2*2*2*2*2',
  '17/2', '--/-1-2-', '**2*', '++1++', '/2/', '10/' ]
.forEach(t=>console.log(t+' -> '+f(t)))
Your test <input id=I><button onclick="test()">-></button>
<pre id=O></pre>

edc65
quelle
Sparte dir ein Byte : p < '0' ? ( c=='/' | c<'+' || ' ' )+c : c ;.
Kenney