Homework 2: Dictionaries, If Statements, Functions, and Modules#

✅ Put your name here

#

CMSE 201 – Spring 2025#

CMSE Logo

Learning Goals#

Content Goals#

  • Use if/elif/else statements to implement a logical flow

  • Write and execute functions

  • Use the numpy module for math and data

  • Display data on plots using matplotlib

  • Utilize dictionaries to store data

Practice Goals#

  • Coding conventions

  • More advanced debugging

  • Using functions to build reusable/transferable code

  • Use visualization best practices to make informative plots

Assignment instructions#

Work through the following assignment, making sure to follow all the directions and answer all the questions.

This assignment is due at 11:59 pm on Friday, February 28th. It should be uploaded into the “Homework Assignments” submission folder for Homework #2. Submission instructions can be found at the end of the notebook.

REMINDER: You are responsible for following the citation guidelines for code that you did not write and/or is from outside CMSE 201 content. (From Day 4, edited slightly) Guidelines for Using Code You Didn’t Write: If you are using content to solve problems that has not been covered in our pre-class or in class assignments, you MUST cite your work. This includes any use of the resources reviewed in class (e.g. Stack Overflow, Google, LearnPython, etc.). If you use generative AI tools besides HiTA, you must indicate which tool you used (e.g. chatGPT, Co-Pilot, Claude, etc.) and what lines of code were produced by generative AI and which ones were produced by you. If you use only HiTA, you are expected to cite use of HiTA for each part of each problem you use it for. Failure to sufficiently cite your work may result in loss of points on the problem.

Academic integrity statement (2 Points)#

In the markdown cell below, paste your personal academic integrity statement. By including this statement, you are confirming that you are submitting this as your own work and not that of someone else.

Put your personal academic integrity statement here.


1. Dictionaries (10 Points)#

Python dictionaries are particularly useful for keeping track of pieces of information of different types.

Scenario: You are building a database of the two basic types of animals invertebrates and vertebrates. Each type contains basic animal classes. For example, vertebrates include fish, reptiles, etc., while invertebrates encompasses porifera, molluscs, etc. Scientists on a worldwide expedition will use your dictionary to categorize interesting wild life they may encounter during their journey. You will start the database by including 4 animal classes for each of the two animal types. For each animal class, you will list 3 examples to jumpstart the database.

✅  1.1 Task (5 Points)#

In the cell below, create a Python dictionary that includes entries for the two basic types of animals: (1) invertebrates and (2) vertebrates. Each of these two entries will contain as their values a list of 3 animal classes under the corresponding type. The dictionary must also contain a separate entry for each of the 6 animal classes that lists 3 example animals from these classes. Make sure that the entries are consistently typed within the dictionary. For example, if you use “fish” as an example of verbetrate, then you must use “fish” (not “Fish” or “fishies”) as the key of the entry that includes 3 examples of “fish.”

# Put your answer here

✅  1.2 Task (5 Points)#

You have made your animal database, now it’s time to use it!

In the cell below, write a print statement that describes the membership of one of the example animals to its class and type. The example animal and its class must be fetched from the dictionary, while the connecting statements such as “belongs to” can be typed manually into the print statement. For example, your output could be:

'[sparrow] belongs to the [birds] class which belongs to the vertebrate animal type.'

Note that the output inside [] must be obtained from the animal examples and classes in your dictionary, while the other strings in the output are typed manually in the print statement.

# put your answer here

2. Debugging a Function (10 Points)#

In the Tasks below, you will be asked to find, describe, and fix the bugs in each example.

In the cell below, you will find a function that takes in the mass of an object and a planet in the solar system and returns the weight of that ball as measured on the input planet.

The weight \(w\) is computed according to:

\(\begin{equation} w=m*g, \end{equation}\)

where \(m\) is the mass of the ball and \(g\) is the acceleration due to gravity on the planet.

Run the cell below because it will be used later. Take a few minutes to study the given function and read the comments that describe its inputs and outputs, as well as what the different lines of code do. Do not change the given code. You will have the chance to make edits in a different cell.

For reference, here are some examples for official sports ball masses.

# Do not edit this cell

# generate some initial data for testing
mass = 20   # kg
planet = 'earth'

def compute_weight(object_mass=1, planet='earth'):
    """
    Computes the weight of an object on a planet in the solar system

    Args:
        mass (float): The mass of the object
        planet (str): The planet name. 
        Must be be one of the options 'earth', 'jupiter', 'mars', 
        'mercury', 'mars', 'venus', 'saturn', 'neptune'.

    Returns:
        float: The weight of the object on the selected planet.
    """

    # create a message documenting the received input
    msg = "mass entered is {}. Planet entered is {}".format(object_mass, planet)

    # acceleration due to gravity for planets in the solar system in m/s^2
    # Source: https://aerospaceweb.org/question/astronomy/q0227.shtml
    g_earth = 9.81      # m/s^2, Earth
    g_jupiter = 24.79   # m/s^2, Jupiter
    g_mercury = 3.7     # m/s^2, Mercury
    g_mars = 3.73       # m/s^2, Mars
    g_venus = 8.87      # m/s^2, Venus
    g_saturn = 10.44    # m/s^2, Saturn
    g_neptune = 11.15   # m/s^2, Neptune
    # g_pluto = 0.62      # m/s^2, Pluto (not a planet any more :( )

    # set the gravity constant g to the correct value
    if planet == 'earth':
        g = g_earth
    elif planet == 'jupiter':
        g = g_jupiter
    elif planet == 'mercury':
        g = g_mercury
    elif planet == 'mars':
        g = g_mars
    elif planet == 'venus':
        g = g_venus
    elif planet == 'saturn':
        g = g_saturn
    elif planet == 'neptune':
        g = g_neptune
    elif planet == 'pluto':
        print('pluto is no longer a planet')
        # Input invalid. Exit the function without returning anything
        return
    else:
        print("Incorrect planet. Planet must be on of 'earth', 'jupiter', 'mars', 'mercury', 'mars', 'venus', 'saturn', or 'neptune'")
        # Input invalid. Exit the function without returning anything
        return
    
    # after setting the correct g, return the weight of the object
    return g * mass  

# Now let's play with some examples.

mass_ball = 0.45  # kg, mass of a soccer ball for example

# let's see what the mweight of the ball on Mars is
weight_ball = compute_weight(mass_ball, 'mars')

print(weight_ball)
74.6

✅  2.1 Task (1 Point)#

The cell below tests the compute_weight function by giving a test data composed of masses of sports balls in kilograms, as well as their weights on Earth (g_earth=9.81 m/s^2) and on Mars (g_mars=3.73 m/s^2). Note that \(g_{\text{earth}} > g_{\text{mars}}\). However, something seems to be wrong with the output.

Find any issues with the function that could be causing the incorrect output (remember that this is called “debugging”!).

Write any bugs that you found in the space below. You will fix bugs in the next question, don’t worry about doing that here!

import numpy as np

# define masses of sports balls
sports_balls = 10**-3 * np.array([2.7 ,  # kg, table tennis
             45.93,          # kg, golf
             145,            # kg, baseball
             410])            # kg, american football

# call the function and print weights on earth and on Mars
for ball in sports_balls:
    print("For mass = {:.2f} gram the weight on earth is {:.2f}, the weight on Mars is {:2f}".format(ball*10**3, compute_weight(ball, 'earth'), compute_weight(ball, 'mars')))
For mass = 2.70 gram the weight on earth is 196.20, the weight on Mars is 74.600000
For mass = 45.93 gram the weight on earth is 196.20, the weight on Mars is 74.600000
For mass = 145.00 gram the weight on earth is 196.20, the weight on Mars is 74.600000
For mass = 410.00 gram the weight on earth is 196.20, the weight on Mars is 74.600000

Put your answer for 2.1 here

✅  2.2 Task (4 Points)#

The function and the test code are copied into the cell below. Fix the bug you found, and run the test code.

import numpy as np

# Write your answer for 2.2 here by editing the function definition to fix the bug

# generate some initial data for testing  # 
mass = 20   # kg
planet = 'earth'

def compute_weight(object_mass=1, planet='earth'):
    """
    Computes the weight of an object on a planet in the solar system

    Args:
        mass (float): The mass of the object
        planet (str): The planet name. 
        Must be be one of the options 'earth', 'jupiter', 'mars', 
        'mercury', 'mars', 'venus', 'saturn', 'neptune'.

    Returns:
        float: The weight of the object on the selected planet.
    """

    # create a message documenting the received input
    msg = "mass entered is {}. Planet entered is {}".format(object_mass, planet)

    # acceleration due to gravity for planets in the solar system in m/s^2
    # Source: https://aerospaceweb.org/question/astronomy/q0227.shtml
    g_earth = 9.81      # m/s^2, Earth
    g_jupiter = 24.79   # m/s^2, Jupiter
    g_mercury = 3.7     # m/s^2, Mercury
    g_mars = 3.73       # m/s^2, Mars
    g_venus = 8.87      # m/s^2, Venus
    g_saturn = 10.44    # m/s^2, Saturn
    g_neptune = 11.15   # m/s^2, Neptune
    # g_pluto = 0.62      # m/s^2, Pluto (not a planet any more :( )

    # set the gravity constant g to the correct value
    if planet == 'earth':
        g = g_earth
    elif planet == 'jupiter':
        g = g_jupiter
    elif planet == 'mercury':
        g = g_mercury
    elif planet == 'mars':
        g = g_mars
    elif planet == 'venus':
        g = g_venus
    elif planet == 'saturn':
        g = g_saturn
    elif planet == 'neptune':
        g = g_neptune
    elif planet == 'pluto':
        print('pluto is no longer a planet')
        # Input invalid. Exit the function without returning anything
        return
    else:
        print("Incorrect planet. Planet must be on of 'earth', 'jupiter', 'mars', 'mercury', 'mars', 'venus', 'saturn', or 'neptune'")
        # Input invalid. Exit the function without returning anything
        return
    
    # after setting the correct g, return the weight of the object
    return g * mass  

#--------------------------------------Do not edit the code below-------------------------
# Testing the function
# define masses of sports balls
sports_balls = 10**-3 * np.array([2.7 ,  # kg, table tennis
             45.93,          # kg, golf
             145,            # kg, baseball
             410])            # kg, american football

# call the function and print weights on earth and on Mars
for ball in sports_balls:
    print("For mass = {:.2f} gram the weight on earth is {:.2f}, the weight on Mars is {:2f}".format(ball*10**3, compute_weight(ball, 'earth'), compute_weight(ball, 'mars')))

✅  2.3 Task (5 Points)#

In the code cell below, you have a function and a function call written for you. The function definition and/or the function call have some errors. You should do/answer the following:

  1. What should the output of the function call be?

  2. Write a plain English description of the bug. Search the web for unfamiliar error messages that you may receive when running the cell.

  3. Fix the function definition to remove bugs in the code cell below, and write down how you fixed it. Rerun the fixed code and make sure it gives the correct answer.

Put your answer for 2.3 here

# 2.3: Correct this function definition, and if needed, the function call

# A function to print MSU facts 
# Source: https://msu.edu/about/facts

def print_MSU_facts(ranking, student_population, area=5000, num_programs, student_teacher_ratio):
    string1 = "MSU is top {:d} university. The student population is {:d}, and its campus spans {:d} acres.".format(ranking, student_population, acres)
    string2 = "MSU has {:d}+ academic programs, and the student-teacher ratio is {}".format(num_programs, student_teacher_ratio)
    output_string =  string1 + string2

    print(output_string)


# Code to test the function. 
# MSU facts
public_uni_ranking = 30
num_students = 51316
acres = 5200
num_academic_prgrams = 400
student_faculty_ratio = '16:1'

# call the function
print_MSU_facts(public_uni_ranking, num_students, acres, num_academic_prgrams, student_faculty_ratio)

3. Functions, if/else, and Manufacturing! (10 Points)#

Different products require different surface finish. For example, consumer products are often expected to be smooth and shiny, while non-critical components of boilers can be rough. Certain industries have stricter requirements on surface finish and tolerance such as the aerospace industry. However, tighter tolerances and smoother surfaces come at the cost of increased production expenses and longer production times, see here.

Different production processes have limitations on the surface finish (measured in micrometers \(\mu m\) which is one millionth of a meter, or microns). For example, grinding can produce finer surfaces than turning or milling, see Fig. 15.8 here.

Rough ranges for surface finished produced by turning, milling, and grinding are:

  • Grinding: 0.025 \(\mu m\) – 3.2 \(\mu m\).

  • Turning: 0.40 \(\mu m\) – 3.2 \(\mu m\).

  • Milling: 0.40 \(\mu m\) – 25 \(\mu m\).

3.1 Selecting the right process for the job (3 points)#

Write a function that takes in the desired surface finish (in microns) and a manufacturing process as a string (‘turning’, ‘milling’, or ‘grinding’) and returns the Boolean “True” if the process can produce the required surface finish, and definition and “False” if it cannot.

Write your function in the cell below. Demonstrate that your function works using the test data given (surface_finish_test_data).

hint: You can test if a string is in a list using in. For example, 'cat' in ['dog', 'dolphin', 'cat'] will evaluate to True.

#----------------Run this cell before proceeding, but do no edit it.
# test surface finish (in microns)
surface_finish_test_data = [11.56,  0.78,  0.11,  0.96, 12.33,  0.84, 13.42,  0.91,  0.13, 10.45,  0.09,  0.10 ]  # in microns
# Write your Answer to 3.1 here:

3.2 Extending to the full Data Set (2 points)#

In the cell below, you will find a data set of tolerances for a part sent to a machine ship. Use your function on the list to count the number of processes that can only be completed using grinding or milling.

For example, your output may look like this:

Only grinding         Only Milling
        7                 11      
#-------------Do not edit--------------------
# full tolerance list (in microns) 

tolerance_list = [10.784816857410622,  0.6284242401927808,  12.93574564247594,  11.12811894288246, 13.776787616827054,  0.05107017590751106,  1.0127501750972174,  11.675191297747707,  12.062884629308304,  0.16496634293111634,  12.590085712262848,  10.731140195151154,  0.045065685183655425,  11.51518692397626,  1.0418687155577828,  0.8291592892965186,  7.952897208385569,  12.438588832472773,  0.6207610683948976,  0.7528983420257483,  0.5675155635817709,  11.22386987451356,  13.023339642701792,  0.7486025733524816, 10.764849744815045,  11.745369578976508,  0.08570630717518767,  12.998961097741738,  11.828738900408295,  10.628084496275532,  0.11179193052272116,  0.7695671658260386,  9.922153972105964,  0.1169692709084147,  12.333488049446247,  1.125792754642666,  0.15322878584568517,  0.6984137044479597,  12.936398835857625,  13.313918034830612,  0.10213420843315299,  0.7865597569325863,  10.767448516372495,  10.406624904442811, 11.947019067105021,  0.12922769019058133,  0.7322069947908311, 13.49528686072342,  0.390276218528216,  0.7601984858717746, 12.628682578472825,  9.922979277692916,  12.016473959072854,  0.7145423882679505,  11.61989597384899,  0.04726044396200514,  0.10246806193431096,  0.5687861054879977,  0.11909587262102675,  0.6425321468962494, 0.21135459672999074,  0.8072720616657312,  12.887720354117628,  1.096957977232816,  13.533965673378663,  12.520124338949184,  0.06944516368385857,  10.82389986128962, 0.3830359009796972,  12.914193636031131,  0.7491712279013639,  1.055959382080717,  0.10514992993691348,  13.014680685502269,  0.8617968557764097,  0.03508747608245555, 14.552068181509526,  0.8944577980093145, 11.902207248788262, 0.1304118893082896,  0.8452501664971064, 1.2140352228779538, 11.123010545594665, 0.0789648039157834, 1.0395050730726916, 12.797943860265375, 10.138084813390835, 0.9773702715191002, 0.02558748747438859, 0.5554200433485876, 11.705145465181145, 12.584623696693342, 10.932942228395497, 10.494983558601154, 0.17938653487971756]
# Write your code for 3.2 here:

3.3 Adding Complexity (3 points)#

What if you wanted to also take into account the length of time it takes to process the part? Run the cell below which has a function that estimates the time required to finish a part to a particular surface finish for each of the three basic process turning, milling, and grinding.

Write a new function that takes in a desired surface finish in microns and recommends a manufacturing process (turning, milling, or grinding) based on the process’s viability and ability to reach the desired surface finish in the least amount of time. Use the provided function estimate_time in your code to get the process time. You can choose to build from your previous code or start from scratch. You may find it helpful to make use of the test data again while you’re debugging your function!

Demonstrate that your code works by writing code that runs your function and determines the number of recommended operations for each of turning, milling, grinding in the full data set.

For example, your output may look like this:

Recommended Process Tally
Turning    Milling    Grinding
  37         49          21

Or your may choose to store the result in a dictionary and print it according to

{'turning': 37, 'milling': 49, 'grinding': 21}
#--------------Run this cell, but do not edit it----------------------------
# function to estimate the amount of time it would take to finish to a required tolerance using a specific machining process

def estimate_time(surface_finish, process):
    if process == 'turning':
        process_time = 8.030 * np.exp(1.031 * surface_finish)
    elif process == 'milling':
        process_time = 11.926 * np.exp(0.472 * surface_finish)
    elif process == 'grinding':
        process_time = 21.669 * np.exp(17.150 * surface_finish)
    else:
        print('incorrect input process')
        return
    
    # return the estiamted time rounded to 3 decimal places
    return np.round(process_time,3)
#-------------------Write your answer to 3.3 in the following cell---------
# write you answer to 3.3 here:

3.4 Reflections (2 points)#

✅  In the cell below, answer the following reflection questions:

  • In Part 3.3, did you use your function from 3.1 at all?

  • In what way? (Or if you didn’t, why not?)

  • This problem explored optimizing a manufacturing process using two variables: surface finish and process time. The process implicitly assumed a simple cut (i.e., a planar workpiece, no complicated geometry). Other possible considerations for finishing a part can introduce furether code complexity. Discuss the role functions can play in a more complicated scenario.

Put your answers here.

4. Numpy, matplotlib, and functions (18 Points)#

4.1 Making a plotting function (6 points)#

In CMSE 201, you will be making plots often. To help future you save time, you are going to write a function to use when you make plots!

✅  In cells below, write a function that takes in arrays of x and y values and displays a plot containing 4 subplots. Use plt.subplot() and include labels, line shapes, and colors to make the plots clear.

For this exercise, you will analyze global temperature trends for four different regions over time. The anomalies represent the difference between the observed temperature and a reference period’s average temperature. In 1900, the anomaly is -0.2°C, meaning global temperatures were 0.2°C cooler than the reference period. By 2020, the anomaly reaches 1.0°C, indicating that the world is about 1°C warmer compared to the baseline.

You must also test your function with the test data to receive full credit

# test data here
import numpy as np

years = np.array([1900, 1920, 1940, 1960, 1980, 2000, 2020])
global_temp = np.array([-0.2, -0.1, 0.0, 0.1, 0.4, 0.7, 1.0])
north_america_temp = np.array([-0.3, -0.2, 0.0, 0.2, 0.5, 0.8, 1.2])
europe_temp = np.array([-0.1, 0.0, 0.1, 0.3, 0.6, 0.9, 1.1])
asia_temp = np.array([-0.4, -0.3, -0.1, 0.2, 0.5, 0.9, 1.3])
# put your answer here

4.2 Using numpy arrays and functions for calculations (6 points)#

The temperature anomalies in different regions vary significantly over time. To better compare trends between regions, we can examine the percent change in temperature anomalies rather than absolute values.

We can calculate the percent change as follows:

\(\% \ difference = \frac{(final-initial)}{initial} \times 100\)

✅  In the cell below, write a function that takes in an array of temperature anomalies and calculates the percent change between each value. Demonstrate that your code works using one of the temperature anomaly arrays from the dataset.

# put your code here

4.3 Putting it all together (6 points)#

Along with this homework assignment, you will find a .csv file with some additional global temperature anomalies.

✅  In the cell(s) below, use the data from the file (and the functions you wrote) to calculate the percent difference and generate plots for plots for the regions in the CSV data file.

NOTE: This homework only includes up to Day 9 content which does not include the pandas module. Therefore, you should use the numpy module for this problem. It is designed to be simpler with numpy!

Remember that you can open up data files in Jupyter to see what the data looks like!

# put your work here

Congratulations, you’re done!#

Submit this assignment by uploading it to the course Desire2Learn web page. Go to the “Homework Assignments” section, find the submission folder link for Homework #2, and upload it there.

© Copyright 2025, The Department of Computational Mathematics, Science and Engineering at Michigan State University