w3resource

Dictionary as Abstract Syntax Tree: Evaluating Complex Expressions


90. Dictionary-based Expression Evaluator

Write a Python function that evaluates mathematical expressions represented as dictionaries. The expression dictionary should support basic operations (+, -, *, /), variables, and nested expressions.

Solution:

Python Code:

# Define a function to evaluate a mathematical expression represented as a dictionary.
def evaluate_expression(expr, variables):
    """
    Evaluate a mathematical expression represented as a dictionary.
    
    Args:
        expr: Dictionary representing the expression
        variables: Dictionary mapping variable names to values
    
    Returns:
        The result of evaluating the expression
    """
    # Handle constants: If the expression contains a "const" key, return its value directly.
    if "const" in expr:
        return expr["const"]
    
    # Handle variables: If the expression contains a "var" key, look up its value in the variables dictionary.
    if "var" in expr:
        var_name = expr["var"]  # Get the variable name from the expression.
        if var_name not in variables:
            raise ValueError(f"Variable '{var_name}' not defined")  # Raise an error if the variable is undefined.
        return variables[var_name]  # Return the value of the variable.
    
    # Handle operations: If the expression contains an "op" key, evaluate the operation recursively.
    if "op" in expr:
        op = expr["op"]  # Get the operator (e.g., "+", "-", "*", "/").
        left = evaluate_expression(expr["left"], variables)  # Recursively evaluate the left operand.
        right = evaluate_expression(expr["right"], variables)  # Recursively evaluate the right operand.
        
        # Perform the operation based on the operator type.
        if op == "+":
            return left + right  # Addition.
        elif op == "-":
            return left - right  # Subtraction.
        elif op == "*":
            return left * right  # Multiplication.
        elif op == "/":
            if right == 0:
                raise ZeroDivisionError("Division by zero")  # Raise an error for division by zero.
            return left / right  # Division.
        else:
            raise ValueError(f"Unknown operator: {op}")  # Raise an error for unsupported operators.
    
    # If the expression format is invalid, raise an error.
    raise ValueError("Invalid expression format")

# Example expressions
# Define an example expression: x + y * 2
expr1 = {
    'op': '+',  # The operation is addition.
    'left': {'var': 'x'},  # The left operand is the variable 'x'.
    'right': {'op': '*', 'left': {'var': 'y'}, 'right': {'const': 2}}  # The right operand is y * 2.
}

# Define another example expression: (10 / a) - (b * c)
expr2 = {
    'op': '-',  # The operation is subtraction.
    'left': {'op': '/', 'left': {'const': 10}, 'right': {'var': 'a'}},  # The left operand is 10 / a.
    'right': {'op': '*', 'left': {'var': 'b'}, 'right': {'var': 'c'}}  # The right operand is b * c.
}

# Example variable values
# Define variable values for the first expression: x = 5, y = 3
variables1 = {'x': 5, 'y': 3}

# Define variable values for the second expression: a = 2, b = 3, c = 4
variables2 = {'a': 2, 'b': 3, 'c': 4}

# Evaluate expressions
# Evaluate the first expression using the provided variables.
result1 = evaluate_expression(expr1, variables1)

# Evaluate the second expression using the provided variables.
result2 = evaluate_expression(expr2, variables2)

# Print the results of the evaluations.
print(f"Expression 1 result: {result1}")  # Should be 11 (5 + 3*2).
print(f"Expression 2 result: {result2}")  # Should be -7 (10/2 - 3*4).

Output:

Expression 1 result: 11
Expression 2 result: -7.0

Explanation of Each Line:

  • Function Definition : Defines evaluate_expression, a function to evaluate a mathematical expression represented as a dictionary.
  • Docstring : Provides a description of the function, its arguments, and its return value.
  • Handle Constants : Checks if the expression contains a "const" key and returns its value directly.
  • Handle Variables : Checks if the expression contains a "var" key and retrieves its value from the variables dictionary.
  • Undefined Variable Check : Raises an error if the variable is not defined in the variables dictionary.
  • Handle Operations : Checks if the expression contains an "op" key to evaluate mathematical operations.
  • Get Operator : Retrieves the operator (e.g., "+", "-", "*", "/") from the expression.
  • Evaluate Left Operand : Recursively evaluates the left operand of the operation.
  • Evaluate Right Operand : Recursively evaluates the right operand of the operation.
  • Addition Operation : Performs addition if the operator is "+".
  • Subtraction Operation : Performs subtraction if the operator is "-".
  • Multiplication Operation : Performs multiplication if the operator is "*".
  • Division Operation : Performs division if the operator is "/", with a check for division by zero.
  • Unknown Operator Error : Raises an error if the operator is not supported.
  • Invalid Expression Error : Raises an error if the expression does not match any valid format.
  • Example Expression 1 : Defines an expression x + y * 2 as a nested dictionary.
  • Example Expression 2 : Defines an expression (10 / a) - (b * c) as a nested dictionary.
  • Variable Values for Example 1 : Defines variable values for the first expression: x = 5, y = 3.
  • Variable Values for Example 2 : Defines variable values for the second expression: a = 2, b = 3, c = 4.
  • Evaluate Expression 1 : Evaluates the first expression using the provided variables.
  • Evaluate Expression 2 : Evaluates the second expression using the provided variables.
  • Print Result 1 : Prints the result of the first expression evaluation (5 + 3 * 2 = 11).
  • Print Result 2 : Prints the result of the second expression evaluation (10 / 2 - 3 * 4 = -7).

Explanation - Dictionary-based Expression Evaluator

  • Concept: Evaluate mathematical expressions represented as nested dictionaries.
  • Challenge: Recursively evaluate an expression tree with operations, variables, and constants.
  • Key Skills:
    • Recursive tree traversal
    • Expression evaluation techniques
    • Pattern matching
  • Applications:
    • Building calculators or formula evaluators
    • Implementing simple programming language interpreters
    • Creating rule engines or decision systems
    • Evaluating user-defined formulas in applications
  • Benefits:
    • Provides a flexible way to represent and compute expressions
    • Allows for dynamic expression creation and modification
    • Separates expression representation from evaluation logic

For more Practice: Solve these Related Problems:

  • Write a Python function to evaluate a dictionary-based expression that supports logical operators (`AND`, `OR`, `NOT`).
  • Write a Python function to evaluate a dictionary-based expression while keeping a detailed log of computation steps.
  • Write a Python function to extend dictionary-based expressions to support lambda functions as operations.
  • Write a Python function to validate and optimize a dictionary-based expression tree before evaluation.

Python Code Editor:

Previous: Dictionary Serialization with Circular References.
Next: Python Tuple Exercise Home

What is the difficulty level of this exercise?

Test your Programming skills with w3resource's quiz.



Follow us on Facebook and Twitter for latest update.