HW 4:
ConditionOwls

Submission Details

Due: 3/4

Submit via Gradescope:

3 files in total

  • buggyConditionals.py

  • owlQuiz.py

  • A PDF that contains your self-assessment & reflection

Instructions

  • Log in to Coding Rooms

  • Navigate to the Assignment of HW 4: Conditionowls

  • Work through each part of the homework and use Coding Rooms to develop your code.

  • When you're ready to submit, download the Python files:

    • buggyConditionals.py

    • owlQuiz.py

    • Submit them to Gradescope.

  • Review the solutions to perform a self-assessment and write your reflection.

    • You may write up your self-assessment and reflection in whatever format is most comfortable for you (written on paper, typed in a Word or Google Doc, etc.), but you must convert it to a PDF before submitting. Please ask if you need help with this!

    • Submit the PDF to Gradescope and name it SelfAssessmentReflection.pdf.

Self-assessment & Reflection (reproduced from the Syllabus for reference)

Homeworks are an opportunity to engage with the material and practice your programming skills. To support you, solutions will be available on moodle. It is your responsibility to engage with them in a way that strategically moves your learning forward. You should:

  • Attempt the homework without looking at the solutions.

  • Review the solutions; if you were stuck, you may revise your homework. You may find yourself iteratively reviewing and revising to best support your learning.

  • When you submit your homework, you will be required to complete a self-assessment and reflection:

  1. Give yourself an assessment mark on the initial attempt:

✘ if you did not complete it

✓- if you completed it, but were very far from the solution

✓ if you completed it and essentially had the solution

✓+ if you completed it correctly, including precise communication

? if you are unsure as to whether or not you completed it

  1. Provide a short reflection as to why you earned that mark, such as:

  • I did not understand how to get started, and it was too close to the deadline to visit support hours.

  • I got stumped by a bug where my program entered an infinite loop.

  1. If you used the solutions to revise your work, describe what you needed to change, as in:

    • I modified the style of my conditional when I saw a simpler approach in the solutions.

    • I was so stuck that the majority of my submission is based on the solutions.

  2. Ask specific questions on portions that are still confusing, such as:

    • Why does it cause an error when I returned "1" instead of 1?

[Optional] Provide one hint for the homework (to your past self or future student).

Overview

This homework will give you a chance to practice with conditionals!

First, you'll work to debug some code to help clarify your understanding or identify questions.

Then, you'll create a Buzzfeed-type quiz to determine how much of a night owl someone is!

Learning goals

  • practice with conditionals

  • practice debugging skills

  • implementing a program from a given design

  • type-hinting and using mypy to make sure types are consistent

Be strategic!

  • Start early!

  • Ask questions!

  • Leave time for questions by... starting early :)

  • When you're stuck, pause and evaluate what could be going on. Remember the self-regulated learning cycle!

    • Do you have a plan?

    • Are you evaluating your plan? How will you test your code as you go?

    • How will you revise? What will you do when you're confused? Stuck?

Part 1: Debugging conditionals

In Coding Rooms, open the file buggyConditionals.py.

  • This program has some bugs in it!

  • Work to debug the program, using the comments to guide you.

  • For reference, the original buggy program is below.

buggyConditionals.py

def countVowels( word:str ) -> int:

""" Count and return the number of vowels (a, e, i, o, u) in a word. """


lowerWord:str = word.lower()

numAs:int = lowerWord.count( "a" )

numEs:int = lowerWord.count( "e" )

numIs:int = lowerWord.count( "i" )

numOs:int = lowerWord.count( "o" )

numUs:int = lowerWord.count( "u" )


return numAs + numEs + numIs + numOs + numUs


def buggy1( word:str ) -> int:

""" Count and return the number of vowels (a, e, i, o, u) in a word. """


lowerWord:str = word.lower()

numVowels:int = 0


for letter in lowerword:

if letter == "a":

numVowels = 1

if letter == "e":

numVowels = 1

if letter == "i":

numVowels = 1

if letter == "o":

numVowels = 1

if letter == "u":

numVowels = 1

return numVowels


def buggy2( word:str ) -> int:

""" Count and return the number of vowels (a, e, i, o, u) in a word. """


lowerWord:str = word.lower

numVowels:int = 0


for letter in lowerWord:

for vowel in "aeiou":

if letter = vowel:

numVowels += 1

else:

numVowels = 0

return numVowels


def buggy3( word:str ) -> int:

""" Count and return the number of vowels (a, e, i, o, u) in a word. """


lowerWord:str = word.lower()

numVowels:int = 0


for vowel in "AEIOU":

for letters in word:

if letter == vowel

numVowels += 1

return numVowels


def hasRepeatedLetter( word:str ) -> bool:

""" Returns True if there is a repeated letter in the word

and False otherwise.

Examples: buggy4( "hello" ) -> True since "l" is repeated

buggy4( "elephant" ) -> True since "e" is repeated

buggy4( "dinosaur" ) -> False since no letter is repeated. """


alphabet:str = "abcdefghijklmnopqrstuvwxyz"

lowerWord:str = word.lower()


for letter in alphabet:

if lowerWord.count( letter ) > 1:

return True

# if we get here, it means we never entered

# the return True statement within the conditional within the loop

# so there must not have been a repeated letter

return False


def buggy5( word:str ) -> bool:

""" Returns True if there is a repeated letter in the word

and False otherwise.

Examples: buggy4( "hello" ) -> True since "l" is repeated

buggy4( "elephant" ) -> True since "e" is repeated

buggy4( "dinosaur" ) -> False since no letter is repeated. """


lowerWord:str = word.lower()


for letter in lowerWord:

if letter.count( lowerWord ) > 1:

return True

# if we get here, it means we never entered

# the return True statement within the conditional within the loop

# so there must not have been a repeated letter

return False


def buggy6( word:str ) -> int:

""" Returns True if there is a repeated letter in the word

and False otherwise.

Examples: buggy4( "hello" ) -> True since "l" is repeated

buggy4( "elephant" ) -> True since "e" is repeated

buggy4( "dinosaur" ) -> False since no letter is repeated. """


lowerWord:str = word.lower()


# walk over the string

for i in range(len(lowerWord)):

# store the current letter

currentLetter:str = lowerWord[i]


# get the letters following the current one

followingLetters:str = lowerWord[i+1:]


# for each following letter

for followingLetter in followingLetters:

# check if it's the same as the curernt one

if followingLetters == currentLetter:

# if so, we found a repeat!

return True

else:

return False

def testVowelFunctions(testWords:list) -> None:

passedTestsBuggy1:int = 0

passedTestsBuggy2:int = 0

passedTestsBuggy3:int = 0

for word in testWords:

correctCount:int = countVowels( word )

buggy1Count:int = buggy1(word)

if buggy1Count != correctCount:

print( f"TEST FAILED: buggy1(\"{word}\")... {buggy1Count} != {correctCount}" )

else:

passedTestsBuggy1 += 1


buggy2Count:int = buggy2(word)

if buggy2Count != correctCount:

print( f"TEST FAILED: buggy2(\"{word}\")... {buggy2Count} != {correctCount}" )

else:

passedTestsBuggy2 += 1


buggy3Count:int = buggy3(word)

if buggy3Count != correctCount:

print( f"TEST FAILED: buggy3(\"{word}\")... {buggy3Count} != {correctCount}" )

else:

passedTestsBuggy3 += 1


if passedTestsBuggy1 == len(testWords):

print( "buggy1 passed all tests!" )

if passedTestsBuggy2 == len(testWords):

print( "buggy2 passed all tests!" )

if passedTestsBuggy3 == len(testWords):

print( "buggy3 passed all tests!" )


def testRepeatFunctions(testWords:list) -> None:

passedTestsBuggy5:int = 0

passedTestsBuggy6:int = 0

for word in testWords:

repeatExists:bool = hasRepeatedLetter( word )

buggy5Check:bool = buggy5(word)

if buggy5Check != repeatExists:

print( f"TEST FAILED: buggy5(\"{word}\")... {buggy5Check} != {repeatExists}" )

else:

passedTestsBuggy5 += 1


buggy6Check:bool = buggy6(word)

if buggy6Check != repeatExists:

print( f"TEST FAILED: buggy6(\"{word}\")... {buggy6Check} != {repeatExists}" )

else:

passedTestsBuggy6 += 1


if passedTestsBuggy5 == len(testWords):

print( "buggy5 passed all tests!" )

if passedTestsBuggy6 == len(testWords):

print( "buggy6 passed all tests!" )


def main():

testWords:list = ["", "HELLO", "Mount", "Holyoke", "College", "owl", "dinosaur", "Elephant"]

testVowelFunctions( testWords )

testRepeatFunctions( testWords )


if __name__ == "__main__":

main()

Tips

  • Some bugs are "easy" to detect in that Python will actually print out an error.

    • Use the error message to identify where the bug is.

      • The line number is a great starting point!

  • Some bugs are "logical" bugs, which are a bit harder to identify and fix. For the buggy code given to you, identify them by looking at the

      • Focus on examples where the expected output does not match the actual output to help isolate the bug(s)

      • Draw memory and trace the program to understand how Python is interpreting the code

      • Use print statements to gain insight into memory and narrow down the source(s) of the bug(s)

      • Use the comments to help you understand the high-level approach; there is a logical bug whenever the Python code does not implement the high-level approach

Part 2: the (computer) science behind Buzzfeed Quizzes

Have you ever taken a Buzzfeed quiz? You answer a bunch of multiple choice questions and find out things like... "What type of emoji are you?"


In this part, you'll program your own simplified version of the Buzzfeed quiz "How much of a night person are you?". Here's an overview of how you will deliver the quiz and its results.

Quiz delivery

Here is the list of questions and answers to present to the user.

  1. What is the most prominent part of your nightly routine?
    (A) Reading
    (B) Teeth-brushing
    (C) Having an existential crisis
    (D) Pajamas

  2. Which most accurately describes your work ethic?
    (A) Procrastinating
    (B) Diligent
    (C) Lazy
    (D) Well-paced

  3. In the morning you feel...
    (A) Like I've been hit by a bus
    (B) Reasonably rested
    (C) Groggy
    (D) Like a million bucks

Quiz results


  • You'll use three score values to decide the outcome of the quiz; these will be maintained in a list of length 3

  • The pseudocode below will tell you how to update the values for each question and how to use the final values to determine the result

Sample program behavior

What is the most prominent part of your nightly routine?

A. Reading

B. Teeth-brushing

C. Having an existential crisis

D. Pajamas

(A/B/C/D): C

Which most accurately describes your work ethic?

A. Procrastinating

B. Diligent

C. Lazy

D. Well-paced

(A/B/C/D): A

In the morning you feel...

A. Like I've been hit by a bus

B. Reasonably rested

C. Groggy

D. Like a million bucks

(A/B/C/D): C

You're 100% night owl! (You're pretty much nocturnal, and that's okay! Embrace the night.)


OR


What is the most prominent part of your nightly routine?

A. Reading

B. Teeth-brushing

C. Having an existential crisis

D. Pajamas

(A/B/C/D): B

Which most accurately describes your work ethic?

A. Procrastinating

B. Diligent

C. Lazy

D. Well-paced

(A/B/C/D): D

In the morning you feel...

A. Like I've been hit by a bus

B. Reasonably rested

C. Groggy

D. Like a million bucks

(A/B/C/D): C

You're 50% Night Owl! (Staying up late or waking up early, both are equally easy, or difficult, for you.)

Pseudocode

We have provided a design for you, given by the function descriptions and pseudocode below.

In the pseudocode, we refer to a, b and c as shorthand for the score value at index 0, 1, and 2, respectively.

  • For the deliverQuestion functions

    • you must use scores[0] for a, scores[1] for b, and scores[2] for c to modify the list values

  • For the determineOwliness function

    • you can use scores[0] etc OR

    • you can make variables a, b and c assigned to scores[0], scores[1] and scores[2], then use a, b and c for the rest of the function.

Why is this? Remember we talked about "primitive types" and "reference types" briefly in class? Since a list is a "reference type," we can modify its values in a function and they persist even after the function execution has completed. However, a str is a "primitive type" and the assignment actually copies the value. Therefore, modifying the value of the new variable would not modify the original list entries.

Tips

    • Use the \ to continue a line of code onto the next line. This is helpful if, for example, you are trying to create a long string, as in:

question1:str = "What is the most prominent part of your nightly routine?\n" + \

"\t(A) Reading\n\t(B) Teeth-brushing\n\t(C) Having an existential crisis" + \

"\n\t(D) Pajamas\n(A/B/C/D): "

    • Use the input function to ask the user a question and display the options.
      You may want to use the \n and \t characters, which display new line and tabs respectively. Try it out with this sample code:

print( "Hello, there!\nThis is on another line\n\tThis is on a new line AND indented!" )

howOwly function

    • takes no parameters

    • has a return type of None

    • expected behavior: deliver a buzzfeed-type quiz that asks the user a series of questions and determines how much of a night owl they are

    • pseudocode for the implementation:

      • assign a variable called scores of type list that has length 3 and initializes all three entries to hold the value 0

      • invokes the function deliverQuestion1, passing the scores list as the argument

      • invokes the function deliverQuestion2, passing the scores list as the argument

      • invokes the function deliverQuestion3, passing the scores list as the argument

      • invokes the function determineOwliness, passing the scores list as the argument

deliverQuestion1 function

    • takes 1 parameter of type list called scores

    • has a return type of None

    • expected behavior: Assumes that scores has length 3. Asks the user a question and updates the values in the list accordingly.

    • pseudocode for the implementation:

Prompt the user to respond to Question 1

IF the answer to 1 is Having an existential crisis

add 2 to the value of c

ELSE IF the answer to 1 is Teeth-brushing or pajamas

add 1 to the value of a

ELSE IF the answer to 1 is Reading

add 1 to the value of b

add 1 to the value of c

deliverQuestion2 function

    • takes 1 parameter of type list called scores

    • has a return type of None

    • expected behavior: Assumes that scores has length 3. Asks the user a question and updates the values in the list accordingly.

    • pseudocode for the implementation:

Prompt the user to respond to Question 2

IF the answer to 2 is not Diligent and is not Well-paced

subtract 1 from the value of b


IF the answer to 2 is Diligent

add 2 to the value of b

ELSE IF the answer to 2 is Well-paced

add 1 to the value of b

ELSE IF the answer to 2 is Procrastinating

add 2 to the value of c

ELSE IF the answer to 2 is Lazy

add 2 to the value of a

deliverQuestion3 function

    • takes 1 parameter of type list called scores

    • has a return type of None

    • expected behavior: Assumes that scores has length 3. Asks the user a question and updates the values in the list accordingly.

    • pseudocode for the implementation:

Prompt the user to respond to Question 3

IF the answer to 3 is Like a million bucks

add 2 to the value of b

ELSE IF the answer to 3 is Reasonably rested

add 2 to the value of b

add 1 to the value of a

ELSE IF the answer to 3 is Groggy

add 1 to the value of a

add 1 to the value of c

ELSE IF the answer to 3 is Like I've been hit by a bus

add 2 to the value of c

determineOwliness function

    • takes 1 parameter of type list called scores

    • has a return type of None

    • expected behavior: Assumes that scores has length 3. Analyzes the values and prints the appropriate quiz results.

    • pseudocode for the implementation:

IF (b > c) and (a > c)

tell the user
You're 5% night owl! (Well, well, well, looks like we've got a morning person here!)

ELSE IF (c > a + 1) or (c > b + 1)

tell the user
You're
100% night owl! (You're pretty much nocturnal, and that's okay! Embrace the night.)

ELSE

tell the user
You're 50% night owl! (Staying up late or waking up early, both are equally easy, or difficult, for you.)

A special thank you to Emily Craig '17 and Sarah Robinson '17, whose MaGE active learning module on Conditionals inspired this homework!

Solutions

As per the Syllabus: you should use these to support your learning. Do not look at solutions until you have attempted the work. It is up to you to best leverage this resource.