CPSC120
Fundamentals of Computer Science

Activity 18

Chained Conditionals

Grade Conversion

Create the function convert_grade(numeric_grade: float) -> str that converts numeric grades to letter grades. The function has one parameter numeric_grade that is a number in the range [0, 100] that represents a student's grade. The function should return a string the equivalent letter grade as a string, either 'A', 'B', 'C', 'D', or 'F'. Do not use any logical operators for this exercise Use the following scale for your conversions.

A [90, 100]
B [80, 90)
C [70, 80)
D [60, 70)
F [0, 60)

Valid inputs to the function are in the range of [0, 100]. The function should use an assert statement to produce an error if the input is outside of this range.

Test Cases

import test

def convert_grade(numeric_grade: float) -> str:
    # Put your code here

def main() -> None:
    test.equal(convert_grade(100), "A")
    test.equal(convert_grade(90), "A")
    test.equal(convert_grade(89), "B")
    test.equal(convert_grade(80), "B")
    test.equal(convert_grade(79), "C")
    test.equal(convert_grade(70), "C")
    test.equal(convert_grade(69), "D")
    test.equal(convert_grade(60), "D")
    test.equal(convert_grade(59), "F")
    test.equal(convert_grade(0), "F")
    return None

main()

Leap Year

We have leap years added to our calendar because they do not take into account the fact that the Earth actually takes (about) 365.25 days to revolve once around the sun. While it sounds like this should be an easy thing to account for, there's actually some fairly complex math involved in dealing with this inconsistency.

Details

Write the Python function is_leap_year(year: int) -> bool that determines whether a year is a leap year. The function should return True if year is a leap year and False otherwise.

A leap year occurs almost every 4 years. All leap years are divisible by 4, but not all years divisible by 4 are leap years. A year is a leap year if it is divisible by 4, unless it is divisible by 100 and it is not divisible by 400.

Negative years don't exist in the Gregorian calendar, so the function should use an assert statement to produce an error if the input year is negative.

Test Cases

import test

def is_leap_year(year: int) -> bool:
    # Put your code here

def main() -> None:
    test.equal(is_leap_year(1700), False)
    test.equal(is_leap_year(1800), False)
    test.equal(is_leap_year(1900), False)
    test.equal(is_leap_year(2000), True)
    test.equal(is_leap_year(2020), True)
    test.equal(is_leap_year(2021), False)
    return None

main()

Hint

  • The rule for determining if a year is a leap-year is tricky. Another way to phrase the rule is:

    1. Every year that is divisible by 400 is a leap year.
    2. Every year that is divisible by 100 is not a leap year, except for those years covered by the above rule.
    3. Every year that is divisible by 4 is a leap year, except for those years covered by the above rules.
    4. Every year is not a leap year, except for those years covered by the above rules.
  • You can use the % (mod) operator to test divisibility. If year % 4 is 0, then the year is divisible by 4.

  • Don't forget that you can use your logical operators to reduce the code’s complexity.

Challenge

Another approach to testing is exhaustive enumeration. There have been 2019 years since the beginning of the common era. Write code that checks all of the years since 0 A.D. Compute the total number of leap years in that time frame.

Date Validation

Writing programs with dates and time is notoriously hard. We also want to create programs that don't crash. So we need to develop programs that verify if the user enters a valid date. For example, what happens when a user enters a birthday of January 32nd?

Details

Write the Python function is_valid_date(day: int, month: int, year: int) -> bool that determines whether a date is valid. The parameters day, month, and year are all integers that specify a date. For example, the day February 5th 2036 is day 5, month 2, and year 2036. The function should return True if the date is valid and False otherwise.

Test Cases

import test

def is_valid_date(day: int, month: int, year: int) -> bool:
    # Put your code here

def main() -> None:
    test.equal(is_valid_date(29, 2, 2020), True)
    test.equal(is_valid_date(30, 2, 2020), False)
    test.equal(is_valid_date(28, 2, 2021), True)
    test.equal(is_valid_date(29, 2, 2021), False)
    test.equal(is_valid_date(1, 1, 2021), True)
    test.equal(is_valid_date(0, 1, 2021), False)
    test.equal(is_valid_date(1, 12, 2021), True)
    test.equal(is_valid_date(1, 13, 2021), False)
    test.equal(is_valid_date(1, 0, 2021), False)
    test.equal(is_valid_date(1, 1, 0), False)
    return None

main()

Hint

  • Validating a date can be broken into three steps, validate the day, validate the month, and validate the year. If all three are valid, the function should return True.

  • Validating the year and month can be done by testing if the year and month are inside of valid ranges. The year should be positive, and the month should be between 1 and 12.

  • Validating the day is requires testing if it is in a valid range. But the day range depends on the month. To make this easier, create an additional function, days_in_month(month: int, year: int) -> int that returns the number of days in a month. Remember:

    30 days hath September, April, June, and November
    All the rest have 31
    Except for February, the only one.

    February has either 28 or 29 days, depending on whether it is a leap year. Hint: use the is_leap_year function you wrote to help with this. Test this function before using it in the is_valid_date function.

Challenge

Write an additional function validate_date_time(month: int, day: int, year: int, hours: int, minutes: int) -> bool. The function should validate the date and the time specified. Assume the time is specified as two integers, and their values should be in the ranges [0, 12] and [0, 60].