The exercise in Activity 04 that involved computing the area of a triangle involved a function with six arguments ($x$ and $y$ components of each vertex). With six arguments, the likelihood of a user passing arguments in the wrong order is high.
Use an appropriate data structure to develop a new version of the function with a simpler interface (the interface is the arguments that are passed to the function). Add appropriate checks inside your function to validate the input data.
In [1]:
def area(p0, p1, p2):
"Calculate the area of a triangle given three points coordinates in the format (x, y)"
# Check if all the points have two coordinates
if len(p0) == 2 and len(p1) == 2 and len(p2) == 2:
return abs((p0[0]*(p1[1]-p2[1]) + p1[0]*(p2[1]-p0[1]) + p2[0]*(p0[1]-p1[1])) / 2)
else:
return 'Insert the coordinates of three points in the format (x, y)'
# Test cases
print(area((0, 0), (1, 0), (0, 1))) # 0.5
print(area((0, 0), (5, 0), (0, 8))) # 20
print(area((0, 0), (5, 1, 0), (0, 8))) # Error message
For a simple (non-intersecting) polygon with $n$ vertices, $(x_0, y_0)$, $(x_1, y_1)$, . . , $(x_{n-1}, y_{n-1})$, the area $A$ is given by
$$ A = \left| \frac{1}{2} \sum_{i=0}^{n-1} \left(x_{i} y _{i+1} - x_{i+1} y_{i} \right) \right| $$and where $(x_n, y_n) = (x_0, y_0)$. The vertices should be ordered as you move around the polygon.
Write a function that computes the area of a simple polygon with an arbitrary number of vertices. Test your function for some simple shapes. Pay careful attention to the range of any loops.
In [3]:
def polygon_area(points):
"""Calculate the area of a simple polygon given a tuple of points in the format (x, y).
The points have to be ordered as you move around the polygon"""
# Initialize area to 0
area = 0
# For each point check the number of coordinates and add to the area
for i in range(len(points)):
if len(points[i]) == 2:
# Here I use modulo to restart from 0 to account for the term where i=n-1
area += points[i][0]*points[(i+1)%len(points)][1] - points[(i+1)%len(points)][0]*points[i][1]
else:
return 'The coordinates of the points should be in the format (x, y)'
return abs(area/2)
# Test cases
print(polygon_area(((0, 0), (1, 0), (0, 1)))) # triangle, area = 0.5
print(polygon_area(((0, 0), (1, 0), (1, 1), (0, 1)))) # square, area = 1
Write a function that uses list indexing to add two vectors of arbitrary length, and returns the new vector. Include a check that the vector sizes match, and print a warning message if there is a size mismatch. The more error information you provide, the easier it would be for someone using your function to debug their code.
Add some tests of your code.
Hint: You can create a list of zeros of length n by
z = [0]*n
In [5]:
def add_vec(x, y):
"Sum two vectors of arbitrary length"
# Check if the vectors have the same length
if len(x) == len(y):
# Initialize sum to zero
z = [0]*len(x)
# Add vectors element by element
for i in range(len(x)):
z[i] = x[i] + y[i]
return z
else:
return 'The two vectors must have the same length'
# Test cases
print(add_vec((1, 4), (2, -3)))
print(add_vec((1, 4), (2, -3, 1))) # Error message
print(add_vec((1, 4, -5, 9), (2, -3, 1, 7)))
Optional (advanced): Try writing a one-line version of this operation using list comprehension and the built-in function zip.
In [6]:
def add_vec2(x, y):
"Sum two vectors of arbitrary length using list comprehension"
# Check if the vectors have the same length
if len(x) == len(y):
# Create a new list summing the two vectors element-wise
return [a + b for a, b in zip(x, y)]
else:
return 'The two vectors must have the same size'
# Test cases
print(add_vec2((1, 4), (2, -3)))
print(add_vec2((1, 4), (2, -3, 1))) # Error message
print(add_vec2((1, 4, -5, 9), (2, -3, 1, 7)))
Create a dictionary that maps college names (the key) to college abbreviations for at least 5 colleges (you can find abbreviations at https://en.wikipedia.org/wiki/Colleges_of_the_University_of_Cambridge#Colleges). From the dictionary, produce and print
In [5]:
# Colleges dictionary
colleges = {'Christ\'s':'CHR'
, 'Churchill':'CHU'
, 'Clare':'CL'
, 'Clare Hall':'CLH'
, 'Corpus Christi':'CC'
, 'Darwin':'DAR'
, 'Downing':'DOW'
, 'Emmanuel':'EM'
, 'Fitzwilliam':'F'
, 'Girton':'G'
}
# Check the dictionary
print('Colleges dictionary:\n', colleges)
# Initialize empty abbreviation dictionary
colleges_abbr = {}
# Populate dictionary
for name, abbr in colleges.items():
colleges_abbr[abbr] = name
# Check the abbreviations dictionary
print('\nColleges\' abbreviations dictionary:\n', colleges_abbr)
# Sort the abbreviations
colleges_abbr_sorted = sorted(colleges_abbr)
# Check the sorted abbreviations
print('\nSorted colleges abbreviation:\n', colleges_abbr_sorted)
Optional extension: Create a dictionary that maps college names (the key) to dictionaries of:
For at least 5 colleges. Take the data from https://en.wikipedia.org/wiki/Colleges_of_the_University_of_Cambridge#Colleges. Using this dictionary,
In [6]:
# Colleges dictionary with additional info
colleges_ext = {'Christ\'s':{'abbreviation':'CHR', 'year':1505, 'students':541}
, 'Churchill':{'abbreviation':'CHU', 'year':1960, 'students':704}
, 'Clare':{'abbreviation':'CL', 'year':1326, 'students':655}
, 'Clare Hall':{'abbreviation':'CLH', 'year':1966, 'students':155}
, 'Corpus Christi':{'abbreviation':'CC', 'year':1352, 'students':467}
, 'Darwin':{'abbreviation':'DAR', 'year':1964, 'students':674}
, 'Downing':{'abbreviation':'DOW', 'year':1800, 'students':623}
, 'Emmanuel':{'abbreviation':'EM', 'year':1584, 'students':750}
, 'Fitzwilliam':{'abbreviation':'F', 'year':1869, 'students':688}
, 'Girton':{'abbreviation':'G', 'year':1869, 'students':677}
}
In [9]:
# Initialize the result
more_students = ''
# Initialize the variable that keeps track of the max number of students
n_students = 0
# Iterate over the colleges in the dict
for coll, data in colleges_ext.items():
# If the number of students of the current college is greater than n_students
# update n_students with the current number and more_students with the current college name
if data['students'] > n_students:
more_students, n_students = coll, data['students']
# Print the college with more_students
print('The college with more students is', more_students)
In [12]:
# Initialize the result
out = [0, '']
# Initialize the variable that keeps track of the oldest year found to an arbitrary large year
year = 2500
for coll, data in colleges_ext.items():
# If the year of foundation of the current college is lesser than year
# update year with the current number and out with the current college number of students and abbreviation
if data['year'] < year:
out, year = [data['students'], data['abbreviation']], data['year']
# Print the oldest college number of students and name
print('{} is the oldest college and it has {} students'.format(out[1], out[0]))