Veo tus BIDMAS y te crío un BADMIS

21

Veo tus BIDMAS y te crío un BADMIS

Reto

Dado un conjunto de números con operadores entre ellos: "5 + 4 * 9/3 - 8", devuelve todos los resultados posibles de la expresión para cada permutación del orden de operaciones básicas: [/, *, +, -].

Reglas

  • Lagunas estándar prohibidas
  • I / O
    • La entrada debe ordenarse con operaciones infijadas, pero sin embargo eso es más fácil (cadena o matriz)
    • No es necesario que admita operadores unarios (por ejemplo, "-3 * 8 / +2")
    • Los enteros se pueden reemplazar por flotantes para los idiomas que analizan implícitamente el tipo (por ejemplo, 45 ⟶ 45.0)
    • La salida debe ser todos los resultados posibles de la expresión, sin formato u orden especificado
  • Todas las entradas son válidas (por ejemplo, no es necesario tratar con "7/3 + *"). Esto también significa que nunca necesitará dividir por cero.
  • Todos los operadores son asociativos a la izquierda, por lo que "20/4/2" = "(20/4) / 2"
  • Este es Code Golf, por lo que gana la menor cantidad de bytes

Casos de prueba (con explicación)

  • "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

Casos de prueba (sin explicación)

  • "45/8 + 19/45 * 3" = [6.891666666666667, 18.141666666666666, 0.11111111111111113, 0.01234567901234568, 0.01234567901234568, 5.765740740740741]
  • "2 + 6 * 7 * 2 + 6/4" = [112196 23 87.5]
Freddie R
fuente
2
Bonito primer desafío, sin embargo, por cierto.
Shaggy
Muy relacionado
Arnauld
Caso de prueba sugerido 2 - 3 + 4=>[-5, 3]
Jo King
Caso de prueba sugerido: 2*3-6+2-9/6*8+5/2-9da 24 resultados distintos.
Arnauld

Respuestas:

3

C # (compilador interactivo de Visual C #) , 285 bytes

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]));}}

Pruébalo en línea!

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
  }
}
Encarnación de la ignorancia
fuente
Lo he arreglado para que no tenga que omitir duplicados, ya que no es una parte fundamental del problema como se señaló.
Freddie R
1
@Arnauld Corregido al costo de 4 bytes, fue porque mi algoritmo de permutaciones estaba un poco equivocado
Encarnación de la ignorancia
3

JavaScript (Node.js) , 132 bytes

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

Pruébalo en línea!

Esto permite salidas duplicadas.

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)

Pruébalo en línea!

Toma una cadena con espacios entre operadores y números.

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
fuente
@JoKing Implementé la solución que he indicado antes, debería salir [3, -5]ahora.
Shieru Asakoto
2

Perl 6 , 92 90 88 bytes

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

Pruébalo en línea!

Toma una cadena con un espacio después de cualquier operador y devuelve un conjunto de números. Esto funciona principalmente sustituyendo todas las instancias de n op ncon el resultado evaluado por todas las permutaciones de los operadores.

Explicación:

{                                                                                   }  # 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
Jo King
fuente
Puede eliminar set, ya que se eliminó la condición para eliminar duplicados. Buen código
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]

Pruébalo en línea!

La función toma una sola cadena como entrada y devuelve una lista de posibles resultados.

Sin golf

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]

Pruébalo en línea!

Joel
fuente
1

Jalea , 30 bytes

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

Pruébalo en línea!

Un par de enlaces. El segundo es el enlace principal, y toma como argumento una lista Jelly de flotantes / enteros intercalados con los operadores como caracteres. Esta es una versión plana de la forma en que Jelly toma su entrada cuando se ejecuta como un programa completo con argumentos de línea de comandos. El valor de retorno del enlace es una lista de listas de miembros individuales, cada una de las cuales es un valor posible para la expresión.

Explicación

Enlace auxiliar

Toma una lista de flotantes / enteros alternando con operadores (como caracteres) como argumento izquierdo y un operador como carácter como argumento derecho; devuelve la lista de entrada después de evaluar números separados por el operador relevante, trabajando de izquierda a derecha.

œṡ⁹                  | 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

Enlace principal

Toma una lista de flotantes / enteros alternando con operadores (como caracteres)

Ḋ         | 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
fuente
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

Pruébalo en línea!

Toma datos con ints formateados como flotantes, según "Los enteros pueden reemplazarse por flotantes para idiomas que implícitamente analizan el tipo".

Chas Brown
fuente
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

Toma una cinta en forma de un vector de números y funciones de infijo, evalúa cada llamada de función individual y pasa recursivamente cada cinta resultante de vuelta a sí misma hasta que solo quede un solo número. Desafortunadamente,get(t, (), ...) no funciona correctamente en Julia 1.0, por lo que se necesita una versión más nueva.

Se pueden guardar seis bytes, si un conjunto de matrices anidadas es aceptable como salida:

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

Salida:

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]] 
usuario3263164
fuente
0

Perl 5 ( -alp), 89 bytes

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

TIO

o valores únicos, 99 bytes

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