Fall 2024 - P2
| Big Idea 3 | .1 | .2 | .3 | .4 | .5 | .6 | .7 | .8 | .10 | 
3.3.1 Mathematical Expressions
Categories: CSP Big Idea 3Student led teaching on Mathematical Expressions. Learn how mathematical expressions involve using arithmetic operators (like addition, subtraction, multiplication, and division) to perform calculations
Mathematical Expressions:
- Algorithm: A well-defined set of finite instructions designed to accomplish a specific task.
    - Example: Baking cookies involves following a structured series of steps in a precise order.
- Another example: In the morning, tasks such as putting on clothes and eating breakfast are executed in a particular sequence.
- In essence, an algorithm represents an ordered process that systematically leads to a desired outcome.
 
Key Elements of an Algorithm:
- 
    Sequencing: Ensuring tasks are executed in a strict, predefined order. 
- 
    Selection: After completing an initial step, a decision is made (yes/no or true/false), which dictates the next action—if a condition holds true, one path is followed, otherwise, an alternative action is taken. 
- 
    Iteration: Repeatedly performing a sequence of steps based on a condition. - Example: Complete the first step, proceed to the next, evaluate a condition, and if necessary, continue repeating the steps.
 
Methods for representing algorithms:
- Flowchart: Uses arrows and shapes to visually represent decisions and the flow of steps.
- Pseudocode: A simplified, high-level representation of an algorithm, often written in plain language or comments to describe each section’s functionality without using formal code syntax. </span>
import functools
import logging
# Setting up the logging configuration
logging.basicConfig(level=logging.INFO, format='%(levelname)s: %(message)s')
def memoize_factorial(func):
    """Decorator to cache results of factorial computations."""
    cache = {}
    
    @functools.wraps(func)
    def wrapper(n):
        if n not in cache:
            logging.info(f"Calculating factorial for {n}")
            cache[n] = func(n)
        else:
            logging.info(f"Using cached result for {n}")
        return cache[n]
    
    return wrapper
@memoize_factorial
def factorial(n):
    """Recursive factorial with memoization."""
    # Selection: Handle edge cases first
    if n < 0:
        logging.error(f"Factorial is not defined for negative numbers: {n}")
        return "Factorial is not defined for negative numbers"
    elif n == 0 or n == 1:
        # Base case
        return 1
    else:
        # Recursion with memoization
        return n * factorial(n - 1)
def parse_input(user_input):
    """Parses a comma-separated string of numbers, raises ValueError if input is invalid."""
    try:
        return [int(num.strip()) for num in user_input.split(',')]
    except ValueError:
        logging.error("Input contains invalid values. Please enter a valid list of non-negative integers.")
        raise
def main():
    try:
        # Get user input and parse it
        user_input = input("Enter a list of non-negative integers (comma-separated): ")
        numbers = parse_input(user_input)
        # Calculate and print the factorial for each valid number
        for number in numbers:
            result = factorial(number)
            if isinstance(result, int):
                logging.info(f"The factorial of {number} is: {result}")
            else:
                logging.error(f"Factorial for {number} is undefined due to invalid input.")
    
    except ValueError:
        logging.error("Invalid input. Program terminating.")
if __name__ == "__main__":
    main()
INFO: Calculating factorial for 5
INFO: Calculating factorial for 4
INFO: Calculating factorial for 3
INFO: Calculating factorial for 2
INFO: Calculating factorial for 1
INFO: The factorial of 5 is: 120
Example 1
Scenario: You’re in the middle of a geometry test and need to graph the function ( f(x) = 2(x - 3)^2 + 5 ), but you’re unsure how to start. By inputting a range of x-values, you can quickly compute the corresponding y-values, helping you plot the points and accurately sketch the graph. With this approach, you’ll confidently ace the graphing question and boost your test score!
# List of x-coordinates to be plugged into the equation to get the corresponding y-values
x_values = [2, 5, 7, 10]
# Loop to iterate through the list of x-coordinates
for x in x_values:
    # Calculate the corresponding y-values using the equation f(x) = 2(x - 3)^2 + 5
    y = 2 * (x - 3) ** 2 + 5
    # Print the result for each x-coordinate
    print(f"f({x}) = {y}")
f(2) = 7
f(5) = 13
f(7) = 37
f(10) = 103
