"""
Examples
"""

"""
Write a function that finds all elements present in input lists seq1 and seq2, 
and returns a new list containing only those elements, sorted in increasing order.
"""


def seq_intersect(seq1, seq2):
    result = []  # Initialize an empty list to store the intersection.
    for x in seq1:  # Iterate over each item in the first sequence.
        if x in seq2:  # Check if the item is also in the second sequence.
            if not x in result:
                result.append(x)  # If so, add it to the result list.
    result.sort()  # Sort the resulting list to ensure items are in order.
    return result  # Return the sorted intersection list.


seq1 = [1, 4, 5, 1, 5, 8, 9, 10, 22]
seq2 = [8, 4, 1, 8, 13, 82, 33]
print(seq_intersect(seq1, seq2))


"""
Multiply and add function, scalar
"""


def multiply_and_add_scalar(m, n, p):
    return m * n + p


t = multiply_and_add_scalar(3, 4, 2)  # t = 14
print(t)
t = multiply_and_add_scalar(5, 2, t)  # t = 39
print(t)


"""
Multiply and add function, scalar
Modified, to include default argument values
"""


def multiply_and_add_scalar_bis(m, n=0.5, p=2):
    return m * n + p


t = multiply_and_add_scalar_bis(3)  # t = 3.5
print(t)
t = multiply_and_add_scalar_bis(5, 2)  # t = 12
print(t)


"""
Let's try type-dependent behavior
"""


def multiply_and_add(m, n, p):
    return m * n + p


t = multiply_and_add("I", 1, multiply_and_add("C", 2, "-P"))
print(t)


"""
Write a function bubble_sort_descending() which takes a list as argument and returns the list sorted in descending order
"""


def bubble_sort_descending(arr):
    n = len(arr)  # local variable
    for i in range(n):  # repeat for every array element; local var. i
        for j in range(0, n - i - 1):  # traverse the unsorted part of the list
            if arr[j] < arr[j + 1]:  # compare and swap
                temp = arr[j]  # local variables temp and j
                arr[j] = arr[j+1]
                arr[j+1] = temp
    return arr  # return the sorted array

# Example usage
seq = [5, 3, 8, 4, 2]
sorted_seq = bubble_sort_descending(seq)

print("Original array seq = ", seq)
# [ 5, 3, 8, 4, 2]
print("Sorted array sorted_seq = ", sorted_seq)
# [8, 5, 4, 3, 2]

# Then add these two lines. What is printed?
seq[0] = -1
print("Original array seq = ", seq)
# [-1, 5, 4, 3, 2] How come??
print("Sorted array sorted_seq = ", sorted_seq)
# [-1, 5, 4, 3, 2] How come??

# Now that you know array parameters can be modified from "outside" update your function and code to return a NEW array
def bubble_sort_descending_returns_new(unsorted_arr):
    n = len(unsorted_arr) # local variable
    arr = unsorted_arr.copy()
    for i in range(n): # repeat for every array element; local var. i
        for j in range(0, n - i - 1): # traverse the unsorted part of the list
            if arr[j] < arr[j + 1]: # compare and swap
                temp = arr[j] # local variables temp and j
                arr[j] = arr[j+1]
                arr[j+1] = temp
    return arr

# Example usage
seq = [5, 3, 8, 4, 2]
sorted_seq = bubble_sort_descending_returns_new(seq)

print("NEW: Original array seq = ", seq)
# [ 5, 3, 8, 4, 2]
print("NEW: Sorted array sorted_seq = ", sorted_seq)
# [8, 5, 4, 3, 2]

# Then add these two lines. What is printed?
seq[0] = -1
print("NEW: Original array seq = ", seq)
# [-1, 3, 8, 4, 2]
print("NEW: Sorted array sorted_seq = ", sorted_seq)
# [8, 5, 4, 3, 2]



