from typing import List

def collect_underperformers(nums: List[int], threshold: int) -> List[int]:
    """Return a new list consisting of those numbers in nums that are below
    threshold, in the same order as in nums.
    
    >>> collect_underperformers([1, 2, 3, 4], 3)
    [1, 2]
    >>> collect_underperformers([1, 2, 108, 3, 4], 50)
    [1, 2, 3, 4]
    >>> collect_underperformers([], 7)
    []
    """
    
    # accumulator (empty list)
    underperformers = []
    
    # Idea:
    # Loop over each item in the list
    #     Check if the item is < threshold
    #         Add / append to the accumulator list
    
    # This english description of what our code does 
    # is called 'pseudocode'
    
    # Used our pseudocode to write the function in real code.
    
    # Loop over each item in the list
    for num in nums:
        # Check if the item is < threshold
        if num < threshold:
            # Add / append to the accumulator list    
            underperformers.append(num)

            # another way:
            #underperformers = underperformers + [num]
            
    # return the accumulator
    return underperformers


def scale_midterm_grades(grades: List[int], multiplier: int, bonus: int) -> None:
    """Modify each grade in grades by multiplying it by multiplier and then
    adding bonus. Cap grades at 100.
    
    >>> grades = [45, 50, 55, 95]
    >>> scale_midterm_grades(grades, 1, 10)
    >>> grades
    [55, 60, 65, 100]
    """
    
    # do we need an accumulator?
    # No. We are modifying/mutating the list grades
    # so we don't need to accumulate and return a new one.
    
    ## Pseudocode:
    # Loop over each index:
    #     Modify the element at the index by multiplying it by 
    #     multiplier.
    #     Check if the modified element is > 100
    #          Set the element to be 100
    
    # Loop over each index:
    for i in range(len(grades)):
        # Modify the element at the index by multiplying it by 
        # multiplier and add the bonus.
        grades[i] = grades[i] * multiplier + bonus
        # Check if the modified element is > 100
        if grades[i] > 100:
            # Set the element to be 100    
            grades[i] = 100

    # No return necessary - we are modifying the given list
    
    
def scale_midterm_grades_bad(grades: List[int], multiplier: int, bonus: int) -> None:   
    # Can we loop over the elements and not the indexes?
    # can we do:
    for grade in grades:
        grade = grade * multiplier + bonus
    # Numbers are not mutable!
    # We can't change them in place
    
    # We HAVE to use the indexes for the for loop
    
    # Usually when you want to modify a list with just numbers
    # or strings in it, you should iterate over the indexes
    
    
        
    
    