Coursera: Week 5
Learn to Program: The Fundamentals
Week 5 – while loops, lists, mutability
This week I learned that, of course, I’ve been doing it all wrong. Guido van Rossum has decided that there’s no room for individuality, and Python script must be standardized. To quote from Intermezzo: Coding Style: “Name your classes and functions consistently; the convention is to use CamelCase for classes and lower_case_with_underscores for functions and methods.” To tell the truth, I was only using CamelCase because I find underscoring to be unattractive.
Only a couple of more weeks to go and I’m trying to put it all together. Since the first assignment involved modular arithmetic and 24-hour clocks, I thought I’d take the infamous ‘babysitter’ exercise and re-do it with a 12-hour clock. I guess I am a masochist.
Besides clock arithmetic it has Boolean expressions, if/elif statements, and exception handling. This is the one where I finally had to make friends with the debugger. I’m probably not done with it – it needs more input validation – but since there’s not a lot of code for clock arithmetic online (Python has its own built-in datetime module), I’m posting it anyway .
'''Ex 7. A babysitter charges $2.50 an hour until 9:00 PM when the rate drops to $1.75 an hour (the children are in bed). Write a program that accepts a starting time and ending time in hours and minutes and calculates the total babysitting bill. You may assume that the starting and ending times are in a single 24 hour period. Partial hours should be appropriately prorated.''' A = "Enter the time the sitter arrived in form HH:MM(specify AM or PM): " B = "Enter the time the sitter left in form HH:MM (specify AM or PM): " C = "Incorrect input. Please enter the time the sitter arrived \ in form HH:MM(specify AM or PM): " D = "Incorrect input. Please enter the time the sitter left \ in form HH:MM(specify AM or PM): " def calc_fee(start_time, end_time): ''' str -> float Return the sitters fee by converting the given starting time and ending time into number of hours (in fractions) where noon = 12:00PM and midnight = 12:00AM. >>> calc_fee('3:45PM', '8:30PM') "The babysitter's fee is: $11.88" >>> calc_fee('9:10PM','11:40PM') "The babysitter's fee is: $4.38" >>> calc_fee('11:20AM','11:10PM') "The babysitter's fee is: $27.96" >>> calc_fee('9:20AM','11:10AM') "The babysitter's fee is: $4.58" >>> calc_fee('10:20AM','8:15PM') "The babysitter's fee is: $24.79" >>> calc_fee('12:40PM','11:50PM') "The babysitter's fee is: $25.79" >>> calc_fee('10:17AM','10:17PM') "The babysitter's fee is: $29.04" >>> calc_fee('11:00AM','12:00AM') "The babysitter's fee is: $30.25" >>> calc_fee('11:00AM','12:00PM') "The babysitter's fee is: $2.50" >>> calc_fee('10:15AM','11:15PM') "The babysitter's fee is: $30.81" ''' #get AM or PM start_letter = start_time[-2] end_letter = end_time[-2] #get the hours and minutes start_hour = eval(start_time.split(':')[0]) end_hour = eval(end_time.split(':')[0]) #convert minutes to decimal part of hour start_minutes = float(start_time[-4:-2])/60 end_minutes = float(end_time[-4:-2])/60 #modulo operation time = ((end_hour + end_minutes) - (start_hour + start_minutes))%12 extra_hours = (end_hour + end_minutes) - 9.0 # if hours = 12 if time == 0: fee = 2.5*12.0 # if 0 < hours < 12 else: fee = 2.5*time #check if all hours after 9PM if start_letter == 'P' and start_hour >= 9.0 and start_hour !=12: fee = fee*0.7 #check if hours are more than 12 and end after 9PM elif end_hour != 12 and start_letter == 'A'\ and end_letter == 'P' and end_hour > start_hour and end_hour >= 9.0: time = time + 12 fee = fee*time - (0.75*(extra_hours)) #check if hours are more than 12 and end before 9PM elif start_letter == 'A' and end_letter == 'P'\ and end_hour != 12 and end_hour > start_hour: time = time + 12 fee = 2.5*time #check if hours end at midnight elif start_letter == 'A' and end_letter == 'A'\ and end_hour == 12 and end_hour > start_hour: time = time + 12 fee = fee*time - (0.75*(extra_hours)) #check for hours after 9PM elif end_hour !=12 and end_letter == 'P' and end_hour >= 9.0 : #subtract 0.75 cents/hour from fee after 9:00 PM fee = fee - (0.75*(extra_hours)) #check if hours ends at midnight elif end_hour == 12 and end_letter == 'A': fee = fee*time - (0.75*(extra_hours)) else: fee = fee return "The babysitter's fee is: $%.2f"% fee def check_input(): x = raw_input(A) y = raw_input(B) while True: try: print calc_fee(x,y) break except: x = raw_input(C) y = raw_input(D) def main(): check_input() main() if __name__ == "__main__": import doctest doctest.testmod()
Coursera: Week 4 – Is It For You?
Learn to Program: The Fundamentals
Week 4 – for loops, fancy string manipulation
This is the week I discovered I’m an addict. It was Friday, I had a long to-do list, but made the mistake of checking my e-mail. Oh, the lectures and assignment for the following week are already up. Fast-forward 6 hours and I had viewed the lectures, done the exercise and finished the assignment. I couldn’t stop. To be fair, I did take a detour on Boolean expressions for the assignment. I still don’t understand them (Zelle covers them in Chapter 8 of his book) but, apparently, they’re good for shortening those ridiculously long if/elif statements I’ve been posting. Anyway, I never did get out of the house.
So, are you the kind of person who can spend hours playing a game, until you get to the final level? Can’t wait for the next edition of “World of Puzzles” to arrive? Are you so bored you’re actually thinking of taking that refresher course in Calculus, but can’t remember the algebra? Try Python, instead. Programming is guaranteed to eat up as much time as you’ve got.
Coursera: Week 3 – Beginner Tips
Learn to Program: The Fundamentals
This is from the syllabus:
Week 1 – Installing Python, IDLE, mathematical expressions, variables, assignment statement, calling and defining functions, syntax and semantic errors
Week 2 – Strings, input/output, Booleans, function reuse, function design recipe, docstrings
Week 3 – import, namespaces, if statements
As you can see, it’s fairly rigorous. One of the reasons for taking the course is to get feedback from other students so I’ve been spending a lot of time on the Discussion Forums and many beginners don’t know what to make of it. So here’s my suggestions to anyone thinking of taking a MOOC to learn Python.
1) Most important – DOWNLOAD it. Don’t believe them when they tell you that it’s unnecessary. Python 2 or 3 (or both), it doesn’t matter. Check out the Beginner’s Guide for help. It’s week 3 at Coursera and people are dropping out, not because of the programming, but because IDLE is giving them fits. Look at it this way – even if you decide Python’s not for you, knowing how to use an editor is part of being computer literate.
2) Play with it. Many students are complaining that they can’t understand what they’re being asked, much less give the answers. Before you enroll in a course, consider doing exercises. There are loads of websites for beginners. Some people swear by CodeAcademy (Python 2) or Computer Science Circles (Python 3). Copy and paste the exercises into the editor instead of just doing them online. Get used to saving scripts, changing them around and running them. After a while, the weirdness wears off and it actually gets to be fun.
3) Coursework takes more time than you think. When the course description says 6-8 hours a week, it means 6-8 hours when you’re awake, when the phone isn’t ringing, when you’re not constantly being interrupted, etc. If you’re hard up for quality time, consider taking a course that doesn’t have hard deadlines for the quizzes and projects. I haven’t verified this, but I’m told that the courses at edX and Udacity are more go-at-your-own-pace.
Brush Up Your Quadratic Equations
Python Programming: Chapter 7, Exercise 18.
I’ve been playing with this all afternoon, trying to get the bugs out. Can’t really vouch for the math. It seems to work – at least it did five minutes ago – but when I try to shorten the code (all those mu equations), it weirds out, so I left it as is. If you want to try to “break” the program, as Zelle says, knock yourself out. I’m sure it won’t be that hard.
##18. Take a favorite programming problem from a previous chapter and add ##decisions and/or exception handling as required to make it truly robust ##(will not crash on any inputs) . Trade your program with a friend and have ##a contest to see who can "break" the other's program. #http://paulbourke.net/geometry/sphereline/ from math import sqrt from graphics import * ''' Points P (x,y) on a line defined by two points P1 (x1,y1,) and P2 (x2,y2) is described by: P = P1 + u (P2 - P1) or in each coordinate x = x1 + u (x2 - x1) = x1 + u*dx y = y1 + u (y2 - y1) = y1 + u*dy A circle centered at P3 (0,0) with radius r is described by: (x )**2 + (y )**2 = r2 Substituting the equation of the line into the circle gives a quadratic equation of the form a *u**2 + b* u + c = 0 where: a = (x2 - x1)**2 + (y2 - y1)**2 = dx**2 + dy**2 b = 2*[x1(x2 - x1) + y1(y2 - y1)] = 2*(dx*x1 + dy*y1) c = x1**2 + y1**2 - r**2 The exact behavior is determined by the expression within the square root b * b - 4 * a * c If this is less than 0 then the line does not intersect the sphere. If it equals 0 then the line is a tangent to the sphere intersecting it at one point, namely at u = -b/2a. If it is greater then 0 the line intersects the sphere at two points. ''' win = GraphWin("Draw a Line Through the Circle", 400,400) win.setCoords(-10.0,-10.0,10.0,10.0) win.setBackground('LemonChiffon') def circle(x,y,r,color_fill,color_outline): circle = Circle(Point(x,y), r) circle.setOutline(color_outline) circle.setFill(color_fill) circle.draw(win) def message(msg): message = Text(Point(0, -9), msg) message.setFill('blue') message.draw(win) def circle_line_intersection(X1,Y1, X2, Y2, r): line = Line(Point(X1,Y1), Point(X2,Y2)) line.setOutline('blue') line.setWidth('3') line.draw(win) dX = (X2 - X1) dY = (Y2 - Y1) a = dX**2 + dY**2 b = 2*((dX * X1) + (dY* Y1)) c = X1**2 + Y1**2 - r**2 e = X1**2 + Y1**2 f = X2**2 + Y2**2 i = b * b - 4.0 * a * c # discriminant u = (-X1*dX - Y1*dY)/a # both end points within the circle if e < r**2 and f < r**2: Txt = 'Line is within Circle at points \ (%02.f,%02.f),(%02.f,%02.f)'%(X1,Y1,X2,Y2 ) message(Txt) # disc is < 0 - line does not intersect elif i < 0.0 : Txt = 'Line does not intersect Circle.' message(Txt) # tangent line if disc = 0, elif i == 0: mu = -b /(2.0 * a) h = (X1 + mu * dX) v = (Y1 + mu * dY) Txt = 'Line is tangent to the Circle at point(%02.f,%02.f).'%(h,v) message(Txt) circle(h,v,0.15,'yellow','black') # first end point outside of circle and second end point within circle elif e >= r**2 and f <= r**2: mu = (-b - sqrt(i))/(2.0 * a) h = (X1 + mu * dX) v = (Y1 + mu * dY) Txt = 'Line intersects Circle at point (%02.f,%02.f).'%(h,v) message(Txt) circle(h,v,0.15,'yellow','black') # first end point within circle and second end point outside of circle elif e <= r**2 <= f: mu = (-b + sqrt(i)) / (2.0 * a) h = (X1 + mu * dX) v = (Y1 + mu * dY) Txt = 'Line intersects Circle at point (%02.f,%02.f).'%(h,v) message(Txt) circle(h,v,0.15,'yellow','black') # secant Line if disc > 0 and neither end point within circle elif i > 0.0 and 0.0 < u < 1.0: # first intersection mu = (-b - sqrt(i)) / (2.0 * a) h1 = (X1 + mu * dX) v1 = (Y1 + mu * dY) circle(h1,v1,0.15,'yellow','black') # second intersection mu = (-b + sqrt(i)) / (2.0 * a) h2 = (X1 + mu * (dX)) v2 = (Y1 + mu * (dY)) circle(h2,v2,0.15,'yellow','black') Txt = 'Line intersects Circle at points \ (%02.f,%02.f),(%02.f,%02.f)'%(h1,v1,h2,v2 ) message(Txt) def main(): instructions = Text(Point(0, 9), 'Click on two points to draw a horizontal line.') instructions.setFill('blue') instructions.draw(win) #center circle circle(0,0,5,'orange','green') #get the end points of the line p = win.getMouse() x1 = p.getX() y1 = p.getY() circle(x1,y1,0.15,'red','red') p2 = win.getMouse() x2 = p2.getX() y2 = p2.getY() circle(x2,y2,0.15,'red','red') circle_line_intersection(x1,y1,x2,y2, 5) instructions.setText ('Click anywhere to quit.') win.getMouse() win.close() if __name__ == '__main__': main()
Archery Scorer
Python Programming: Chapter 7, Exercise 16.
I used ten-band scoring, with the bull’s-eye worth 11 points. Again, the code could be shorter – but that’s not the purpose of the exercise.
'''16. Archery Scorer. Write a program that draws an archery target (see Programming Exercise 2 from Chapter 5) and allows the user to click five times to represent arrows shot at the target. Using five-band scoring, a bulls-eye (yellow) is worth 9 points and each successive ring is worth 2 fewer points down to 1 for white. The program should output a score for each click and keep track of a running sum for the entire series. ''' from graphics import * import math win = GraphWin("Archery Target", 500,500) win.setBackground('gold') win.setCoords(-250, -250, 250, 250) cen = Point(0,0) msg = Text(Point(0,230), 'Click to hit the target.') msg.setFill('blue') msg.draw(win) def score_text(): #put the score numbers on the target v = 190 z = 18 bullseye = Text(Point(0,0), 'x') bullseye.setSize(14) bullseye.draw(win) for i in range(1,11): score_number = Text(Point(0,v), i) score_number.setSize(z) score_number.setFill('blue') score_number.draw(win) v = v - 19 z -= 1 def hit_target(): #draw a circle where the user clicks and add to the count count = 0 for i in range(10): p = win.getMouse() x = p.getX() y = p.getY() p = Circle(Point(x,y),4) p.setFill('purple') p.draw(win) d = x**2 + y**2 string = 'You hit the target. Score is %s.' if d > 200**2: msg.setText(('You missed the target. Score is %s.' %count)) elif d <= 10**2: count += 11 msg.setText(('Congrats! You hit the bull's-eye. Score is %s.' %count)) elif d <= 29**2: count += 10 message = msg.setText((string %count)) elif d <= 48**2: count += 9 message = msg.setText((string %count)) elif d <= 67**2: count += 8 message = msg.setText((string %count)) elif d <= 86**2: count += 7 message = msg.setText((string %count)) elif d <= 105**2: count += 6 message = msg.setText((string %count)) elif d <= 124**2: count += 5 message = msg.setText((string %count)) elif d <= 143**2: count += 4 message = msg.setText((string %count)) elif d <= 162**2: count += 3 message = msg.setText((string %count)) elif d <= 181**2: count += 2 message = msg.setText((string %count)) elif d <= 200**2: count += 1 message = msg.setText((string %count)) msg.setText('Game over. Score is %s. Click anywhere to quit.' %count) win.getMouse() win.close() return count def main(): #draw the target rad = 200 color = ['white', 'black', 'cyan3', 'red', 'yellow'] for i in range(5): for j in range(2): c = Circle(cen, rad) c.setFill(color[i]) c.setOutline('gray') c.setWidth('2') c.draw(win) rad = (rad - 19) #draw the bull's-eye center = Circle(cen,10) center.setOutline('gray') center.setWidth('2') center.draw(win) score_text() hit_target() if __name__ == '__main__': main()
Does a Line Intersect the Circle?
Python Programming: Chapter 7, Exercise 14.
I usually post code for exercises that were either fun to do or required research or gave me a headache. This exercise was none of the above, but I’m posting it because I use it later on, for exercise 18.
##14. Do Programming Exercise 7 from Chapter 5, but add a decision ##to handle the case where the line does not intersect the circle. from graphics import * import math win = GraphWin("Draw a Horizontal Line", 400,400) win.setCoords(-10.0,-10.0,10.0,10.0) win.setBackground('LemonChiffon') def message(msg): message = Text(Point(0, -9), msg) message.setFill('blue') message.draw(win) def main(): instructions = Text(Point(0, 9), 'Click on two points to draw a horizontal line.') instructions.setFill('blue') instructions.draw(win) ball = Circle(Point(0,0), 5) #radius is 5 from center 0 ball.setOutline('green') ball.setWidth('2') ball.setFill('orange') ball.draw(win) #draw first point p = win.getMouse() x1 = p.getX() y = p.getY() c = Circle(Point(x1,y),0.1) c.setFill('blue') c.draw(win) txt = Text(Point(x1+1,y+.5),'') txt.setText('%0.2f, %0.2f' %(x1,y)) txt.draw(win) #draw second point p2 = win.getMouse() x2 = p2.getX() c = Circle(Point(x2,y),0.1) c.setFill('blue') c.draw(win) txt = Text(Point(x2+1,y+.5),'') txt.setText('%0.2f, %0.2f' %(x2,y)) txt.draw(win) line = Line(Point(x1,y), Point(x2,y)) line.setOutline('red') line.setWidth('3') line.draw(win) #is the line above or below the ball? if y >5 or y< -5 : Txt = 'Line does not intersect Circle.' message(Txt) else: Txt = 'Line intersects Circle.' message(Txt) #draw intersect points x = math.sqrt(25 - y**2) for i in range(2): pt = Circle(Point(x, y),0.15) pt.setFill('yellow') pt.draw(win) x = -x instructions.setText ('Click anywhere to quit.') win.getMouse() win.close() if __name__ == '__main__': main()
Date of Easter from 1900 to 2099
Python Programming: Chapter 7, Exercise 10.
More doctests.
'''10. The formula for Easter in the previous problem works for every year in the range 1900-2099 except for 1954, 1981, 2049, and 2076. For these 4 years it produces a date that is one week too late. Modify the above program to work for the entire range 1900-2099. Check at: http://www.assa.org.au/edm.html ''' def get_date(year): ''' int -> str Return the date of Easter given a year between 1900 and 2000 >>> Enter a year between 1900 and 2099: 1922 In the year 1922 , Easter falls on April 16 >>> Enter a year between 1900 and 2099: 1822 Illegal date >>> Enter a year between 1900 and 2099: 1954 In the year 1954 , Easter falls on April 18 >>> Enter a year between 1900 and 2099: 1981 In the year 1981 , Easter falls on April 19 >>> Enter a year between 1900 and 2099: 2049 In the year 2049 , Easter falls on April 18 >>> Enter a year between 1900 and 2099: 2076 In the year 2076 , Easter falls on April 19 ''' if year < 1900 or year > 2099: print("Illegal date") else: a,b,c = year%19,year%4,year%7 d = (19*a+24)%30 e = (2*b+4*c+6*d+5)%7 days_after = d+e days = 22+days_after if year in [1954, 1981, 2049, 2076]: days -= 7 print"In the year ",year,", Easter falls on", if days <= 31: print "March " +str(days) else: print "April " + str(days-31) def main(): Year = input("Enter a year between 1900 and 2099: ") get_date(Year) main() if __name__ == "__main__": import doctest doctest.testmod()
Date of Easter for the Years 1982-2048
Python Programming: Chapter 7, Exercise 9.
Most of this is from ReexamPracticeQuestionSolutions.pptx (or in my case, .odp). You can download it at: http://www.csee.usf.edu/~rtindell/courses/Python/Solutions/
##from: ReexamPracticeQuestionSolutions.pptx '''Ex 9. A formula for computing the date of Easter in the years 1982-2048, inclusive,is as follows: Let a = year % 19, b = year%4, c = year%7, d = (19*a + 24)%30, and e = (2*b+4*c+6*d+5)%7. The date of Easter is (d+e) days after March 22 (which could be in April). Write a program that inputs a year, verifies that it is in the proper range, and then prints the date of Easter that year. Check dates at: http://www.assa.org.au/edm.html''' def main(): year =input("Enter a year between 1982 and 2048: ") if year < 1982 or year > 2048: print("Illegal date") else: a = year%19 b = year%4 c = year%7 d = (19*a+24)%30 e = (2*b+4*c+6*d+5)%7 days_after = d+e days = 22+days_after print "In year ",year,", Easter falls on", if days <= 31: print"March " ,str(days) else: print"April " , str(days-31) main()
A babysitter charges $2.50 an hour…
Python Programming: Chapter 7, Exercise 7.
I used a 24 hour clock because I’m not a masochist.
'''Ex 7. A babysitter charges $2.50 an hour until 9:00 PM when the rate drops to $1.75 an hour (the children are in bed). Write a program that accepts a starting time and ending time in hours and minutes and calculates the total babysitting bill. You may assume that the starting and ending times are in a single 24 hour period. Partial hours should be appropriately prorated.''' def calcFee(startTime, endTime): ''' str, str -> float >>> calcFee('15:45', '20:30') 'The babysitters fee is: $11.88' >>> calcFee('21:10','23:40') 'The babysitters fee is: $4.38' >>> calcFee('11:20','23:10') 'The babysitters fee is: $27.96' ''' #get the hours and minutes startHour = float(startTime.split(':')[0]) endHour = float(endTime.split(':')[0]) startMinutes = float(startTime.split(':')[1]) endMinutes = float(endTime.split(':')[1]) #turn minutes to decimal part of hour time = endHour + endMinutes/60 - (startHour + startMinutes/60) fee = 2.5*time if endHour < 21: fee = fee elif 21 <= startHour: fee = 1.75*time else: extraHours = endHour - 21 #subtract 0.75 cents from fee for time after 9:00 PM fee = fee - (0.75*(extraHours + (endMinutes/60))) return "The babysitters fee is: $%.2f"% fee def main(): x = raw_input("Using a 24 hour clock, enter the time the sitter arrived: ") y = raw_input("Using a 24 hour clock, enter the time the sitter left: ") print calcFee(x,y) main() if __name__ == "__main__": import doctest doctest.testmod()
Quiz Score to Letter Grade
Python Programming: Chapter 7, Exercise 3.
Thought I’d take the opportunity to try out some docstrings. If a test fails, it produces an error message in the interpreter.
'''Ex 2. A certain CS professor gives 5-point quizzes that are graded on the scale 5-A, 4-B, 3-C, 2-D, 1-F, 0-F. Write a program that accepts a quiz score as an input and uses a decision structure to calculate the corresponding grade. ''' def letterGrade(score): '''int -> string Return a letter grade when given an exam score provided by the user. >>> letterGrade(2) 'D' >>> letterGrade(3) 'C' >>> letterGrade(4) 'B' >>> letterGrade(5) 'A' ''' if score == 5: letter = 'A' elif score == 4: letter = 'B' elif score == 3: letter = 'C' elif score == 2: letter = 'D' else: letter = 'F' return letter def main(): x = input('Enter a numerical grade: ') letter = letterGrade(x) print 'Your grade is %s.' % letter main() if __name__ == "__main__": import doctest doctest.testmod()