Analizando una expresión de notación de infijo y conversión para revertir la notación polaca -- ptimization campo con parsing campo con converting campo con go campo con math-expression-eval camp codereview Relacionados El problema

Parsing an infix notation expression and converting to reverse polish notation


4
vote

problema

Español

Soy bastante nuevo para ir, y no conozco las formas mejor o idiomáticas de hacer la mayoría de las cosas, así que apreciaría los comentarios sobre cómo hacer que mi código sea mejor, más rápido o más idiomático.

Mi programa es un conjunto de métodos / funciones para analizar una expresión de notación de infijo, luego conviértela para revertir la notación polaca con el algoritmo de derivación de Dijkstra y finalmente lo resuelve, hasta ahora, es compatible con las operaciones básicas "+ - / * ^". , paréntesis anidados y amp; Funciones de TRIG básicas.

Archivo 1:

  package gocalc  import (     "strings"     "unicode" )  type Token struct {     Type  TokenType     Value string }  type TokenType int  const (     Number TokenType = iota     Operator     LParen     RParen     fnction )  // fnction Parse converts an expression into a stack of tokens func Parse(input string) (tokens Stack) {     var cont string     var fn bool      for _, v := range input {         val := string(v)         if unicode.IsDigit(v) || val == "." {             cont += val         } else if unicode.IsLetter(v) || strings.Contains("[]", val) {             if val == "]" {                 cont += val                 fn = false             } else {                 cont += val                 fn = true             }         } else if strings.Contains("+-*/^", val) {             if fn {                 cont += val             } else {                 if cont != "" {                     if unicode.IsLetter(rune(cont[0])) {                         tokens.Push(Token{fnction, cont})                     } else {                         tokens.Push(Token{Number, cont})                     }                     cont = ""                 }                 tokens.Push(Token{Operator, val})             }         } else if strings.Contains("()", val) {             if fn {                 cont += val             } else {                 if cont != "" {                     if unicode.IsLetter(rune(cont[0])) {                         tokens.Push(Token{fnction, cont})                     } else {                         tokens.Push(Token{Number, cont})                     }                     cont = ""                 }                 if val == "(" {                     tokens.Push(Token{LParen, val})                 } else {                     tokens.Push(Token{RParen, val})                 }             }          }     }     if cont != "" {         if unicode.IsLetter(rune(cont[0])) {             tokens.Push(Token{fnction, cont})         } else {             tokens.Push(Token{Number, cont})         }     }     return tokens }   

archivo 2:

  holroy0  

Archivo 3:

  holroy1  

El código se puede encontrar en github .

Planeo desarrollar aún más el código y eventualmente agregar la resolución de la ecuación y las características más avanzadas.

Original en ingles

I'm pretty new to Go, and I do not know the best or idiomatic ways to do most of the stuff, so I'd appreciate feedback on how to make my code better, faster or more idiomatic.

My program is a set of methods/functions to parse an infix notation expression then convert it to reverse polish notation using Dijkstra's Shunting-Yard algorithm and then finally solve it, so far it supports basic operations "+ - / * ^", nested parentheses & basic trig functions.

File 1:

package gocalc  import (     "strings"     "unicode" )  type Token struct {     Type  TokenType     Value string }  type TokenType int  const (     Number TokenType = iota     Operator     LParen     RParen     fnction )  // fnction Parse converts an expression into a stack of tokens func Parse(input string) (tokens Stack) {     var cont string     var fn bool      for _, v := range input {         val := string(v)         if unicode.IsDigit(v) || val == "." {             cont += val         } else if unicode.IsLetter(v) || strings.Contains("[]", val) {             if val == "]" {                 cont += val                 fn = false             } else {                 cont += val                 fn = true             }         } else if strings.Contains("+-*/^", val) {             if fn {                 cont += val             } else {                 if cont != "" {                     if unicode.IsLetter(rune(cont[0])) {                         tokens.Push(Token{fnction, cont})                     } else {                         tokens.Push(Token{Number, cont})                     }                     cont = ""                 }                 tokens.Push(Token{Operator, val})             }         } else if strings.Contains("()", val) {             if fn {                 cont += val             } else {                 if cont != "" {                     if unicode.IsLetter(rune(cont[0])) {                         tokens.Push(Token{fnction, cont})                     } else {                         tokens.Push(Token{Number, cont})                     }                     cont = ""                 }                 if val == "(" {                     tokens.Push(Token{LParen, val})                 } else {                     tokens.Push(Token{RParen, val})                 }             }          }     }     if cont != "" {         if unicode.IsLetter(rune(cont[0])) {             tokens.Push(Token{fnction, cont})         } else {             tokens.Push(Token{Number, cont})         }     }     return tokens } 

File 2:

package gocalc  import (     "math"     "strconv"     "strings" )  var oprData = map[string]struct {     prec int     asoc bool // true = right // false = left     fx   func(x, y float64) float64 }{     "^": {4, true, func(x, y float64) float64 { return math.Pow(x, y) }},     "*": {3, false, func(x, y float64) float64 { return x * y }},     "/": {3, false, func(x, y float64) float64 { return x / y }},     "+": {2, false, func(x, y float64) float64 { return x + y }},     "-": {2, false, func(x, y float64) float64 { return x - y }}, }  var fnData = map[string]func(x float64) float64{     "Cos":  func(x float64) float64 { return math.Cos(x) },     "Sin":  func(x float64) float64 { return math.Sin(x) },     "Tan":  func(x float64) float64 { return math.Tan(x) },     "Acos": func(x float64) float64 { return math.Acos(x) },     "Asin": func(x float64) float64 { return math.Asin(x) },     "Atan": func(x float64) float64 { return math.Atan(x) }, }  // Function ToRPN converts a stack of tokens from infix notation to Reverse Polish Notation func ToRPN(tokens Stack) Stack {     output := Stack{}     ops := Stack{}     for _, v := range tokens.Values {         switch {         case v.Type == Operator:             for !ops.IsEmpty() {                 val := v.Value                 top := ops.Peek().Value                 if (oprData[val].prec <= oprData[top].prec && oprData[val].asoc == false) ||                     (oprData[val].prec < oprData[top].prec && oprData[val].asoc == true) {                     output.Push(ops.Pop())                     continue                 }                 break             }             ops.Push(v)         case v.Type == LParen:             ops.Push(v)         case v.Type == RParen:             for i := ops.Length() - 1; i >= 0; i-- {                 if ops.Values[i].Type != LParen {                     output.Push(ops.Pop())                     continue                 } else {                     ops.Pop()                     break                 }             }         default:             output.Push(v)         }     }     if !ops.IsEmpty() {         for i := ops.Length() - 1; i >= 0; i-- {             output.Push(ops.Pop())         }     }     return output }  // Function SolveRPN returns the result of the Reverse Polish Notation expression func SolveRPN(tokens Stack) float64 {     stack := Stack{}     for _, v := range tokens.Values {         if v.Type == Number {             stack.Push(v)         } else if v.Type == Function {             stack.Push(Token{Number, SolveFunction(v.Value)})         } else if v.Type == Operator {             f := oprData[v.Value].fx             var x, y float64              y, _ = strconv.ParseFloat(stack.Pop().Value, 64)             x, _ = strconv.ParseFloat(stack.Pop().Value, 64)              result := f(x, y)             stack.Push(Token{Number, strconv.FormatFloat(result, 'f', 12, 64)})         }     }     out, _ := strconv.ParseFloat(stack.Values[0].Value, 64)     return out }  func SolveFunction(input string) string {     var fArg float64     fType := strings.TrimRight(input, "[.]0123456789+-/*^()")     args := strings.TrimLeft(strings.TrimRight(input, "]"), fType+"[")      if !strings.ContainsAny(args, "+ & * & - & / & ^") {         fArg, _ = strconv.ParseFloat(args, 64)     } else {         stack := Parse(args)         stack = ToRPN(stack)         fArg = SolveRPN(stack)     }      return strconv.FormatFloat(fnData[fType](fArg), 'f', 12, 64) } 

File 3:

package gocalc  type Stack struct {     Values []Token }  // Function Pop removes the top token of the stack and returns its value func (stack *Stack) Pop() (i Token) {     if len(stack.Values) == 0 {         return     }     i = stack.Values[len(stack.Values)-1]     stack.Values = stack.Values[:len(stack.Values)-1]     return }  // Fuction Push adds a token to the top of the stack func (stack *Stack) Push(i ...Token) {     stack.Values = append(stack.Values, i...) }  // Function Peek returns the token at the top of the stack func (stack *Stack) Peek() Token {     return stack.Values[len(stack.Values)-1] }  // Function IsEmpty check if there are any tokens in the stack func (stack *Stack) IsEmpty() bool {     return len(stack.Values) == 0 }  // Function Length returns the amount of tokens in the stack func (stack *Stack) Length() int {     return len(stack.Values) } 

The code can be found on GitHub.

I plan to further develop the code and to eventually add equation solving and more advanced features.

              

Lista de respuestas


Relacionados problema

1  Evaluando una expresión aritmética de un árbol binario  ( Evaluating an arithmetic expression from a binary tree ) 
Digamos que tengo un árbol binario que se ve + 2 * 5 8 He escrito una función para atravesar el inicio para resolverl...

6  Programa de Convertidor de Infix a Postfix  ( Infix to postfix converter program ) 
Esta es mi tarea. Amablemente ayúdame a verificarlo? Las instrucciones son: Implementar una expresión de infIX en el convertidor de expresión postfix. De...

8  Codewars Evaluador de expresión matemática  ( Codewars mathematical expresion evaluator ) 
Recientemente escribí el siguiente código para un Codewars.com Kata para evaluar las expresiones matemáticas . He estado escribiendo Ruby durante años, pero ...

3  La calculadora recursiva basada en RPN-STACK necesita TuneUp  ( Rpn stack based recursive calculator needs tuneup ) 
Esta función toma una serie de cuerdas y números y la procesa recursivamente como un tipo de "programa de cálculo". La estructura se basa en la notación de po...

2  Expresión de infijo (con números negativos) a Postfix  ( Infix expression with negative numbers to postfix ) 
Estoy escribiendo una clase para evaluar una expresión aritmética, ya que ahora mi clase puede convertir una expresión de infijo en PostFix, todavía no admite...

2  Verificación de expresiones matemáticas  ( Verifying mathematical expressions ) 
Esta es una parte de mi programa de calculadora. Tengo que verificar si la entrada ingresada por el usuario es una expresión matemática válida. El primer prog...

3  Calculadora de RPN de NASM  ( Nasm rpn calculator ) 
He estado aprendiendo ensamblaje en los últimos días, y he hecho una simple calculadora RPN. Aquí está la lógica principal del programa, excluyendo las func...

5  Calculadora de derivados algebraica estándar  ( Standard algebraic derivative calculator ) 
Tuve alguna dificultad con este problema, así que estoy seguro de que hay una mejor manera. Aquí está la pregunta de SICP : ejercicio 2.58 Supongamos ...

3  Análisis de expresión (solo operadores aritméticos)  ( Expression parsing arithmetic operators only ) 
Como un proyecto de auto-aprendizaje, escribí un analizador de expresión utilizando el algoritmo de la derivación del patio en JavaScript. Es una parte más gr...

1  Parser Ecuación + Solver  ( Equation parser solver ) 
Aquí hay un analizador de la ecuación que acabo de escribir. Mi enfoque fue la legibilidad y la perspectiva de agregar nuevas características en el futuro. Co...




© 2022 respuesta.top Reservados todos los derechos. Centro de preguntas y respuestas reservados todos los derechos