Home / Extra Coding Practice

Extra Coding Practice

You are not logged in.

If you are a current student, please Log In for full access to the web site.
Note that this link will take you to an external site (https://shimmer.mit.edu) to authenticate, and then you will be redirected back to this page.

Branching 1 Assume you're given 2 int variables: n1 and n2. Print "both" if they are both positive, "only one" if only one of them is positive, and "neither" if neither are positive.

Branching 2 Assume you're given 2 int variables: n1 and n2. Print "both" if they both have a 0 as one of their digits, "only one" if only one of them has a 0, and "neither" if neither has a 0.

Branching 3 Assume you're given 2 int variables: n1 and n2. If both are positive, print the sum of the first digits in each. If both are negative, print the sum of the last digits in each. If only one is positive and the other is not, print the result when you divide the last digit by the first digit of the positive n.

Loops 1 Set a variable named myrange to have the value some range. Set up a positive number in a variable called num. * For example:

myrange = range(1,7)
num = 2

  • Print the first number in myrange that is divisible by num and break out of the loop immediately.

Loops 2 Set a variable named myrange to have the value some range. Set up a positive number in a variable called num. * For example:

myrange = range(1,7)
num = 2

  • Print the last number in myrange that is divisible by num and break out of the loop immediately.

Loops 3 Rewrite the loop so the loop variable is over the string itself

s = "strings are cool"
for i in range(len(s)):
    if s[i] != ' ':
        print(s[i])

Loops 4 Rewrite the loop so the loop variable is over the string itself

mys = "this is weird"
for i in range(len(mys)//2):
    print(mys[i])

Loops 5 Rewrite the loop so the loop variable is over the string itself

astr = "what a strange operation!"
for i in range(0,len(astr),2):
    print(astr[i])

Loops 6 Write code that prints a given string without spaces, all on one line. If the input is s = "strings without spaces are hashtags" then your code prints stringswithoutspacesarehashtags.

Loops 7 Write code that prints the 4th root of a variable n if n is a perfect power. If it's not a prefect power print "no root".

Loops 8 Write code that converts a positive base 10 number to binary, using this method.

  • Find the biggest power of 2 to get close to but not over your original base 10 number, say n. This power of 2 represents a "1" digit at that power of 2 spot in the binary number.
  • Find the difference between your n and that power of 2. This is your new number of interest, n.
  • Repeat both steps until the difference is 0.

Loops 9 Write code to convert a whole binary number to its equivalent number in base 10. Assume the input binary number is a whole number as a int, n and your code prints the equivalent number in base 10. Eg: the int 100100 should print the int 36

Loops 10 Start with the previous code you wrote to convert a binary number (as an int) to its equivalent number in base 10. This time, your code should work with the input, a variable named n, as a decimal binary number and should print the equivalent base 10 decimal number. Eg: the int 1001.011 should give you the int 9.375



Bisection 1 You are guessing a lowercase letter from a to z. Use bisection search to find the value of a str letter variable, secret_letter, and how many guesses you made to find it. For example, if you find the secret letter to be 'h' after 4 guesses, print found h after 4 guesses. Start with this:

letter_low = 'a'
letter_high = 'z'
alphabet = 'abcdefghijklmnopqrstuvwxyz'

Bisection 2 Bisection search splits the domain in half. When you have a domain that is biased towards one half, you can bias the search. This code divides the search space into two parts, but biases the division towards smaller numbers from that range. That means that you'll find smaller numbers faster than larger numbers.

If the original range is this                       |-------------| 
then bisection search by dividing the space by 3 is |----/--------| 
instead of the usual way that divides it in half    |------/------|

The code below tries to find a secret number 0 <= m <= 100, but it does not work for some values of secret. Fix it!

secret = 3  # 3, 11, 42, work
            # 2, 4, 12, 99, 100 do not work
a = 0
b = 100
times = 1
m = a + (b-a) // 3  # note the floor division by 3
while True:
    if m < secret:
        a = m
    elif m > secret:
        b = m
    else:
        print(f'found {m} after {times} times')
        break
    m = a + (b-a) // 3  # note the floor division by 3
    times += 1



Function 1 Implement the function that meets the specification below:

def make_num(a, b, c):
    """ a, b, c are positive ints
    Returns the int number abc, where abc is represented as the concatenation of a, b, and c """
    # your code here
    
# Examples:    
make_num(12, 53, 76)  # should return 125376

Function 2 Implement the function that meets the specification below:

def exact_divide_between(n, d):
    """ n and d are positive ints > 1
    
    Returns how many ints from 2 to d divide n evenly. 
    If there are zero, then returns None, but prints 
    "No divisors 2 to d." (replacing d with the actual parameter)
    """
    # your code here

# Examples
print(exact_divide_between(10,6))   # prints 2
print(exact_divide_between(11,5))   # prints "No divisors 2 to 5" then None
print(exact_divide_between(20,2))   # prints 1

Function 3 Implement the function that meets the specification below:

def add_ops(func, num, s):
    """ func is a function that takes in an int or str and returns an int
        num is an int
        s is a str
    Prints 'check input' if num is not an int or s is not a str. 
    Otherwise, it returns the sum of the result when you run 
    func on num with the result when you run func on s.   
    """
    # your code here

## Examples of func:
def num_chars(a):
    if type(a) == str:
        return len(a)
    if type(a) == int:
        return len(str(a))

def always_0(a):
    return 0

# Examples
print(add_ops(num_chars, 74, 'abc'))  # prints 5
print(add_ops(always_0, 74, 'abc'))   # prints 0

Function 4 Implement the function that meets the specification below:

def validate_address(s):
    """ s is a str
    Returns True if s is a valid email address and False otherwise. 
    A valid email address contains #@#.# where you have one '@' sign but 
    one or more # (any alphabetical or digit character) in each of the 3 places. 
    """
    # your code here

# Examples
print(validate_address('anabell@mit.edu'))           # prints True
print(validate_address('ana.bell@mit.edu'))          # prints True
print(validate_address('a@a.a'))                     # prints True
print(validate_address('anabanana123@hotmail.com'))  # prints True
print(validate_address('a@.edu'))                    # prints False
print(validate_address('***@mit.edu'))               # prints False
print(validate_address('ana@bell@mit.edu'))          # prints False
print(validate_address('anabellmitedu'))             # prints False

Function 5 Implement the function that meets the specification below:

def validate_many_addresses(s):
    """ s is a str, supposed to contain many email addresses separated by a space
                    assume the last character in s is an empty space
    
    Returns True if ALL emails addresses in a are valid email addresses and False otherwise. 
    A valid email address contains #@#.# where you have one '@' sign but 
    one or more # (any alphabetical or digit character) in each of the 3 places. 
    """
    # your code here

# Examples
print(validate_many_addresses('a@mit.edu a@a.a '))          # prints True
print(validate_many_addresses('a@a.a b@b.b c@c.c d@d.d '))  # prints True
print(validate_many_addresses('a.b@m.u aa@.bb '))           # prints False
print(validate_many_addresses('be@gm.co aaa@.bb cc#@d.e ')) # prints False



Tuples 1 Implement the function that meets the specification below:

def make_ints(t):
    """ t is a tuple
    Returns a tuple whose elements are only the ints within t, 
    in the same order that they appear in t. """
    # your code here


# Examples
print(make_ints((3,5,'a',7)))  # prints the tuple (3, 5, 7)

Tuples 2 Implement the function that meets the specification below:

def median(*nums):
    """ nums is a non-empty tuple of numbers in increasing order
    
    If nums has an odd number of elements, returns the value of the 
    middle one. Otherwise, returns the average of the middle two numbers.  """
    # your code here


# Examples
print(median(3,5,8,9,10))  # prints 8
print(median(3,5,8,9))     # prints 6.5



Lists 1 Implement the function that meets the specification below:

def count_ints(L):
    """ L is a list
    Returns how many elements in L are ints. """
    # your code here
    

# Examples
print(count_ints([3,5,'a',7]))  # prints 3

Lists 2 Implement the function that meets the specification below:

def correct_sentence(s):
    """ s is a string representing a sentence of the form: 
               noun likes to verb1 verb2 verb3.
        Returns a string of the form:
               noun likes to verb1, verb2, and verb3.
        Note: noun might be one or many words.
    """
    # your code here
    
# Examples
s = 'ana likes to run skip jump.'
print(correct_sentence(s)) # prints ana likes to run, skip, and jump.
s = 'my mom likes to run skip jump.'
print(correct_sentence(s)) # prints my mom likes to run, skip, and jump.

Lists 3 Implement the function that meets the specification below:

def correct_ordered_sentence(s):
    """ s is a string representing a sentence of the form: 
               noun likes to verb1 verb2 verb3 ... verbn.
        Returns a string of the form:
               noun likes to verb1, verb2, and verb3 .. verbn where the
               verbs are now in alphabetical order.
        Note: noun might be one or many words
    """
    # your code here

# Examples    
s = 'ana likes to run skip jump hop dance.'
print(correct_ordered_sentence(s)) 
            # prints ana likes to dance, hop, jump, run, and skip.

Lists 4 Implement the function that meets the specification below:

def is_sum(L1, L2, L3):
    """ L1, L2, L3 are lists of equal length, whose elements are numbers
    
    Mutates L1 to have elements that are either True or False. An element at 
    index i is True if L1 at that index is the sum of L2 and L3 at that index.
    It's False otherwise. Returns None.    """
    # your code here

# Example
L1 = [3,6,1]
L2 = [1,5,7]
L3 = [1,2,-6]
print(is_sum(L1, L2, L3))  # prints None
print(L1)    # prints [False, False, True]

Lists 5 Implement the function that meets the specification below:

def get_element_lens(L):
    """ L is a list of ints, floats, lists, tuples, or strings.
    
    Returns a list whose elements are the length of each element in L, 
    in the same order they appear in L. If the type of the element is 
    an int or float, the length is the length of its string representation. """
    # your code here

# Examples
Lin = [5, 8.0, [6,4], (0,), 'ana']
print(get_element_lens(Lin))   # prints [1, 3, 2, 1, 3]

Lists 6 Implement the function that meets the specification below:

def change_to_lens(L):
    """ L is a list of ints, floats, lists, tuples, or strings.
    
    Mutates L to be a list whose elements are the length of 
    that element. If the elements is an int or float, the length 
    is the length of its string representation.  Returns None. """
    # your code here

# Examples
B = [5, 8.0, [6,4], (0,), 'ana']
print(change_to_lens(B))   # prints None
print(B)        # prints [1, 3, 2, 1, 3]

A = [5, (0,), '6.100L']  
print(change_to_lens(A)) # prints None 
print(A)        # prints [1, 1, 6]

Lists 7 Implement the function that meets the specification below:

def remove_from_list(L1, L2):
    """ L1 and L2 are lists
    Mutate L1 such that it contains the same elements in the same 
    order, but without any elements that appear in L2. """
    Lnew = L1[:]
    for i in range(len(Lnew)):
        if Lnew[i] in L2:
            del(L1[i])

# Examples
L1 = [4,3,6,7,3,2,1,3]
L2 = [1,3]
remove_from_list(L1, L2)
print(L1)   # prints the list [4, 6, 7, 2]

Lists 8 Implement the function that meets the specification below:

def up_to_n(n, as_str = False):
    """ n is an int
        as_str is a bool, default False
    Returns a new list with n elements, in order from 1 to n. 
    If as_str is False, each element is the int version of that int. 
    If as_str is True, each element in is the str version of that int.    
    """
    # your code here

# Examples
print(up_to_n(4))        # prints the list [1, 2, 3, 4]
print(up_to_n(4, True))  # prints the list ['1', '2', '3', '4']

Lists 9 Fix the function to meet the specification below:

def get_duplicates(L, verbose=False):
    """ L is a list of ints
        verbose is a boolean, used for debugging prints
    Returns a sorted list containing the all elements in 
    L (without repeating) that occur more than once in L """
    # fix this code
    seen = []
    unique = []
    for e in L:
        if e not in seen:
            unique.append(e)
        seen.append(e)
    for e in unique:
        while e in seen:
            seen.remove(e)
    return (seen)

# Examples
L = [1,2,3,2,3]
print(get_duplicates(L))  # prints [2,3]

L = [4,2,3,2,3,1,5,4,4]
print(get_duplicates(L))  # prints [2,3,4]

Lists 10 Fix the function to meet the specification below:

def f(L, val):
    """ L is a list 
        val is an int 
    If all elements in L are less than val, returns their average. 
    If at least one element in L is greater than val, returns False. """
    # fix this code
    for e in L:
        if e >= val:
            return False
    return sum(L)/len(L)

# Examples
# list of all numbers, val a number, and result is True
# list of all numbers, val a number, and result is False
# list with nothing in it, val a number
# list that contains numbers and other types, val a number
# list that contains numbers, val is not a number

Lists 11 Fix the function to meet the specification below:

def f(L, val):
    """ L is a non-empty list of ints
        val is a positive int
    If all elements in L are less than val, returns their average. 
    If at least one element in L is greater than val, returns False. """
    # fix this code
    for e in L:
        if e >= val:
            return False
    return sum(L)/len(L)

Dictionaries 1 Implement the function that meets the specification below:

def get_keys(d, x):
    """ d is a dict
    Assume a dict entry is a dk,dv pair. Returns a list, in sorted order, 
    of all dict keys, dk, whose associated dv is x. """
    # your code here

# Examples
d = {1:2, 3:4, 5:6}
x = 6
print(get_keys(d, x))  # prints [5]

d = {5:6, 3:4, 1:6}
x = 6
print(get_keys(d, x))  # prints [1, 5]

Dictionaries 2 Fix the function to meet the specification below:

def remove_with_val(d, x):
    """ d is a dict
    Assume a dict entry is a dk,dv pair. Mutates d so that all dict entries 
    whose dict value, dv, is x are removed from d. Returns None. """
    # fix this code
    for k,v in d.items():
        if v==x:
            del(d[k])


# Examples
d = {1:2, 3:4, 5:6}
x = 6
remove_with_val(d, x) 
print(d)   # prints {1: 2, 3: 4}

d = {5:6, 3:4, 1:6}
x = 6
remove_with_val(d, x) 
print(d)   # prints {3: 4}

Dictionaries 3 Implement the function that meets the specification below:

def make_d(L):
    """ L is a list with an even number of numerical elements 

    Returns a dictionary whose keys are the numbers at odd positions in L
    and the value associated with each key is the number at the even position
    immediately following an odd one. If there are many numbers at odd positions
    that are the same, pick the first one that appears in L to keep in the dict."""
    # your code here

L = [4,5,6,7]
print(make_d(L))  # prints {4:5, 6:7}            

L = [4,1,5,1,6,1]
print(make_d(L))  # prints {4:1, 5:1, 6:1}            

L = [4,1,4,5,6,1]
print(make_d(L))  # prints {4:1, 6:1}            

Dictionaries 4 Implement the function that meets the specification below:

def count_ints(LL):
    """ LL is a list whose elements are lists of ints 
    
    Returns a frequency dict whose keys are unique ints in LL's inner
    lists, and the associated value with a key is a count of how many times 
    that int appears in all inner lists of LL. """
    # your code here

LL = [[4],[5],[6],[7]]
print(count_ints(LL))  # prints {4: 1, 5: 1, 6: 1, 7: 1}  
         
LL = [[4,3,2,1],[5,4,5,6,7],[6,2,1],[7,3]]
print(count_ints(LL))  # prints {4: 2, 3: 2, 2: 2, 1: 2, 5: 2, 6: 2, 7: 2}           

LL = [[4,4],[4,4,4,4],[4,4,4],[4]]
print(count_ints(LL))  # prints {4: 10}           

Recursion 1 Fix the RECURSIVE function to meet the specification below:

def g(n):
    """ n is an int
    Returns the sum of digits in n """
    # fix this code
    if n == 1:
        return 1
    else:
        least_sig_dig = n%10
        return g(n/10)

Recursion 2 Fix the RECURSIVE function to meet the specification below:

def is_even(n):
    """ n is an int
    Returns True if n is even and False otherwise """
    # fix this code
    if n == 0:
        return True
    elif n == 1:
        return False
    else:
        return is_even(n-1)

Recursion 3 Implement a MEMOIZED and RECURSIVE function that meets the specification below:

def score_count(x, d):
    """ x is a positive int
        d is a dict
    Returns all the ways to make a score  of x by adding   
    1, 2, and/or 3 together. Order matters. """
    # your code here

# Examples:
print(score_count(1))  # prints 1
print(score_count(2))  # prints 2
print(score_count(3))  # prints 4
print(score_count(4))  # prints 7
print(score_count(7))  # prints 44
print(score_count(18)) # prints 35890

Recursion 4 Fix the RECURSIVE function to meet the specification below:

def h(n):
    """ n is an int
    Returns the sum of digits in n """
    # fix this code
    s = str(n)
    if len(s) == 0:
        return 0
    else:
        return int(s[0])+h(int(s[1:]))

Recursion 5 Implement a RECURSIVE function that meets the specification below:

def count_in(L, e):
    """ L is a list whose elements are either ints or lists, 
        and whose inner-lists are either ints or lists, etc.
        e is an int
    Returns how many times e occurs in L, and any inner-lists of L, etc.
    """
    # your code here

# Examples:
L = [4,7,9,1,9,3,9,4]
print(count_in(L, 9))   # prints 3
L = [4,7,9,1,9,3,9,4]
print(count_in(L, 0))   # prints 0
L = [4,[7,[9,1]],[1,[9,9,[9,8,[9]],3],9,4]]
print(count_in(L, 9))   # prints 6
L = [4,[7,[9,1]],[1,[9,9,[9,8,[9]],3],9,4]]
print(count_in(L, 0))   # prints 0

Recursion 6 Implement a RECURSIVE function that meets the specification below:

def sum_lengths(L):
    """ L is a list whose elements are either strs or lists, 
        and whose inner-lists are either strs or lists, etc.
    Returns the length of all strings in L and all inner-lists of L. """
    # your code here

# Example
L = ['a','b',['c','defg',['h',['ijk']]]]
print(sum_lengths(L))    # prints 11

Recursion 7 Implement a RECURSIVE function that meets the specification below:

def is_str_in(L, s):
    """ L is a list whose elements are either strs or lists, 
            and whose inner-lists are either strs or lists, etc.
        s is a string
    Returns True if s is in L or any of the inner-lists of L """
    # your code here

# Examples
L = ['a','b',['c','defg',['h',['ijk']]]]
print(is_str_in(L, 'd'))        # prints False
L = ['a','b',['c','defg',['h',['ijk']]]]
print(is_str_in(L, 'defgh'))    # prints False
L = ['a','b',['c','defg',['h',['ijk']]]]
print(is_str_in(L, 'h'))        # prints True
L = ['a','b',['c','defg',['h',['ijk']]]]
print(is_str_in(L, 'a'))        # prints True

OOP 1 Think about some other attributes of a book: data attributes and behaviors

We will represent a Book object. It's your turn to make some design decisions. Start with this code add more attributes and methods to customize our book object. The test cases here don't test anything beyond what is shown, so don't use them to test correctness of your code.

  1. Work in your IDE to make the design decisions for the Book class definition.
  2. Create a bunch of Book objects and run your methods on them to test your code.
  3. Paste your final customized Book class implementation here.

Be creative and play around with adding all sorts of new data attributes and methods you may want a book to have!

class Book(object):
    def __init__(self, title, author, pages):
        self.title = title
        self.author = author
        self.pages = pages
    def display_info(self):
        return f"{self.title} by {self.author} has {self.pages} pages."
    
book1 = Book("We Never Go Out Of Style", 'L. Crew', 100)        
book2 = Book("I Knew You Were Trouble", 'A. Half', 100)

OOP 2 Implement a class that meets the specification below:

class Rectangle(object):
    """ A class to represent a rectangle. """

    def __init__(self, width, height):
        """ width and height are ints """
        # your code here

    def compute_area(self):
        """ Returns the area of self """
        # your code here
    
    def compute_perimeter(self):
        """ Return the perimeter of self """
        # your code here
    
    def is_square(self):
        """ Returns True if the width equals the height, and False otherwise """
        # your code here

# Examples:
my_rectangle = Rectangle(10,5)
print(my_rectangle.compute_area())      # prints 50
print(my_rectangle.compute_perimeter()) # prints 30
print(my_rectangle.is_square())         # prints False

OOP 3 Implement a class that meets the specification below:

class UniqueItems(object):
    """ A group of items that contains NO DUPLICATES """
    def __init__(self, items):
        """ items is a list """
        # your code here

    def add_item(self, item):
        """ Adds items to self """
        # your code here

    def remove_item(self, item):
        """ Removes item from self """
        # your code here
        
    def get_items(self):
        """ Returns a list of items in self, in sorted order """
        # your code here

    def __str__(self):
        """ Returns a str representing the sorted group of items in self,
            separated by commas and then a space """    
        # your code here
            
# Examples
u1 = UniqueItems([4,6,2,4,6,4])
print(u1.get_items())   # prints [2, 4, 6]
u1.add_item(6)
print(u1.get_items())   # prints [2, 4, 6]
u1.add_item(0)
print(u1.get_items())   # prints [0, 2, 4, 6]
u1.remove_item(2)
print(u1.get_items())   # prints [0, 4, 6]
print(u1)               # prints 0, 4, 6

OOP 4 Implement a function that meets the specification below. DO NOT access data attributes directly. Only access methods.

def make_uniques(LL):
    """ LL is a list, whose elements are lists of ints
    Returns a UniqueItems object whose items are the union 
    of all elements in all lists of LL. """
    # your code here
       
# Examples     
L = [[3,2,1], [5,8], [2], [7,9]]    
u = make_uniques(L)
print(u.get_items())  # prints [1, 2, 3, 5, 7, 8, 9]

L = [[3,3,3], [3,3], [1]]    
u = make_uniques(L)
print(u.get_items())  # prints [1, 3]

OOP 5 Implement a class that meets the specification below:

class Todo(object):
    """ A Todo object has a name and a SORTED list of things to do """
    def __init__(self, name, items_list=[]):
        """ name is a string
            items_list is a list, by default empty
        Initializes as Todo object """
        # your code here
            
    def add_todo(self, item):
        """ Adds an item to self """
        # your code here
    
    def mark_off(self, item):
        """ Removes all instances of item from self """
        # your code here

    def get_name(self):
        """ Returns the name of self """
        # your code here
    
    def get_item_list(self):
        """ Returns a copy of self's sorted items """
        # your code here
    
    def __add__(self, other):
        """ other is a Todo object
        Combines Todo objects and returns a new Todo object (may have duplicates) whose:
        * name is self's name concatenated with 'AND' concatenated with other's name. 
                e.g. if self's name is My Stuff and other's name is Your Stuff, 
                the combined name is My Stuff AND Your Stuff
        * items are sorted in alphabetical order """
        # your code here
        
    def __str__(self):
        """ Returns all items in self, one on each line, sorted in alphabetical order. """
        # your code here
        
# Examples
grocery = Todo('To Buy')
grocery.add_todo('oranges')
grocery.add_todo('coffee')
grocery.add_todo('milk')
grocery.add_todo('pizza')
grocery.add_todo('coffee')
grocery.add_todo('coffee')
print(grocery)
print()
grocery.mark_off('coffee')
print(grocery)
print()
print(grocery.get_item_list())  # prints ['milk', 'oranges', 'pizza']
print(grocery.get_name())       # prints To Buy

stuff = Todo('Tasks')
stuff.add_todo('make friends')
stuff.add_todo('be optimistic')
stuff.add_todo('study for exams')
stuff.add_todo('sleep 8 hours')

stuffnthings = stuff+grocery
print(stuffnthings.get_name())      # prints Tasks AND To Buy
print(stuffnthings.get_item_list()) # prints ['be optimistic', 'make friends', 'milk', 'oranges', 'pizza', 'sleep 8 hours', 'study for exams']

OOP 6 Implement a function that meets the specification below. DO NOT access data attributes directly. Only access methods.

def checkoff(s1, s2):
    """ s1 and s2 are strings of letters and spaces separated by commas
           for ex: "To Visit,Spain,Brazil,Canada,Spain,Japan,India"
    Returns a Todo object whose 
    * name is the part of s1 until the first comma
    * things in the object are the parts in s1 between subsequent commas
      or the end of s1, without the things in s2 between subsequent commas
      or the end of s2
    """
    # your code here

# Examples
s1 = "To Visit,Spain,Brazil,Canada,Spain,Japan,India"
s2 = "Brazil,Spain,India,Japan"
visit = checkoff(s1, s2)
print(visit.get_item_list())

OOP 7 Implement a class that meets the specification below:

###########################################################
#### GIVEN THIS QUADRILATERAL CLASS, DO NOT MODIFY ########
####           click to reveal           ##################
###########################################################
class Quadrilateral(object):
    """ A class to represent a quadrilateral by 4 points. """

    def __init__(self, topleft, topright, botright, botleft):
        """ topleft, topright, botleft, botright are tuples with 2 elements, 
            representing the 4 corners of a quadrilateral """
        # hidden implementation
    def get_coordinates(self):
        """ Returns a tuple with 4 elements, in this order: 
            * the top-left x,y coord
            * the top-right x,y coord
            * the bot-right x,y coord
            * the bot-left x,y coord """
        # hidden implementation
    def get_topleft_topright_length(self):
        """ Returns the length between the top-left and top-right coordinates """   
        # hidden implementation
    def get_topright_botright_length(self):
        """ Returns the length between the top-right and bottom-right coordinates """        
        # hidden implementation
    def get_botright_botleft_length(self):
        """ Returns the length between the bottom-right and bottom-left coordinates """        
        # hidden implementation
    def get_botleft_topleft_length(self):
        """ Returns the length between the bottom-left and top-left coordinates """        
        # hidden implementation
    def compute_area(self):
        """ Returns the area of self """
        # hidden implementation
    def compute_perimeter(self):
        """ Return the perimeter of self """
        # hidden implementation
#####################################################
# Implement this class, a subclass of Quadrilateral
##### VERSION 1 #####################################

class Rectangle(Quadrilateral):
    """ A class to represent a rectangle. """

    def __init__(self, topleft, topright, botright, botleft):
        """ topleft, topright, botleft, botright are tuples with 2 elements, 
            representing the 4 corners of a rectangle 
        Asserts that the points form a rectangle. """
        # your code here

    def get_width_and_height(self):
        """ Retruns a tuple with the first element representing
        the width and the second elements representing the height """
        # your code here

# Examples
my_rectangle = Rectangle((1,6), (11,6), (11,1), (1,1))
print(my_rectangle.compute_area())      # prints 50
print(my_rectangle.compute_perimeter()) # prints 30
print(my_rectangle.get_width_and_height())  # prints (10.0, 5.0)
# your_rectangle = Rectangle((1,8), (11,6), (1,1), (11,1))  # uncomment to see AssertionError

OOP 8 Implement a class that meets the specification below:

###########################################################
#### GIVEN THIS QUADRILATERAL CLASS, DO NOT MODIFY ########
####           click to reveal           ##################
###########################################################
class Quadrilateral(object):
    """ A class to represent a quadrilateral by 4 points. """

    def __init__(self, topleft, topright, botright, botleft):
        """ topleft, topright, botleft, botright are tuples with 2 elements, 
            representing the 4 corners of a quadrilateral """
        # hidden implementation
    def get_coordinates(self):
        """ Returns a tuple with 4 elements, in this order: 
            * the top-left x,y coord
            * the top-right x,y coord
            * the bot-right x,y coord
            * the bot-left x,y coord """
        # hidden implementation
    def get_topleft_topright_length(self):
        """ Returns the length between the top-left and top-right coordinates """   
        # hidden implementation
    def get_topright_botright_length(self):
        """ Returns the length between the top-right and bottom-right coordinates """        
        # hidden implementation
    def get_botright_botleft_length(self):
        """ Returns the length between the bottom-right and bottom-left coordinates """        
        # hidden implementation
    def get_botleft_topleft_length(self):
        """ Returns the length between the bottom-left and top-left coordinates """        
        # hidden implementation
    def compute_area(self):
        """ Returns the area of self """
        # hidden implementation
    def compute_perimeter(self):
        """ Return the perimeter of self """
        # hidden implementation
#####################################################
# Implement this class, a subclass of Quadrilateral
##### VERSION 2 #####################################

class Rectangle(Quadrilateral):
    """ A class to represent a rectangle centered on the origin. """

    def __init__(self, width, height):
        """ width and height are positive, even ints """
        # your code here
    
    def get_width_and_height(self):
        """ Retruns a tuple with the first element representing
        the width and the second elements representing the height """
        # your code here

# Examples
my_rectangle = Rectangle(10, 5)
print(my_rectangle.compute_area())      # prints 50
print(my_rectangle.compute_perimeter()) # prints 30
print(my_rectangle.get_width_and_height())  # prints (10.0, 5.0)

OOP 9 Implement a class that meets the specification below. DO NOT access data attributes directly. Only access methods.

###########################################################
#### GIVEN THIS QUADRILATERAL CLASS, DO NOT MODIFY ########
####           click to reveal           ##################
###########################################################
class Quadrilateral(object):
    """ A class to represent a quadrilateral by 4 points. """

    def __init__(self, topleft, topright, botright, botleft):
        """ topleft, topright, botleft, botright are tuples with 2 elements, 
            representing the 4 corners of a quadrilateral """
        # hidden implementation
    def get_coordinates(self):
        """ Returns a tuple with 4 elements, in this order: 
            * the top-left x,y coord
            * the top-right x,y coord
            * the bot-right x,y coord
            * the bot-left x,y coord """
        # hidden implementation
    def get_topleft_topright_length(self):
        """ Returns the length between the top-left and top-right coordinates """   
        # hidden implementation
    def get_topright_botright_length(self):
        """ Returns the length between the top-right and bottom-right coordinates """        
        # hidden implementation
    def get_botright_botleft_length(self):
        """ Returns the length between the bottom-right and bottom-left coordinates """        
        # hidden implementation
    def get_botleft_topleft_length(self):
        """ Returns the length between the bottom-left and top-left coordinates """        
        # hidden implementation
    def compute_area(self):
        """ Returns the area of self """
        # hidden implementation
    def compute_perimeter(self):
        """ Return the perimeter of self """
        # hidden implementation

######################################################
#### GIVEN THIS RECTANGLE CLASS, DO NOT MODIFY #######
##########            click to reveal           ######
######################################################
class Rectangle(Quadrilateral):
    """ A class to represent a rectangle centered on the origin. """

    def __init__(self, width, height):
        """ width and height are positive, even ints """
        # hidden implementation
    def get_width_and_height(self):
        """ Retruns a tuple with the first element representing
        the width and the second elements representing the height """
        # hidden implementation
#####################################################
# Implement this class, a subclass of Rectangle
#####################################################

class Square(Rectangle):
    """ A class to represent a square centered on the origin. """
    
    def __init__(self, side):
        """ side is a positive int """
        # your code here
        
    def get_diagonal_len(self):
        """ Returns the length of the diagonal """
        # your code here
    
# Examples
my_square = Square(27)
print(my_square.compute_area()) # expected: 729
print(my_square.compute_perimeter()) # expected: 108
print(my_square.get_diagonal_len()) # expected: 38.18377
/