CS 0008: Spring 2015 Preparation for Assignment 2. If you spend time on this and understand everything here, you will be able to handle Assignment 2 much better! This will also help you prepare for Exam 1. You should do this entirely by yourself. There is nothing to hand in. === Consider this version of num_vowels: # nothing wrong with the constant; it is a global variable, but # it is capitalized telling us that we won't change the value. # all functions can use it. VOWELS = 'aeiou' def num_vowels1(s): '''Return the number of vowels in string s. The letter "y" is not treated as a vowel.''' count = 0 for char in s: if char in VOWELS: count = count + 1 return count However, num_vowels1("I am Groot") incorrectly returns 3 rather than 4. What's wrong? Create a file in IDLE, fix the mistake, and call num_vowels1 to confirm that your new version is correct. ==== This question concerns using a Boolean variable as a "sentinel" to check for a condition. Suppose you want to check whether all the elements of a list are the int 1, and print "yes" if so, "no" otherwise. Here is an example to work with (we want to print "no"). lst = [1,1,2,3,4,1,1] # Initialize boolean variable allOnes to True allOnes = True # Since we need to check all of the list entries, we will use a for # loop. To make sure you understand the for-loop, try this in the shell: for el in lst: print(el) # Now add a test for int lst = [1,1,2,3,4,1,1] allOnes = True for el in lst: if el == 1: print("yup! it's 1") # What we really care about is whether an element is NOT 1 lst = [1,1,12,13,14,1,1] allOnes = True for el in lst: if not el == 1: print("nope! it's not a 1") # Now let's make it a function; and you complete it. Trace through # your code on paper so you understand what is going on def ones(lst): allOnes = True for el in lst: # you fill in these lines return allOnes # make sure your code works for all of these cases: ones([1,1,1]) ones([1]) ones([4]) ones([4,3,2,1]) ones([1,2,3]) ones([1,2,1]) ===== Indexing sequences: Lists and strings may be indexed; it works exactly the same way for both. Try this out in the shell: lst = [1,1,12,13,14,1,1] ls[0] ls[2] ls[4] ls[6] len(lst) # As you can see, the list has 6 elements, numbered from 0 to 5. st = "Stinky cheese" # Similarly, st has 13 elements, numbered from 0 to 12 len(st) st[0] st[7] st[12] ==== Now we can use while-loops rather than for-loops to step through a sequence. Let's rewrite this for loop using a while loop: lst = [1,1,12,13,14,1,11] for el in lst: print(el) i = 0 while # you fill this in; be sure your code prints ALL and ONLY the # elements of the list. Of course, your code should work # for any value of "lst" print(el[i]) i += 1 The same thing works for strings: st = "Stinky Cheese" i = 0 while # you fill this in print(st[i]) i += 1 Once you figure that out, you will be familiar with a common programming task -- getting the number of loop iterations exactly right. A common bug is to do one too few or one too many. Another common bug is forgetting to increment i (i += 1). In that case, the loop goes on forever ... ==== Why use a while loop? When you don't know how many iterations you need. Write code to print out the index of the first 13 that appears in a list. Print -1 if there is no 13. Let's try this version (create a file in IDLE and edit it; it will be easier than using the shell) lst = [1,1,12,13,14,1,11] i = 0 while lst[i] != 13: i += 1 print("the first 13 is at index",i) Hmmm, that SEEMS right. But what happens when lst is this instead? lst = [1,1,12,15,14,1,11] i = 0 while lst[i] != 13: i += 1 if i < # you fill this in print("the first 13 is at index",i) else: print("there is no 13", -1) Oops! your code tries to access lst[13], but it doesn't exist! That's what "list index out of range means" To fix this, you will need to combine 2 ideas: 1. You will have to test for the end of the list; you had to figure that out above 2. Remember from class that Boolean Expressions "short circuit" - Python stops evaluating them, once it already knows what the answer should be. Programmers often exploit this. #Try these out in the shell test = False and True and False and True # Python actually stops after the initial "False" because it already knows the answer. False and anything is False! # To see this: 4/0 # this raises and error test = False and 4/0 and True and False # see, no error! because Python stops after the initial False So, your task is to write a condition that uses an "AND"; the first condition should check for the end of the list make sure your code works for the following (we aren't handling the empty list []) lst = [13] lst = [14] lst = [14,15,13] lst = [13,14,15] lst = [14,13,13] ===== Building up strings # Try these out st = "" st += 'a' st += 'b' st += 'ccc' st += 'eeeeeeeee' print(st) st1 = "" # copy the first 3 chars of st to st1 for i in range(3): print(i) # remember, range(n) generates a sequence of 0 through n-1 st1 += st[i] print("st is",st) print("st1 has the first 3 chars of st; it is", st1) ===== Hints for function "transWord" 1. First test for the special case of the word being all vowels using an if-statement. The "then" clause takes care of that special case. The "else" clause takes care of all the other cases. The "else" clause body is longer than the "then" clause body. 2. You should use this structure # if the word only contains vowels # then return right now with the answer # else # split the word into prefix and stem: # prefix = "" # add characters to prefix one by one # stem = "" # copy the rest of the characters to stem, one by one # return the answer ===== Hints for function "transSent" You will be able to use this handy method provided by Python. # Try this in the shell st = "Hello there bear do you want some stinky cheese" st.split() # Save the result in a variable: words = st.split() words # Now you can use a for or while loop (whichever is appropriate) to step through the list, handling each word in turn # We will let you figure out the structure of this function yourself. The tricky thing is that you want each of the words # to be separated by a space, but there should not be any extra spaces at the beginning or the end of the string, and the # string should end in a '.' === A note on debugging: Add print statements to help debug your program. For example, suppose a loop is processing lst element by element, using index i, but something isn't right. Try adding print("start: i",i,"lst[i]",lst[i]) to the beginning of the loop body and print("end: i",i,"lst[i]",lst[i]) to very end, to see what's going on.