Section #5: String Parsing, Drawing, & Main

Octber 24th, 2021

Written by Juliette Woodrow, Brahm Capoor, Nick Parlante, Anna Mistele, and John Dalloul

This week in section you will gain practice with string parsing, building lists, drawing, and the main function. These problems are meant to prepare you for homework 5. Solutions will be posted at the end of the week. There are more problems on this than we expect you to get through in section. Feel free to use the other ones as practice! If you have any questions, post on Ed or email Juliette!

Discussion about s[end]

We have gotten a lot of questions about why s[len(s)] causes an eror but using len(s) as the right index in a slice does not cause an error. For eaxmple:

          
>>> s = 'zz@python'
>>> at = s.find('@')
>>> end = len(s)
>>> s[end]
Traceback (most recent call last):
File "stdin", line 1, in module
IndexError: string index out of range
>>>
>>> s[at + 1:end]
'python'



What is going on here? There are two reasons why this happens.

Reason 1: UBNI

• Why does s[at + 1:end] work fine?
• Up To But Not Including - UBNI
• The char at the second index in a slice is not included in the slice
• So the fact that it’s one past the end is fine - it is not included
• This is the best reason, so focus on this one

Reason 2: Slice Garbage

• The other reason it works is a little sketchy
• It turns out, slices never raise an error about bad out of bounds index numbers
• They will work with any old garbage numbers
• If a number is too big, it is interpreted as “the end of the string”
• This does not mean you can stop caring about index numbers
• It just means the slice is not checking for you
• Our above solution is fine - the end index is managed accurately
• Going exactly one past the chars we want in all cases
        
>>> s = 'Python'
>>> len(s)
6
>>> s[2:5]
'tho'
>>> s[2:6]
'thon'
>>> s[2:46789]
'thon'



String Parsing and Lists

Parse Time

Implement a function, find_time(str) that takes in a string and, if it contains one, returns a time written in the string. Times will be of the format "XX:XX" and you don't need to include any AM or PM designations. For example, given the input string "Let's go to the movies at 09:30 tomorrow" your function should return "09:30". If there are no times in the string, return the empty string.

Parse out Hashtag

Implement a function, parse_out_hashtag(s), which takes in a string representing a single tweet and returns the hashtag within the tweet. For this problem, each tweet will have only one hashtag. A Hashtag can be defined as a string of 1 or more alphanumeric characters immadiately following a "#" character. A single hashtag ends at the first non-alphanumeric character following the '#'. For example, parse_out_hashtag('I am going to #wearmymask everywhere') would return 'wearmymask' and parse_out_hashtag('what is #ResX?') would return 'ResX'.

Here are some drawings for looping over the word following the '#' character (also known as an octothorpe).

Before:

After:

Find the Price

Implement a function, find_price(s, currency) that takes in a string and a currency symbol and returns an integer price if that is mentioned in the string s. We want to look through a line and find the place where a price is mentioned. You can assume that the currency symbol specified will only show up once in the line provided. To find the price, locate the currency symbol and then find all the digits AFTER the symbol (not all currencies have the symbol come first--think about how we could adjust our code if the symbol came last, instead). Stop reading once the last digit has been read. Return the price as an integer (without the currency symbol).

For example, find_price("Une cramique au chocolat coûte €3", "€") would return 3.

Exclaim Word

Implement a function, exclaim_word(s), which takes in a string and returns the exclamatory word in that string. Consider an exclamatory word the "word" substring of one or more alphabetic chars which are immediately to the left of the '!' in s. For example: exclaim_word('x123hello!cs106a') would return 'hello' and exclaim_word(32happy!day') would return 'happy'. If there are no exclamatory words, return the empty string.

Parse Info From Emails

1. Implement a function, parse_username(s),which takes in a string representing a single email address, and returns the username. The username is all alphabetic characters, digits, and '.' characters that come before the '@' character in the email address. For example: parse_username('maya.angelou1@gmail.com') would return 'maya.angelou1'
2. Implement a function, parse_hostname(s),which takes in a string representing a single email address, and returns the host name for that email address. The host name for a given email is all alphabetic characters, digits, and '.' characters that come after the '@' character in the email address. For example: parse_username('nick@cs.stanford.edu') would return 'cs.stanford.edu'

Parse Phone Number

Implement a function, parse_phone_number(s), which takes in a string that has a ten digit phone number somewhere in it and returns a list of the number in two parts: the area code and the rest of the number. The area code is the part of the phone number up until the first '-' character. The string can have text before or after the phone number. You may assume the following: that the only digits in the string will be part of the phone number. If there are any digits in the string, they will make up a complete phone number. If there is no phone number in the string, return an empty list. There may be '-' outside of the phone number. For example, parse_phone_number('Zoom is too much-call me instead: 212-225-9876') would return ['212', '2259876'], parse_phone_number('so call-me beep-me if you wanna reach me-at 650-555-5555 ') would return ['650', '5555555'], and parse_phone_number('The weekend is not long enough') would return [].

Drawing

Stanford Flag

You have been hired by Stanford to create a digital version of their new flag that they are desiging to welcome all students back to campus in the fall. They have given you the following description of the flag:

• The flag should have num_stripes Cardinal red and white horizontal stripes
• Each stripe takes up the entire width of the flag
• Each stripe has the same thickness
• The top stripe is red (with the alternating pattern, the bottom stripe should end up being red also)
• In the center of the flag (in front of the stripes) is a green square representing the new Town Square. The side length of the square as a ratio of the flag width is given by the constant SQUARE_SIDE_LENGTH_RATIO.
They want you to draw three of these flags on the canvas, one on the bottom half of the left third, one on the top half of the middle third, and one on the bottom half of the right third. In the parts of the canvas without the Stanford flag (top half of left third, bottom half of middle third, and top half of the right third), you will draw a different patch called a spider patch. In a spider patch, draw a series of lines distributed across the top edge of the figure, all terminating at the lower-right corner. The first line should start at the upper left corner, the last line should start at the upper right corner, with the other lines distributed evenly in between. Draw a green rectangle at the outer edge of each spider patch.

To accomplish this task, decompose into a function called draw_stanford_flag(canvas, left, top, width, height, num_stripes) where left should be the starting x value of the top left corner of this flag on the canvas and top should be the starting y value of the top left corner of this flag on the canvas.

You should also decompose into a function called draw_spider_patch(canvas, left, top, width, height, n) where left should be the starting x value of the top left corner of this spider patch on the canvas and top should be the starting y value of the top left corner of this spider patch on the canvas. n is the number of lines to draw and is guaranteed to be 2 or more.

Once you have that working, write a function called draw_flag(canvas, width, height, num_stripes, n) which draws the three flags at their locations specified above. Below is an example of what one call to draw_flag(canvas, 600, 600, 9, 4) should look like. You can ignore the black outline on parts of the image.

The main function

Not to do in section, just for more practice with writing your own main as this is a confusing topic

Your job is to write a program that emulates the 3 calculator functions shown below:

          
$python3 calculator.py -square 42 1764 # prints the square of the number passed in$ python3 calculator.py -exp 2 10
1024 # prints the first number raised to the power of the second number

\$ python3 calculator.py -add 1 2 3 4 5
15   # prints the sum of all the numbers typed in


You may assume that you are provided with a main function that takes as a parameter the list of arguments typed in the console, as below:
          
import sys

def main(args):