Ich sehe deine BIDMAS und ziehe dir ein BADMIS auf

21

Ich sehe deine BIDMAS und ziehe dir ein BADMIS auf

Herausforderung

Wenn eine Reihe von Zahlen mit Operatoren dazwischen gegeben ist: "5 + 4 * 9/3 - 8", geben Sie alle möglichen Ergebnisse des Ausdrucks für jede Permutation in der Reihenfolge der Grundoperationen zurück: [/, *, +, -].

Regeln

  • Standardlücken verboten
  • I / O
    • Die Eingabe muss mit Infix-Operationen bestellt werden, dies ist jedoch am einfachsten (Zeichenfolge oder Array).
    • Sie müssen keine unären Operatoren unterstützen (z. B. "-3 * 8 / +2")
    • Ganzzahlen können durch Gleitkommazahlen für Sprachen ersetzt werden, die den Typ implizit analysieren (z. B. 45 ⟶ 45.0).
    • Die Ausgabe muss alle möglichen Ergebnisse des Ausdrucks enthalten, kein bestimmtes Format oder keine bestimmte Reihenfolge
  • Alle Eingaben sind gültig (z. B. muss nicht mit "7/3 + *" umgegangen werden). Dies bedeutet auch, dass Sie niemals durch Null teilen müssen.
  • Operatoren sind alle linksassoziativ, so dass "20/4/2" = "(20/4) / 2"
  • Dies ist Code Golf, so dass die geringste Anzahl von Bytes gewinnt

Testfälle (mit Erläuterung)

  • "2 + 3 * 4" = [14, 20]
    • 2 + (3 * 4) ≤ 2 + (12) ≤ 14
    • (2 + 3) * 4 ≤ (5) * 4 ≤ 20
  • "18/3 * 2 - 1" = [11, 2, 6]
    • ((18/3) * 2) - 1 ≤ ((6) * 2) - 1 ≤ (12) - 1 ≤ 11
    • (18/3) * (2 - 1) ≤ (6) * (1) ≤ 6
    • (18 / (3 * 2)) - 1 ⟶ (18 / (6)) - 1 ⟶ (3) - 1 ⟶ 2
    • 18 / (3 * (2 - 1)) ≤ 18 / (3 * (1)) ≤ 6
    • 18 / ((3 * 2) - 1) ≤ 18/5 ≤ 3.6

Testfälle (ohne Erklärung)

  • "45/8 + 19/45 * 3" = [6.891666666666667, 18.1416666666666, 0.11111111111111113, 0.01234567901234568, 0.01234567901234568, 5.765740740740741]
  • "2 + 6 * 7 * 2 + 6/4" = [112 196 23 87.5]
Freddie R
quelle
2
Schöne erste Herausforderung übrigens.
Shaggy
Eng verwandt
Arnauld
Vorgeschlagener Testfall 2 - 3 + 4=>[-5, 3]
Jo King
Vorgeschlagener Testfall: 2*3-6+2-9/6*8+5/2-924 eindeutige Ergebnisse.
Arnauld,

Antworten:

3

C # (Visual C # Interactive Compiler) , 285 Byte

x=>{int c=0,j,t=1,i;for(;c++<25;t=c){var r="*+-/".ToList();for(i=j=1;j++<4;t=t/j+1)(r[j-1],r[t%j])=(r[t%j],r[j-1]);float k(float z,int p=4){char d;int l;float m;return i<x.Count&&(l=r.IndexOf(d=x[i][0]))<p?k((m=k(x[(i+=2)-1],l))*0+d<43?z*m:d<44?z+m:d<46?z-m:z/m,p):z;}Print(k(x[0]));}}

Probieren Sie es online!

x=>{                                          //Lambda taking in a List<dynamic>
  int c=0,j,t=1,i;                            //A bunch of delcarations jammed together to save bytes
  for(;c++<25;t=c){                           //Loop 24 times (amount of permutations a set of length 4 can have)
    var r="/+*-".ToList();                    //Initialize r as list of operators
    for(i=j=1;j++<4;t=t/j+1)                    //Create the Tth permutation, saving result in r, also reset i to 1
      (r[j-1],r[t%j])=(r[t%j],r[j-1]);
    float k(float z,int p=4) {                //Define local function 'k', with z as current value accumalated and p as current precedence
      char d;int l;float m;                   //Some helper variables
      return i<x.Count                        //If this is not the last number
        &&(l=r.IndexOf(d=x[i][0]))<p?         //  And the current operator's precedence is higher than the current precedence
      k(                                      //  Recursive call with the accumalative value as
        (m=k(x[(i+=2)-1],l))                  //    Another recursive call with the next number following the current operator as seed value,
                                              //    And the next operator's precedence as the precedence value, and store that in variable 'm'
        *0+d<43?z*m:d<44?z+m:d<46?z-m:z/m,    //    And doing the appropriate operation to m and current value ('z')
        p)                                    //  Passing in the current precedence
    :z;                                       //Else just return the current number
    }
    Print(k(x[0]));                           //Print the result of calling k with the first number as starting value
  }
}
Verkörperung der Ignoranz
quelle
Ich habe es behoben, damit Sie keine Duplikate auslassen müssen, da es, wie bereits erwähnt, kein grundlegender Teil des Problems ist.
Freddie R
1
@Arnauld Wurde auf Kosten von 4 Byte behoben, weil mein Permutationsalgorithmus etwas falsch war
Verkörperung der Ignoranz
3

JavaScript (Node.js) , 132 Byte

a=>(w=[],F=(b,a)=>b?[...b].map(q=>F(b.replace(q,""),a.replace(eval(`/[\\d.-]+( \\${q} [\\d.-]+)+/g`),eval))):w.push(a))("+-*/",a)&&w

Probieren Sie es online!

Dies ermöglicht doppelte Ausgaben.

JavaScript (Node.js) , 165 161 155 153 152 137 Bytes

a=>Object.keys((F=(b,a)=>b?[...b].map(q=>F(b.replace(q,""),a.replace(eval(`/[\\d.-]+( \\${q} [\\d.-]+)+/g`),eval))):F[a]=1)("+-*/",a)&&F)

Probieren Sie es online!

Nimmt eine Zeichenfolge mit Leerzeichen zwischen Operatoren und Zahlen.

a=>                                             // Main function:
 Object.keys(                                   //  Return the keys of the -
  (
   F=(                                          //   Index container (helper function):
    b,                                          //    Operators
    a                                           //    The expression
   )=>
    b                                           //    If there are operators left:
    ?[...b].map(                                //     For each operator:
     q=>
      F(                                        //      Recur the helper function - 
       b.replace(q,""),                         //       With the operator deleted
       a.replace(                               //       And all -
        eval(`/[\\d.-]+( \\${q} [\\d.-]+)+/g`), //        Expressions using the operator
        eval                                    //        Replaced with the evaluated result
       )
      )
    )
    :F[a]=1                                     //     Otherwise - set the result flag.
  )(
   "+-*/",                                      //    Starting with the four operators
   a                                            //    And the expression
  )
  &&F
 )
Shieru Asakoto
quelle
@JoKing Implementiert das Update, das ich zuvor angegeben habe, sollte [3, -5]jetzt ausgegeben werden .
Shieru Asakoto
2

Perl 6 , 92 90 88 Bytes

{map {[o](@_)($_)},<* / + ->>>.&{$^a;&{S:g{[\-?<[\d.]>+]+%"$a "}=$/.EVAL}}.permutations}

Probieren Sie es online!

Nimmt eine Zeichenfolge mit einem Leerzeichen hinter Operatoren und gibt eine Reihe von Zahlen zurück. Dies funktioniert hauptsächlich, indem alle Instanzen von n op ndurch das ausgewertete Ergebnis für alle Permutationen der Operatoren ersetzt werden.

Erläuterung:

{                                                                                   }  # Anonymous code block
                    <* / + ->>>.&{                                    } # Map the operators to:
                                  $^a;&{                             }  # Functions that:
                                        S:g{                }      # Substitute all matches of:
                                            \-?<[\d.]>+]+        # Numbers
                                                         %$a     # Joined by the operator
                                                              =$/.EVAL   # With the match EVAL'd
 map {           },                                                    .permutations   # Map each of the permutations of these operators
      [o](@_)        # Join the functions
             ($_)    # And apply it to the input
Scherzen
quelle
Sie können das entfernen set, da die Bedingung zum Entfernen von Duplikaten entfernt wurde. Netter Code.
Freddie R
2

Python 3 , 108 Bytes

f=lambda e,s={*"+-*/"}:[str(eval(p.join(g)))for p in s for g in zip(*map(f,e.split(p),[s-{p}]*len(e)))]or[e]

Probieren Sie es online!

Die Funktion nimmt eine einzelne Zeichenfolge als Eingabe und gibt eine Liste möglicher Ergebnisse zurück.

Ungolfed

def get_all_eval_results(expr, operators={*"+-*/"}):
    results = []
    for operator in operators:
        remaining_operators = operators - {operator}

        # Split expression with the current operator and recursively evaluate each subexpression with remaining operators
        sub_expr_results = (get_all_eval_results(sub_expr, remaining_operators) for sub_expr in expr.split(operator))

        for result_group in zip(*sub_expr_results):   # Iterate over each group of subexpression evaluation outcomes
            expr_to_eval = operator.join(result_group)  # Join subexpression outcomes with current operator
            results.append(str(eval(expr_to_eval)))   # Evaluate and append outcome to result list of expr
    return results or [expr]  # If results is empty (no operators), return [expr]

Probieren Sie es online!

Joel
quelle
1

Gelee , 30 Bytes

œṡ⁹¹jṪḢƭ€jŒVɗßʋFL’$?
Ḋm2QŒ!烀

Probieren Sie es online!

Ein paar Links. Der zweite Link ist der Hauptlink und basiert auf einer Jelly-Liste von Gleitkommazahlen / Ganzzahlen, die mit den Operatoren als Zeichen durchsetzt sind. Dies ist eine abgeflachte Version der Art und Weise, wie Jelly seine Eingabe aufnimmt, wenn es als vollständiges Programm mit Befehlszeilenargumenten ausgeführt wird. Der Rückgabewert des Links ist eine Liste mit Listen einzelner Mitglieder, von denen jede einen möglichen Wert für den Ausdruck darstellt.

Erläuterung

Hilfslink

Nimmt eine Liste von Gleitkommazahlen / Ganzzahlen im Wechsel mit Operatoren (als Zeichen) als linkes Argument und einen Operator als Zeichen als rechtes Argument; Gibt die Eingabeliste zurück, nachdem die durch den entsprechenden Operator getrennten Zahlen von links nach rechts ausgewertet wurden.

œṡ⁹                  | Split once by the right argument (the operator currently being processed)
                   ? | If:
                  $  | - Following as a monad
                L    |   - Length
                 ’   |   - Decremented by 1
              ʋ      | Then, following as a dyad:
   ¹                 | - Identity function (used because of Jelly’s ordering of dyadic links at the start of a dyadic chain)
    j       ɗ        | - Join with the following as a dyad, using the original left and right arguments for this chain:
     ṪḢƭ€            |   - Tail of first item (popping from list) and head from second item (again popping from list); extracts the numbers that were either side of the operator, while removing them from the split list
         j           |   - Joined with the operator
          ŒV         |   - Evaluate as Python (rather than V because of Jelly’s handling of decimals with a leading zero)
            ß        | - Recursive call to this helper link (in case there are further of the same operator)
               F     | Else: Flatten

Hauptlink

Erstellt eine Liste von Gleitkommazahlen / Ganzzahlen im Wechsel mit Operatoren (als Zeichen)

Ḋ         | Remove first item (which will be a number)
 m2       | Every 2nd item, starting with the first (i.e. the operators)
   Q      | Uniquify
    Œ!    | Permutations
      烀 | For each permuted list of operators, reduce using the helper link and with the input list as the starting point
Nick Kennedy
quelle
1

Python 2 , 182 172 Bytes

import re
def f(s,P=set('+-/*')):
 S=[eval(s)]
 for p in P:
	t=s
	while p+' 'in t:t=re.sub(r'[-\d.]+ \%s [-\d.]+'%p,lambda m:`eval(m.group())`,t,1)
	S+=f(t,P-{p})
 return S

Probieren Sie es online!

Nimmt Eingaben mit als Gleitkommazahlen formatierten Ints entgegen (siehe "Ganzzahlen können durch Gleitkommazahlen für Sprachen ersetzt werden, die implizit den Typ analysieren").

Chas Brown
quelle
1

Julia 1,2 , 88 (82) Bytes

f(t)=get(t,(),[f.([t[1:i-1];t[i+1](t[i],t[i+2]);t[i+3:end]] for i=1:2:length(t)-2)...;])
julia> f([2, +, 3, *, 4])
2-element Array{Int64,1}:
 20
 14

julia> f([18, /, 3, *, 2, -, 1])
6-element Array{Float64,1}:
 11.0
  6.0
  2.0
  3.6
  6.0
  6.0

Nimmt ein Band in Form eines Vektors von Zahlen und Infixfunktionen, wertet jeden einzelnen Funktionsaufruf aus und übergibt jedes resultierende Band rekursiv an sich selbst, bis nur noch eine einzige Zahl übrig ist. Funktioniert get(t, (), ...)in Julia 1.0 leider nicht richtig, daher wird eine neuere Version benötigt.

Sechs Bytes können gespeichert werden, wenn eine Reihe verschachtelter Arrays als Ausgabe zulässig ist:

f(t)=get(t,(),f.([t[1:i-1];t[i+1](t[i],t[i+2]);t[i+3:end]] for i=1:2:length(t)-2))

Ausgabe:

julia> f([18, /, 3, *, 2, -, 1])
3-element Array{Array{Array{Float64,1},1},1}:
 [[11.0], [6.0]]
 [[2.0], [3.6]] 
 [[6.0], [6.0]] 
user3263164
quelle
0

Perl 5 ( -alp), 89 Bytes

my$x;map{$x.=$`.(eval$&.$1).$2.$"while/\d+[-+*\/](?=(\d+)(.*))/g}@F;$_=$x;/[-+*\/]/&&redo

TIO

oder eindeutige Werte, 99 Bytes

my%H;map{$H{$`.(eval$&.$1).$2}++while/\d+[-+*\/](?=(\d+)(.*))/g}@F;$_=join$",keys%H;/[-+*\/]/&&redo
Nahuel Fouilleul
quelle