############################################################
# review list operations
############################################################


def review_list_ops():
    # indexing, assignment, slicing
    names = ["Wednesday", "Pugsley", "Pubert"]
    print(names)
    print(names[1])
    names[1] = "Joel"
    print(names)
    print(names[:2])
    print()

    # concatenation, backward slicing with default start/stop
    mirror = names + names[::-1]
    print(mirror)
    print()

    # `in` and `not in` membership testing, .append()
    middle_child = "Pugsley"
    print(middle_child in names)
    if middle_child not in names:
        names.append(middle_child)
    print(names)
    print()


# print()
# review_list_ops()


def building_lists():
    # build via successive .append()
    names = ["Wednesday", "Pugsley", "Pubert"]
    names_redacted = []
    for name in names:
        redacted = name[0] + "." * (len(name) - 1)
        names_redacted.append(redacted)
    print(names)
    print(names_redacted)
    print()

    # build via pre-allocation + index assignment
    names_inverted = [0] * len(names)
    for i in range(len(names)):
        names_inverted[i] = names[i].swapcase()
    print(names_inverted)
    print()

    # copying an existing list
    names_again = names.copy()
    names_again = list(names)
    names_again = names[:]
    print(names_again)
    names[1] = "Joel"
    print(names)
    print(names_again)
    print()


# print()
# building_lists()


def more_list_mutation():
    # deletion, insertion
    names = ["Wednesday", "Pugsley", "Pubert"]
    friend = "Joel"
    names.insert(1, friend)
    print(names)
    middle_child = names[2]
    del names[2]
    print(names)
    names.insert(-1, middle_child)  # equivalent to .append()
    print(names)
    print()

    # .extend() and +=, .pop()
    parents = ["Morticia", "Gomez"]
    names.extend(parents)
    print(names)
    swapped_parents = []
    for _ in range(2):  # _ is a placeholder variable
        swapped_parents.append(names.pop())
    print(names)
    names += swapped_parents  # equivalent to .extend()
    print(names)
    print()


# print()
# more_list_mutation()


def custom_reverse(a_list):
    # EXERCISE: implement the equivalent of .reverse() without using it
    ...

def test_reverse():
    test_cases = [
        [6, 1, 0, 0],
        [1, 6, 1, 0, 0],
    ]
    for numbers in test_cases:
        numbers.reverse()
        print(numbers)
        custom_reverse(numbers)
        print(numbers)
        print()


# print()
# test_reverse()


def str_operations_with_lists():
    # .split() outputs a list of substrings
    phrase = "Four score and seven years ago  "
    print(phrase.split("s"))
    print(phrase.split(" "))
    print(phrase.split())  # special behavior: splits on chunks of whitespace
    print()

    # .join() takes in a list of strs to glue together
    words = phrase.split()
    words.sort()
    print(words)
    rephrased = " ".join(words)
    print(rephrased)
    really_rephrased = " dude... ".join(words)
    print(really_rephrased)
    print()


# print()
# str_operations_with_lists()


############################################################
# function environments
############################################################


def greet(name):
    print(f"Griitings, {name}.")
    friendly = name.endswith("y") or name.endswith("ie")
    if friendly:
        print("  We kom in peas.")
    else:
        print("  Wollit and fone.")
    return friendly


def interview(candidates):
    friends = []
    for person in candidates:
        if greet(person):
            friends.append(person)
    return friends


# print()
# result = interview(["Georgie", "Sheldon", "Missy"])
# print(result)
# print()
# result = interview(["Alfie", "Alfred", "Sherry", "Sheryl", "Katie", "Katherine"])
# print(result)


############################################################
# consequences of mutation
############################################################


def playdate(group, visitor):
    group += [visitor]
    num_pairs = 0
    for person1 in group:
        for person2 in group:
            if person1 != person2:
                num_pairs += 1
    return num_pairs // 2


# print()
# children = ["Wednesday", "Pugsley", "Pubert"]
# num_interactions = playdate(children, "Joel")
# print(f"There were {num_interactions} interactions.")
# print(children)


def family_social(family, visitors):
    if len(family) != len(visitors):
        return 0
    num_interactions = 0
    for i in range(len(family)):
        num_interactions += playdate(family[i], visitors[i])
    return num_interactions


# print()
# children = ["Wednesday", "Pugsley", "Pubert"]
# adults = ["Morticia", "Gomez", "Fester"]
# addams = [children, adults]

# addams_doppels = addams.copy()
# num_interactions = family_social(addams_doppels, ["Joel", "Cousin Itt"])
# print(f"There were {num_interactions} interactions.")
# print(addams_doppels)
# print(addams)

# EXERCISE: fix addams_doppels, so that calling family_social() on it
# doesn't mutate the nested contents of addams
