Home Practicum 1 Practicum 2 Practicum 3 Practicum 4 Practicum 5 Practicum 6 Practicum 7 Practicum 8 Practicum 9 Practicum 10

Welcome to DS2000 CS Practicum 2!

  1. Recap and clarifications of last week
  2. Intro to todays excercises
  3. Taking user input
  4. Parsing user input
  5. Unit conversions
  6. More math operations
  7. Additional exercise

Recap and clarifications of last week

Before we get to today's excercise, let's clarify three things that you found confusing last week.

0. Reminder on how to get started:

1. Shell and Editor. Look at the image below and compare it to what you see on your screen.

Remember to save the contents of the editor window, not the interpreter window!

2. Error messages displayed in shell. The image below will help you read and understand the error messages you see in the shell.

Do you see what the error is?

3. Error images displayed in the editor. The image below will help you read and understand the error messages you see in the editor.

The editor highlights the place where it ran into a problem. You will notice that it sometimes highlights a seemingly wrong place in the code: there's nothing wrong with my call to the function main()! If you're confused, remember that the error is always before the highlight, either in the same line or the line above. Do you see where the error in this code is?

The actual practicum of today

Today we're going to practice:

Specifically, we will implement conversion between units that describe amount of data, time, and data transfer speeds. At the end of the exercise we will have the code that can answer questions like: how long would it take to save an episode of a Netflix series for offline watching over home WiFi? How much would it cost to listen to an album on Spotify while roaming abroad?

I marked the graded parts with a dotted border, make sure your zipped submission has one .py file per excercise!

Taking user input

We ask the user for data using the input function, with the prompt as an argument, for example try running this code in the interpreter:
fav_show = input('What is your favorite show? ')
The user's response is now stored in a variable called fav_show. You can print it out on the screen using the print function with the fav_show variable as the argument:
print(fav_show)
You can also add your text or other variables to print in the same line and separate them with commas, like this:
print('Too bad', fav_show, 'is so underrated!')
Note that there are no apostrophes around fav_show when we pass it as an argument, unlike with the words 'Too bad'. Do you understand why? What happens when you run print('fav_show')? Why doesn't it print the name of the show you typed in?

Excercise 1.1

Use the main() function template to write a program that:

  1. asks the user for the title of the series they want to watch and the number of episodes.
  2. prints out the input variables in a readable way (i.e. not just as two values one after another but as a sentence about how many episodes of which series they will save for offline viewing).
'''
DS2000
Spring 2019
PR02 - bits and bytes
'''
def main():
	# ask the user about the title
	# ask the user about the number of episodes
	# print

main()

Save your answer as pr02_ex11.py, it will be a part of your today's submission.

Parsing user input

In python everything that the user enters is treated as text. If we expect a number, we must explicitely tell Python to treat the input as one. We can use float for this if we expect a fraction or int if we expect an integer. Run these two pieces of code and see how the output differs.

Multiplying a string

string = input('Give me an integer: ')
print('Your number times ten is: ', 10 * string)

Multiplying a number

string = input('Give me an integer: ')
number = int(string)
print('Your number times ten is: ', 10 * number)

Excercise 1.2

Save your pr02_ex11.py file as pr02_ex12.py. Now you have two identical files with different names. Modify the contents of pr02_ex12.py for this excercise.

Let's assume that one episode of the series is 1.5 GB (one gigabyte) of data. Let's extend the function from the previous excercise to estimate how much data in total the user will need to download. Now your function:

  1. asks the user for the title of the series they want to watch and the number of episodes
  2. converts the number of episodes input to a number
  3. calculates the total amount of data and saves it to total_data variable
  4. prints out the input variables in a readable way
  5. prints out the total amount of data in GB.

Save your answer as pr02_ex12.py, it will be a part of your today's submission.

Unit conversion and functions

Great, now we know how much data in gigabytes we will need to transfer. Internet connection speeds are expressed in megabits per second, Mbps. To answer how long it will take to download all this data, we have to first convert gigabytes to megabytes to megabits. Have a look at this:

Side story, 1 kilobyte was not always 1000 bytes, it used to be 1024 bytes instead. If you have extra time try googling and wrapping your head around the explanation....

Converting gigabytes to megabits is a two step process: first we convert gigabytes to megabytes, then we convert megabytes to megabits. A function that converts gigabytes to megabytes looks like this:

After defining it, we can run it by typing its name and providing the input argument, for example:
>>> def giga2mega(giga):
	mega = giga * 1000
	return mega
>>> giga2mega(1):
1000
>>> giga2mega(1.5):
1500.0

If we want to use it in the main() function (and we do!) we need to 'call' it and save it's output to a variable, like this:

def giga2mega(giga):
	mega = giga * 1000
	return mega

def main():
	amount_of_data_GB = float(input('How many gigabytes do you want to tranfer?'))
	amount_of_data_MB = giga2mega(amount_of_data_GB)
	print("That's", amount_of_data_MB, "megabytes!")

Excercise 1.3

Take the file from excercise 1.2 and save it as pr02_ex13.py. In the pr02_ex13.py file add the definition of our giga2mega function and a the bytes2bits function you need to write yourself (it's has the same structure as giga2mega but the variable names and the conversion calculation will be different. Then, extend your main() function so now it:

  1. asks the user for the title of the series they want to watch and the number of episodes
  2. converts the number of episodes input to a number
  3. calculates the total amount of data and saves it to total_data variable
  4. uses giga2mega to calculate the size of total_data in megabytes and prints it out.
  5. use the caculated size in megabytes and the bytes2bits function to calculate and print out the size of total_data in megabits
  6. prints out the input variables in a readable way
  7. prints out the total amount of data in GB.

'''
DS2000
Spring 2019
PR02 - bits and bytes
'''
def giga2mega(giga):
	mega = giga * 1000
	return mega

def bytes2bits(byte):
	# your code goes here (two lines)

def main():
	# your code from excercise 1.2 with the requested extensions goes here

main()

Save your answer as pr02_ex13.py, it will be a part of your today's submission.

As a last step, we combine the outputs of our two functions to convert gigabytes to megabits like this:

def gigabytes2megabits(gigabytes):
	megabytes = giga2mega(gigabytes) # converting the input in gigabytes to megabytes
	megabits = bytes2bits(megabytes) # converting the calculated number of megabytes to megabits
	return megabits

Excercise 1.4

Take the file from excercise 1.3 and save it as pr02_ex14.py. From now on, edit file pr02_ex14.py.

A function can take more than one argument. Write a function estimate_transfer_time that takes the amount of data to transfer in gigabytes and the connection speed in megabits per second and calculates the time in seconds necessary to download that amount of data. Extend your main function, so now it:

  1. asks the user for the title of the series they want to watch and the number of episodes.
  2. asks the user for their internet speed in Mbps
  3. converts the number of episodes input to a number
  4. calculates the total amount of data and saves it to total_data variable
  5. prints out the input variables in a readable way (i.e. not just as two numbers one ofter another but a nice sentence about how many episodes of which series they will save for offline viewing).
  6. prints out the total amount of data in GB.
  7. calculates and prints out the time in seconds necessary to transfer this amount of data on the specified connection

Note 1: so far we have been printing out user input by passing it as an argument to the print function. Here, we will pass it as an argument to the functions we wrote ourselves.
Note 2: If you're not sure what kind of speeds are reasonable: Internet providers in Boston offer speeds between 50 and 1000 Mbps, but in general your WiFi is not faster than 300 Mbps.

Your pr02_ex14.py should look something like:

'''
DS2000
Spring 2019
PR02 - bits and bytes
'''
def giga2mega(giga):
	mega = giga * 1000
	return mega

def bytes2bits(byte):
	# your code goes here (two lines)

def gigabytes2megabits(gigabytes):
	megabytes = giga2mega(gigabytes) # converting the input in gigabytes to megabytes
	megabits = bytes2bits(megabytes) # converting the calculated numbers of megabytes to megabits
	return megabits

def estimate_transfer_time(gigabytes, speed):
	# in this line convert gigabytes to megabits
	# in this line calculate time (in seconds) needed for transfer: 
	# 	speed is how many megabits can we transfer in one second. 
	# return the time estimate

def main():
	# your code from excercise 1.2 plus the requested extensions go here

main()

Save your answer as pr02_ex14.py, it will be a part of your today's submission.

Test case: use your code to calculate how long it would take to download 4 seasons of 13 episodes (52 episodes total, each 1.5 GB) on a 6 Mbps connection. Expected output: 104000. If your output is different, test each function one after another and try to find which one introduces the error.

A reminder on math operations

Last week we covered addition +, subtraction -, multiplication *, division /, full division //, and modulo (remainder) %.

Python has a library called math that will allow us to do more operations than these. To start using it, we need to import it. By convention, the import statements are placed on top of the file under the top comment, for example:

'''
DS2000
Spring 2019
PR02 - bits and bytes
'''
import math


def main():
	...

main()

This library implements plenty of operations, for example:

Excercise 1.5

Take the file from excercise 1.4 and save it as pr02_ex15.py. From now on, edit file pr02_ex15.py

Our function so far outputs the transfer time estimate in seconds - it's technically correct but might be difficult for a human to understand (how long is 104000.0 seconds?!). Write a function format_time(seconds) that takes in the number of seconds, rounds them up to the next full integer and then prints it in a human understandable format ("D days, H hours, M minutes, S seconds"). > Show hint

Make sure you import the math library in the beginning of your file. Then extend the function you developed previously, so that it:

  1. asks the user for the title of the series they want to watch and the number of episodes.
  2. asks the user for their internet speed in Mbps
  3. converts the number of episodes input to a number
  4. calculates the total amount of data and saves it to total_data variable
  5. prints out the input variables in a readable way (i.e. not just as two numbers one ofter another but a nice sentence about how many episodes of which series they will save for offline viewing).
  6. prints out the total amount of data in GB.
  7. calculates and prints out the time in seconds necessary to transfer this amount of data on the specified connection
  8. prints out the time in a human readable format. Remember to print using integers, for example "50 minute(s), 10 second(s)", rather than "50.0 minute(s), 10.0 second(s)".

Test case: use your code to calculate how long it would take to download 4 seasons of 13 episodes (52 episodes total) on a 2 Mbps connection. Expected output: 3 days, 14 hours, 40 minutes, and seconds. If your output is different, but your previous excercise worked, there's probably something wrong with the conversion.

Save your answer as pr02_ex15.py, it will be a part of your today's submission.

Excercise 2 (optional, but highly recommended)

Ex 2.1: Standard quality Spotify music streams at at bitrate of 160 kbps. Google Project Fi charges $10 per gigabyte. Write the code to answer the question: given the length of an album in hours and minutes, how much does it cost to stream it on Google Fi?

Ex 2.2: Mobile providers have different ways of calculating the cost of transmissions: some charge for each started KB, others for each started MB, and others for each started GB. Let's stick to the Google Fi rate of $10 per gigabyte. It corresponds to $0.01 per megabyte and $0.00001 per kilobyte. Extend the function from Ex 2.1 to report the three variants of cost that depend on the billing (hint: 600.1 MB gets charged as 1GB in GB-based billing, ast 601MB in MB based billing, and 600100 KB in KB based billing.

Save your answer as pr02_ex2.py, it's not mandatory, but it's good for you to know how to do it and good for me to know that you do.