Functions and Booleans
General Information
Submitting to the Auto-Grader
For auto-grading homework assignments in the course, we use Gradescope.
General Submission Info
When submitting files to Gradescope, you need to submit all the files you want graded at once.
You can do this in several ways:
- Select all files you want to submit and drag and drop them in the submission area when prompted.
- Browse your files when prompted by Gradescope and select all files you want to submit.
- Directly compress all the files you want to submit into a zip file (zip file name does not matter), and submit that zip file via drag-and-drop or browsing for it.
- Compress a folder containing the files you want to submit into a zip file (zip file name does not matter), and submit that zip file via drag-and-drop or browsing for it.
Gradecope will look for files with specific names, and those names are case-sensitive.
So if in the instructions we ask for a file named hello.py
,
then Gradescope will not recognize Hello.py
, hello.txt
, or hello.py.txt
.
Group Submissions
When a group of people is submitting an assignment, only one person should submit the solution.
They should then add the other members to that submission. On the Gradescope page for a submission there should be a "+ Add Group Member" button by the name in the upper-right.
This is important because if multiple people submit, our similarity checker will see identical submissions and flag that.
Unlimited attempts
You have unlimited attempts for our auto-graded assignments.
This means that you should submit early and often in order to be confident that code you are writing as you go passes all of our tests.
Academic Honesty
All work that is completed in this assignment is your own group's. You may talk to other students about the problems you are to solve, however, you may not share code in any way, except with your partner(s). What you submit must be your own group's work.
You may not use any code that is posted on the internet. If you are not sure it is in your best interest to contact the course staff. We will be using software that will compare your code to other students in the course as well as online resources. It is very easy for us to detect similar submissions and will result in a failure for the exercise or possibly a failure for the course. Please, do not do this. It is important to be academically honest and submit your work only. Please review the UMass Academic Honesty Policy and Procedures so you are aware of what this means.
Copying partial or whole solutions, obtained from other students or elsewhere, is academic dishonesty. Do not share your code with your classmates, and do not use your classmates' code. If you are confused about what constitutes academic dishonesty you should re-read the course policies. We assume you have read the course policies in detail and by submitting this project you have provided your virtual signature in agreement with these policies.
About
The aim of this homework assignment is to practice writing functions and working with booleans.
As our skillset continues to expand, you should keep in mind that programming is a fairly cumulative process and as such you would want to refresh concepts introduced so far to succeed in this assignment.
You may find this guide on functions useful as a reference.
Learning Objectives
- Practice defining functions.
- Practice function compositions.
- Practice boolean operations.
- Sanity check code using assert.
Estimated Size
This assignment requires you to implement 5 Python files.
- Each file will have 4 to 6 functions to implement.
- Each function can be reasonably implemented in 1 - 5 lines of code.
- Many functions have simple computations, similar to the first assignment.
- Some functions require you to use other functions implemented by you in the same file.
Assignment
0. Setup
Make a folder on your computer and open it in VSCode.
You must create five files in this folder. Make sure that you do not rename any of these files.
logic.py
fun_math.py
units.py
lines.py
quadratic.py
Remember that for every file you need to have comments indicating the authors at the, for example:
# Authors : Jared Yeager, Tim Richards
# Emails : jyeager@cs.umass.edu, richards@cs.umass.edu
# Spire IDs : 31415926, 27182818
The # Author
/# Authors
, # Email
/# Emails
, and # Spire ID
/# Spire IDs
are the only really necesary formating detail.
Some copying and pasting here will save you some time and sanity.
Note that these details are necessary for the autograder to recognize your solution.
1. Implement logic.py
This problem is a gentle introduction to boolean algebra, a branch of algebra in which computations are expressed in terms of True
and False
instead of numbers.
Boolean logic is a key ingredient in all programming languages. Remember that at the most basic level, a computer is a machine that can understand only two states: ON (True)
and OFF(False)
. Therefore, boolean algebra can be used to represent computations.
Similar to addition, subtraction, multiplication and division, boolean algebra has its own set of operations. This problem invites you to explore these operations and implement them. The three most fundamental boolean operations that you will need to use in this assignment are described below:
and
: Given two booleansA
andB
,A and B
isTrue
if and only if bothA
andB
areTrue
andFalse
otherwise. The truth table forand
is described below for your reference.A B A and B True True True True False False False True False False False False or
: Given two booleansA
andB
,A or B
isTrue
if either or both ofA
andB
areTrue
andFalse
only when bothA
andB
areFalse
. The truth table foror
is described below for your reference.A B A or B True True True True False True False True True False False False not
: Given a booleanA
,not A
isTrue
ifA
isFalse
andFalse
ifA
isTrue
. The truth table fornot
is described below for your reference.A Not A True False False False
If you revisit Lecture 5, you will notice that Python comes with and
, or
and not
operators. In fact, these are all what you really need for this problem!
There are several other complex boolean operations in boolean algebra. Interestingly, many of those operations can be constructed using and
, or
and not
. In this problem, we provide to you descriptions of certain boolean operations. Your task is to implement the specified boolean operations using any combination of and
, or
and not
, using one or more of these operations.
1a. Implement NAND (1 point)
NAND
is an operation that takes as input two booleans A
and B
and returns False
only if both A
and B
are True
. The truth table for NAND
is described below for your reference.
A | B | A nand B |
---|---|---|
True | True | False |
True | False | True |
False | True | True |
False | False | True |
Your task is to implement a function with the following signature:
def nand(a:bool, b:bool) -> bool
This function should take as input two booleans a
and b
and return the value of a nand b
.
Example:
nand(True, True) # This should return False
nand(False, True) # This should return True
1b. Implement IMPLIES (1 point)
Implication
is an operation that takes as input two booleans A
and B
and returns False
only when A
is True
and B
is False
and False
otherwise. The truth table for IMPLIES
is described below for your reference.
A | B | A implies B |
---|---|---|
True | True | True |
True | False | False |
False | True | True |
False | False | True |
Your task is to implement a function with the following signature:
def implies(a:bool, b:bool) -> bool
This function should take as input two booleans a
and b
and return the value of a implies b
.
Example:
implies(True, True) # This should return True
implies(True, False) # This should return False
1c. Implement IFF (1 point)
If and only if (Iff)
is an operation that takes as input two booleans A
and B
and returns True
only when A
and B
are either both True
or both False
and False
otherwise. The truth table for IFF
is described below for your reference.
A | B | A iff B |
---|---|---|
True | True | True |
True | False | False |
False | True | False |
False | False | True |
Your task is to implement a function with the following signature:
def iff(a:bool, b:bool) -> bool
This function should take as input two booleans a
and b
and return the value of a iff b
.
Example:
iff(True, True) # This should return True
iff(True, False) # This should return False
1d. Implement XOR (1 point)
Exclusive or (xor)
is an operation that takes as input two booleans A
and B
and returns False
when A
and B
are either both True
or both False
and True
otherwise. The truth table for XOR
is described below for your reference.
A | B | A xor B |
---|---|---|
True | True | False |
True | False | True |
False | True | True |
False | False | False |
Your task is to implement a function with the following signature:
def xor(a:bool, b:bool) -> bool
This function should take as input two booleans a
and b
and return the value of a xor b
.
Example:
xor(True, True) # This should return False
xor(True, False) # This should return True
2. Implement fun_math.py
In this problem, you will use functions to perform some simple mathematical computations. Any mathematical background or information that you may need is provided to you.
2a. Generate Cullen Numbers (2 points)
Cullen numbers are integers of the form where is an integer.
Your task is to implement a function with the following signature:
def cullen(n:int) -> int
The function should take as input an integer n
and return the corresponding Cullen Number.
Example:
cullen(1) # This should return 3
cullen(5) # This should return 161
2b. Generate Woodall Numbers (2 points)
Woodall numbers are integers of the form where is an integer.
Your task is to implement a function with the following signature:
def woodall(n:int) -> int
The function should take as input an integer n
and return the corresponding Woodall Number.
Example:
woodall(1) # This should return 1
woodall(5) # This should return 159
2c. Generate Fermat Numbers (2 points)
Fermat Numbers are integers of the form where is an integer.
Your task is to implement a function with the following signature:
def fermat(n:int) -> int
The function should take as input an integer n
and return the corresponding Fermat Number.
Example:
fermat(1) # This should return 5
fermat(2) # This should return 17
2d. Divisibility (2 points)
An integer a
is said be divisible by another integer b
if a
when divided by b
leaves no remainder. For instance, is divisible by but not by .
Your task is to implement a function with the following signature:
def divides_evenly(dividend:int, divisor:int) -> bool
The function should take as input two integers, the dividend
and the divisor
and returns whether the dividend
is divisible by the divisor
or not.
Example:
divides_evenly(10, 5) # This should return True
divides_evenly(10, 3) # This should return False
2e. Square Numbers (3 points)
A square number or perfect square is an integer that is the product of some integer with itself. For instance, is a square number since but is not.
Your task is to implement a function with the following signature:
def is_square(n:int) -> bool
The function should take as input an integer n
and returns whether the n
is a square number or not.
Example:
is_square(100) # This should return True
is_square(97) # This should return False
3. Implement units.py
Do you remember fluid unit conversions from middle school? If not, here's a quick recap:
1 US fluid ounce = 8 US fluid drams
1 US liquid quart = 32 US fluid ounces
1 US liquid gallon = 4 US liquid quarts
In this problem, you will implement functions to convert fluid quantities from one unit to another. All the conversion factors that you need have been specified above for your reference. This problem will demonstrate how you can use functions to break a complex problem into smaller sub-problems.
3a. Convert ounces to drams (2 points)
Your task is to implement a function with the following signature:
def ounces_to_drams(ounces:float) -> float
The function should take as input a float ounces
and return the corresponding quantity in drams
.
Example:
ounces_to_drams(8) # This should return 64
ounces_to_drams(2.5) # This should return 20
3b. Convert drams to ounces (2 points)
Your task is to implement a function with the following signature:
def drams_to_ounces(drams:float) -> float
The function should take as input a float drams
and return the corresponding quantity in ounces
.
Example:
drams_to_ounces(8) # This should return 1
drams_to_ounces(120.84) # This should return 15.105
3c. Convert quarts to ounces (2 points)
Your task is to implement a function with the following signature:
def quarts_to_ounces(quarts:float) -> float
The function should take as input a float quarts
and return the corresponding quantity in ounces
.
Example:
quarts_to_ounces(8) # This should return 256
quarts_to_ounces(2.5) # This should return 80
3d. Convert ounces to quarts (2 points)
Your task is to implement a function with the following signature:
def ounces_to_quarts(ounces:float) -> float
The function should take as input a float ounces
and return the corresponding quantity in quarts
.
Example:
ounces_to_quarts(64) # This should return 2
ounces_to_quarts(120.84) # This should return 3.77625
3e. Convert gallons to quarts (2 points)
Your task is to implement a function with the following signature:
def gallons_to_quarts(gallons:float) -> float
The function should take as input a float gallons
and return the corresponding quantity in quarts
.
Example:
gallons_to_quarts(64) # This should return 256
gallons_to_quarts(120.84) # This should return 483.36
3f. Convert quarts to gallons (2 points)
Your task is to implement a function with the following signature:
def quarts_to_gallons(quarts:float) -> float
The function should take as input a float quarts
and return the corresponding quantity in gallons
.
Example:
quarts_to_gallons(72) # This should return 18
quarts_to_gallons(120.84) # This should return 30.21
3g. Convert gallons to drams (2 points)
Your task is to implement a function with the following signature:
def gallons_to_drams(gallons:float) -> float
The function should take as input a float gallons
and return the corresponding quantity in drams
.
Example:
gallons_to_drams(12) # This should return 12288
gallons_to_drams(0.078) # This should return 79.872
Hint: Re-use the functions in 3a. - 3f.
3h. Convert drams to gallons (2 points)
Your task is to implement a function with the following signature:
def drams_to_gallons(drams:float) -> float
The function should take as input a float drams
and return the corresponding quantity in gallons
.
Example:
drams_to_gallons(250) # This should return 0.244141
drams_to_gallons(2999) # This should return 2.928711
Hint: Re-use the functions in 3a. - 3f.
4. Implement lines.py
In this problem, you will write functions to characterize lines and find the point of intersection of two lines if it exists. Let's consider a two-dimensional space. Given two lines:
three possibilities may arise:
- The two lines are the same i.e. they are coincident
- The two lines are parallel
- The two lines intersect at a unique point
All the necessary mathematical background you may need is provided below.
4a. Parallel Lines (3 points)
The two lines are parallel if and .
Your task is to implement a function with the following signature:
def are_parallel(m1:float, b1:float, m2:float, b2:float) -> bool
The function take as argument four floats m1
, m2
, b1
, b2
as described above and returns whether the two lines defined by the specified parameters are parallel or not.
Example:
are_parallel(0.75, 1, 0.75, 2) # This should return True
are_parallel(1, 2.5, 3.5, 2.5) # This should return False
4b. Coincident Lines (3 points)
The two lines are the same (coincident) if and .
Your task is to implement a function with the following signature:
def are_same(m1:float, b1:float, m2:float, b2:float) -> bool
The function take as argument four floats m1
, m2
, b1
, b2
as described above and returns whether the two lines defined by the specified parameters are coincident or not.
Example:
are_same(0.75, 1, 0.75, 1) # This should return True
are_same(0.75, 1, 0.75, 2) # This should return False
4c. Lines with Unique Intersection (3 points)
The two lines intersect at a unique point if .
Your task is to implement a function with the following signature:
def have_unique_intersection(m1:float, b1:float, m2:float, b2:float) -> bool
The function take as argument four floats m1
, m2
, b1
, b2
as described above and returns whether the two lines defined by the specified parameters intersect at a unique point or not.
Example:
have_unique_intersection(1, 2.5, 3.5, 2.5) # This should return True
have_unique_intersection(0.75, 2, 0.75, 4) # This should return False
have_unique_intersection(0.75, 2, 0.75, 2) # This should return False
4d. Intersecting Lines (3 points)
Two lines are said to intersect either if they have a unique intersection point or they are coincident.
Your task is to implement a function with the following signature:
def have_intersection(m1:float, b1:float, m2:float, b2:float) -> bool
The function take as argument four floats m1
, m2
, b1
, b2
as described above and returns whether the two lines defined by the specified parameters intersect or not.
Example:
have_intersection(1, 2.5, 3.5, 2.5) # This should return True
have_intersection(0.75, 1, 0.75, 1) # This should return True
have_intersection(0.75, 2, 0.75, 4) # This should return False
4e. Point of intersection
For two lines that have a unique intersecting point, we can easily determine this point. Since we are working with lines in a two dimensional plane, this point is an ordered pair of the form .
Part I: Determining the coordinate (3 points)
A well established result states that .
Your task is to implement a function with the following signature:
def x_intersect(m1:float, b1:float, m2:float, b2:float) -> float
The function takes as arguments four floats m1
, m2
, b1
, b2
as described above and returns the x-coordinate of the point of intersection. The function should only return an output if the lines specified have a unique point of intersection, otherwise give an error.
Hint: For the error, use an assert
statement with one of the functions 4a. - 4d.
Example:
x_intersect(1, 2.5, 3.5, 2.5) # This should return 0
x_intersect(3.5, 2.5, 3.5, 7.5) # This should give an ERROR!
x_intersect(3.5, 2.5, 3.5, 2.5) # This should give an ERROR!
Part II: Determining the coordinate (3 points)
Notice that once we determine , we can use direct substitution into the equations of the lines to calculate . Therefore, given , we can calculate y as either of the following:
Your task is to implement a function with the following signature:
def y_intersect(m1:float, b1:float, m2:float, b2:float) -> float
The function takes as arguments four floats m1
, m2
, b1
, b2
as described above and returns the y-coordinate of the point of intersection. The function should evaluate using the two equations specified above, verify that both the equations yield the same value of and return an output if the lines specified have a unique point of intersection, otherwise give an error.
Hint: For the error, use an assert
statement with one of the functions 4a. - 4d.
Example:
y_intersect(1, 2.5, 3.5, 2.5) # This should return 2.5
y_intersect(3.5, 2.5, 3.5, 7.5) # This should give an ERROR!
y_intersect(3.5, 2.5, 3.5, 2.5) # This should give an ERROR!
5. Implement quadratic.py
In this problem, we revisit the problem of solving quadratic equations from Homework 1. You will be writing functions to characterize the solutions of quadratic equations in the standard form and find real solutions, if they exist.
5a. Determining the Discriminant (3 points)
The discriminant of a quadratic equation is the quantity . The discriminant determines the nature of roots of a quadratic equation.
Your task is to implement a function with the following signature:
def discriminant(a:float, b:float, c:float) -> float
The function takes as arguments three floats a
, b
, c
, as described above and returns the discriminant of the quadratic equation described by the specified parameters.
Example:
discriminant(6, 10, -1) # This should return 124
discriminant(1, -3, 4) # This should return -7
5b. Check for the existence of real roots (3 points)
A well known result in mathematics states that a quadratic equation has real roots if and only if the discriminant is strictly greater than 0 i.e. .
Your task is to implement a function with the following signature:
def has_real_root(a:float, b:float, c:float) -> bool
The function takes as arguments three floats a
, b
, c
, as described above and returns the if the quadratic equation described by the specified parameters has real roots or not.
Example:
has_real_root(6, 10, -1) # This should return True
has_real_root(1, -3, 4) # This should return False
Hint: Reuse 5a. to calculate the discriminant.
5c. Calculate a real root (3 points)
Using the discriminant, we can write the roots of the quadratic equation as and .
Your final task (Yay!) is to implement a function with the following signature:
def get_any_real_root(a:float, b:float, c:float) -> float
The function takes as arguments three floats a
, b
, c
, as described above and returns any one root of the the quadratic equation described by the specified parameters. It should return a root only if the equation specified by the parameters has real roots otherwise should give an error.
Hint: For the error, use an assert
statement with one of the functions 5a. - 5b.
Example:
get_any_real_root(1, -7, 10) # This should return 2 or 5
Grading Scale
Note that points may be obtained from anywhere, you do not need to try or complete work in any particular order (except where a function depends on another function).
1: Below Standards: 0-15 points
This is the number of points that demonstrates proficiency equivalent to completing logic.py
and fun_math.py
.
2: Approaching Standards: 16-31 points
This is the number of points that demonstrates proficiency equivalent to completing through units.py
.
3: Meeting Standards: 32-49 points
This is the number of points that demonstrates proficiency equivalent to completing through lines.py
.
4: Exceeding Standards: 50-58 points
This is the number of points that demonstrates proficiency equivalent to completing almost the entire assignment.