Problem Set 6 - Due Friday, March 15, 2019

Reading

  1. Slides and notebooks from Lec 09 (Iteration 1), Lec 10 (Lists, Memory Diagrams, and Mutable vs. Immutable Sequences), Lec 11 (List Processing Patterns and List Comprehensions), and Lec 12 (Testing and Debugging)
  2. Problems and solutions from Lab 06 (Lists) and Lab 07 (List Comprehensions, Testing, Debugging)
  3. Think Python, Ch. 8: Iteration
  4. Think Python, Ch. 10: Lists

About this Problem Set

This problem set will give you practice with lists, for and while loops, list comprehensions, testing, and debugging.

  1. In Task 1 (individual task), you will define functions that create lists through accumulation and list comprehensions. This is a continuation of the Word Play task from PS05.
  2. In Task 2 (individual task), you will use a while loop to implement a simple game.
  3. In Task 3 (partner-recommended task), you will use iteration tables to design a loop-based function, and then implement and test this function.
  4. In Task 4 (partner-recommended task), you will distinguish between correct and incorrect implementations of a loop-based functions.

In Tasks 3 and 4, having a partner is optional, but strongly recommended. You can choose to work with a partner on both of the tasks, or just one of the tasks if you prefer. However, if you choose both of the tasks, you must work with the same partner on both tasks. If you want to have a partner, use this shared Google Doc.

Other notes:

All code for this assignment is available in the ps06 folder in the cs111/download directory within your cs server account. This assignment also uses the Codder program to help you do a final check for Tasks 1 and 2 and parts of Tasks 3 and 4.



Task 1: Word Search

This task is an individual problem which you must complete on your own, though you may ask for help from the CS111 staff.

Subtask 1a: Mapping, Filtering, and Accumulating with Loops

This task is a continuation of Task 2 from PS05. In that task, you wrote the functions that included isBeauteous, isPrecarious, and scrabbleScore.

You will use these functions to write three new functions that use a list of English words to find and return words that fulfill a certain property, stored in lists and tuples.

Additionally, you will write a function, reverseWords, that takes any sentence as a string of space-separated words, and returns a string where every word is reversed.

Fill out the body of these functions in the file wordsearch.py following the contracts in that file.

Notice that the file imports the functions from wordplay.py as well as a list of words from vocabulary.py. This list is called englishwords, and is the list that your functions must search through.

Sample Executions

In [1]: listBeauteousPrecariousWords(8)
Out[1]: ['sequoias']

In [2]: listBeauteousPrecariousWords(9)
Out[2]: ['behaviour', 'facetious', 'nefarious', 'tenacious', 'veracious', 'vexatious']

In [3]: listBeauteousPrecariousWords(10)
Out[3]: ['abstemious', 'bivouacked', 'gregarious', 'mendacious', 'precarious']

In [4]: listBeauteousPrecariousWords(14)
Out[4]: []

In [5]: listGoodScrabbleWords(35)
Out[5]: [('acquaintanceships', 35), ('compartmentalized', 35),
 ('compartmentalizing', 36), ('cryptographically', 35),
 ('czechoslovak', 35), ('czechoslovakia', 37),
 ('czechoslovakian', 38), ('czechoslovakians', 39),
 ('czechoslovaks', 36), ('electroencephalograph', 36),
 ('electroencephalographs', 37), ('embezzlement', 36),
 ('embezzlements', 37), ('extemporization', 35),
 ('extemporizations', 36), ('jazzily', 35), ('mozambiquean', 36),
 ('mozambiqueans', 37), ('overcapitalizations', 35),
 ('psychoanalytically', 36), ('psychokinetically', 36),
 ('psychopathically', 36), ('quinquagesimas', 35),
 ('quizzed', 35), ('quizzical', 38), ('quizzically', 43),
 ('quizzing', 36), ('schizophrenically', 41),
 ('schizophrenics', 35), ('sympathizingly', 37)]

In [6]: bestScrabbleWord()
Out[6]: ('quizzically', 43)

In [7]: reverseWords('we are never ever getting back together')
Out[7]: 'ew era reven reve gnitteg kcab rehtegot' 

Notes

Subtask 1b: Mapping and Filtering with List Comprehensions

In this subtask, you will define three functions named listBeauteousPrecariousWordsLC, listGoodScrabbleWordsLC, and reverseWordsLC that behave exactly like the correspondingly named functions from subtask 1a. The difference is that the function definitions in this subtask must use list comprehensions rather than explicit loops to perform all mapping and filtering on lists.

Notes

Ungraded Challenge

For additional ungraded mapping entertainment (use a separate file if you write this code), implement a function called keyboardLeopard that takes three arguments: (1) an arbitrarily long string containing sentences, paragraphs, etc.; (2) a "bad" word to be censored; and (3) a funny word with which to replace the "bad" word. The function must return a version of the first string where every occurrence of the "bad" word is replaced by the funny word. Extend the function to take a list of "bad"/funny word pairs and rewrite the original string to replace all occurrences of each "bad" word with its corresponding funny word in this list of pairs. See here for more inspiration.


Task 2: The Sum Game

This task is an individual problem which you must complete on your own, though you may ask for help from the CS111 staff.

This task involves a simple one-player game that we'll call the Sum Game. The game is parameterized over a positive integer n. The game has two sums named sumA and sumB that are initially 0. At each move of the game, the player is presented with a random integer between between 1 and n (inclusive) and must choose whether to add this number to sumA or sumB. The player wins the game when the two sums are equal.

Here is a transcript of the Sum Game played with 5 as an argument:

In []: sumGame(5)
Welcome to the Sum Game!
Move 1: sumA is 0 and sumB is 0.

Add 3 to sumA or sumB (enter A or B)? A
Move 2: sumA is 3 and sumB is 0.

Add 2 to sumA or sumB (enter A or B)? B
Move 3: sumA is 3 and sumB is 2.

Add 2 to sumA or sumB (enter A or B)? sumB
sumB is not valid. Only strings that are 
(any case of) A or B are valid. Try again.

Add 2 to sumA or sumB (enter A or B)? bcd
bcd is not valid. Only strings that are 
(any case of) A or B are valid. Try again.

Add 2 to sumA or sumB (enter A or B)? b
Move 4: sumA is 3 and sumB is 4.

Add 3 to sumA or sumB (enter A or B)? A
Move 5: sumA is 6 and sumB is 4.

Add 5 to sumA or sumB (enter A or B)? B
Move 6: sumA is 6 and sumB is 9.

Add 2 to sumA or sumB (enter A or B)? a
Move 7: sumA is 8 and sumB is 9.

Add 1 to sumA or sumB (enter A or B)? A
Both sumA and sumB are 9. You win the game after 7 moves!

Note that the player chooses sumA by entering A or a, and chooses sumB by entering B or b. Any other input (including any longer string beginning with A, a, B, or b) is considered invalid, and the player is prompted to enter another input.

Your task is to flesh out the definition of the sumGame function in sumGame.py to implement this game.

Notes

Testing

 


Task 3: Longest Vowel Substrings

In this problem, having a partner is optional, but is strongly recommended. If you want to find a partner, use this shared Google Doc.

In this task, you will first design and then define a function longestVowelSubstrings that returns a list of all the longest substrings of consecutive vowels in given string in the order that they appear in the string. Here are numerous examples of the input/output behavior of this function:

Input Output
'bunny' ['u']
'success' ['u', 'e']
'compute' ['o', 'u', 'e']
'universal' ['u', 'i', 'e', 'a']
'transcendentalism' ['a', 'e', 'e', 'a', 'i']
'extracurricular' ['e', 'a', 'u', 'i', 'u', 'a']
'overcapitalized' ['o', 'e', 'a', 'i', 'a', 'i', 'e']
'aquifer' ['ui']
'evacuate' ['ua']
'confidentialities' ['ia', 'ie']
'inequalities' ['ua', 'ie']
'internationalization' ['io', 'io']
'unquestionable' ['ue', 'io']
'visualizations' ['ua', 'io']
'weatherproofed' ['ea', 'oo']
'autobiographies' ['au', 'io', 'ie']
'mountaineering' ['ou', 'ai', 'ee']
'questionnaire' ['ue', 'io', 'ai']
'incautious' ['iou']
'audacious' ['iou']
'inauspicious' ['iou']
'beautifies' ['eau']
'bureaucracies' ['eau']
'consanguineous' ['eou']
'beauteous' ['eau', 'eou']
'squeegeeing' ['uee', 'eei']
'sequoia' ['uoia']
'obsequiousness' ['uiou']
'queueing' ['ueuei']
'wryly' ['']
'OVERCAPITALIZED', ['O', 'E', 'A', 'I', 'A', 'I', 'E']
'InEqUaLiTiEs' ['Ua', 'iE']
'BeAuTeOuS' ['eAu', 'eOu']

Subtask 3a: Iteration Tables

There are many different approaches for correctly defining longestVowelSubstrings. Some involve using multiple loops. For example, you could first use one loop to find the length of the longest vowel substring, and then use another loop to collect the list of all vowel substrings with that length.

However, in this task you are subject to this requirement:

Requirement: Your longestVowelSubstrings function must use exactly one for loop. Solutions using more than one loop or using a while loop rather than a for loop are not allowed.

How do you go about designing this for loop?

As seen in slides 14 to 15 of Lec Iteration 1 and Subtask 1b keepFirstLetter from PS05, iteration tables are a powerful technique for designing loops, especially in nontrivial functions like longestVowelSubstrings. So in this subtask you will use iteration tables to help you think about how to design the loop you'll need in longestVowelSubstrings.

Although you might think that creating iteration tables might cost extra time, they typically can save you lots of time by helping you design a correct loop from the beginning rather than wasting time debugging incorrect loops.

If you've forgotten the parts of an iteration table, now would be a good time to review the summary of iteration tables in PS05 Subtask 1b keepFirstLetter.

A Sample Iteration Table for longestVowelSubstrings

Rather than ask you to define iteration tables for longestVowelSubstrings from scratch, we'll give you an iteration table for one example input and ask you to show that you understand it by generating the iteration tables for two other inputs.

Below is the iteration table for the loop in longestVowelSubstrings('inequalities'):

char vowelSeq longestSeqsSoFar
'' ['']
'i' 'i' ['i']
'n' '' ['i']
'e' 'e' ['i', 'e']
'q' '' ['i', 'e']
'u' 'u' ['i', 'e', 'u']
'a' 'ua' ['ua']
'l' '' ['ua']
'i' 'i' ['ua']
't' '' ['ua']
'i' 'i' ['ua']
'e' 'ie' ['ua', 'ie']
's' '' ['ua', 'ie']

There are three state variables:

It is possible to have additional state variables, but only three are needed. For example, a longestLengthSoFar state variable could maintain the length of the longest consecutive vowel sequence seen so far. But this state variable is not strictly needed, since it can always be calculated from longestSeqsSoFar (how?).

As in the example from PS05 Subtask 1b keepFirstLetter, this algorithm for longestVowelSubstrings does not have any early termination conditions and will stop only after all of the characters in the input string have been processed.

Based on this example, you should figure out the iteration rules that determine how the value of each state variable in a nonfirst row is determined from the values of the state variables in the the previous row. You don't have to write down these rules, but you will need to understand them to create three more iteration tables.

Representing an Iteration Table as a List of Tuples

An iteration table can be represented in Python as a list of tuples in which the length of each tuple is the number of state variables:

For example, here is a Python list of tuples for the above iteration table:

inequalitiesTable = [
    ('char', 'vowelSeq', 'longestSeqsSoFar'), 
    (None, '', ['']), 
    ('i', 'i', ['i']), 
    ('n', '', ['i']), 
    ('e', 'e', ['i', 'e']),
    ('q', '', ['i', 'e']),
    ('u', 'u', ['i', 'e', 'u']), 
    ('a', 'ua', ['ua']), 
    ('l', '', ['ua']), 
    ('i', 'i', ['ua']),
    ('t', '', ['ua']),                     
    ('i', 'i', ['ua']),                     
    ('e', 'ie', ['ua', 'ie']), 
    ('s', '', ['ua', 'ie'])
]

Note that the None value is used to represent an empty slot in the first row of the table.

Your Subtask 3a

In the given file longestVowelSubstrings.py, flesh out the definitions of these two list-of-tuples iteration tables:

Testing

Because students in the past have had trouble getting the correct structure for the iteration table, we provide a Codder test that your three list-of-tuples iteration tables have a valid structure. However, the content of the three tables will not be checked by Codder until the final grading pass after submission.

Subtask 3b: Defining a testing function for longestVowelSubstrings

In Subtask 3c, you will define the longestVowelSubstrings function. Unlike most previous problems, you will not be provided with Canopy testing functions or Codder testing for longestVowelSubstrings. In order to mature as programmers, you need to learn how to effectively test your own code. So in this Subtask 3b, you will develop a testing function that you will use to test your longestVowelSubstrings function in Subtask 3c.

It's a good idea to define a testing function before defining the function it tests so that you can use it for testing as you incrementally flesh out the desired function.

Subtask 3b, Part 1: Define longestVowelSubstringsTestCases

As shown in Lec 12 (Testing and Debugging) and in the testing parts of Python program files like PS04's animalQuiz.py and PS05's wordplay.py, the first step in automated function testing is defining a list of input/expectedOutput tuples.

For this part, you must flesh out the skeleton for the variable longestVowelSubstringsTestCases, which has been started for you in longestVowelSubstrings.py:

longestVowelSubstringsTestCases = [
    ('bunny', ['u']),
    ('success', ['u', 'e']),
    ('compute', ['o', 'u', 'e']),
    # Flesh out the missing test cases after this point. 

]

longestVowelSubstringsTestCases must contain at least all the test cases that are in the input/output table for longestVowelSubstrings that appears at the beginning of this Task 3. You may add additional test cases if you wish.

Subtask 3b, Part 2: Define testLongestVowelSubstrings

In this part you must flesh out the skeleton of the the function testLongestVowelSubstrings provided in longestVowelSubstrings.py. This function takes as its single argument a list of test cases, where each test case is two-element tuple of (1) an input string and (2) an expected output that is a list of strings. This function should behave like the testing functions described in Lec 12 (Testing and Debugging).

In particular, before you have fleshed out the skeleton of the longestVowelSubstrings function in Subtask 3c, it will return None for every input, and invoking testLongestVowelSubstrings() will lead to a printouts that begin like this:

In []: testLongestVowelSubstrings(longestVowelSubstringsTestCases)
***FAILED: longestVowelSubstrings('bunny') returned None but expected ['u']
***FAILED: longestVowelSubstrings('success') returned None but expected ['u', 'e']
***FAILED: longestVowelSubstrings('compute') returned None but expected ['o', 'u', 'e']
... many more test results must be printed after this point ... 

But when the longestVowelSubstrings is defined correctly, invoking testLongestVowelSubstrings() will lead to a printouts that begin like this:

In []: testLongestVowelSubstrings(longestVowelSubstringsTestCases)
   PASSED: longestVowelSubstrings('bunny') returned expected value ['u']
   PASSED: longestVowelSubstrings('success') returned expected value ['u', 'e']
   PASSED: longestVowelSubstrings('compute') returned expected value ['o', 'u', 'e']```

(Note that PASSED is always preceded by three spaces in the above printout.)

testLongestVowelSubstrings is similar to the testing functions in Python program files like PS04's animalQuiz.py and PS05's wordplay.py except that rather than taking zero arguments it takes a single argument that is a list of input/expectedOutput tuples.

Testing

As shown above, you should test testLongestVowelSubstrings by invoking it on longestVowelSubstringsTestCases before you start defining longestVowelSubstrings in Subtask 3c, and you should continue to invoke it as you incrementally define longestVowelSubstrings in Subtask 3c.

The file longestVowelSubstrings.py ends with the testing block

if __name__ == "__main__":
    testLongestVowelSubstrings(longestVowelSubstringsTestCases)

so running this Python file in Canopy will automatically run the testing function. Other than that, there is no other Canopy or Codder support for testing your testing function.

Subtask 3c: longestVowelSubstrings function definition

The file longestVowelSubstrings.py contains a skeleton for the the longestVowelSubstrings function. In this subtask, you will flesh out the definition of longestVowelSubstrings so that it implements the iteration rules you used when you fleshed out the iteration tables in Subtask 3a.

Notes

 


Task 4: Debugging replaceVowelSequences

In this problem, having a partner is optional, but is strongly recommended. If you want to find a partner, use this shared Google Doc.

This task involves studying correct and incorrect definitions of a function that loops over the characters of a word. Defining this function, replaceVowelSequences, was ths subject of a problem on a previous CS111 midterm. This task first explains that problem, and then asks you to review numerous attempted solutions to that problem to determine which are correct/incorrect and why.

Background: The replaceVowelSequences problem description

This is a problem description for replaceVowelSequences problem. You are not asked to define this function, but are asked to study the solutions of other students for this problem.

Because vowels are more likely to change over time than consonants, linguists sometimes describe words in terms of just their consonants, putting in a star (asterisk) for a sequence of consecutive vowels. You will define a function replaceVowelSequences that takes a word and returns a string that replaces each sequence of vowels in the word with an asterisk. For example:

word replaceVowelSequences(word)
'dog' 'd*g'
'seafood' 's*f*d'
'audacious' '*d*c*s'
'amnesia' '*mn*s*'
'stethoscope' 'st*th*sc*p*'
'dry' 'dry'
'' ''

Here are iteration tables that show the function working on some examples:

Example 1: 'dog'

char result result
'' False
'd' 'd' False
'o' 'd*' True
'g' 'd*g' False

Example 2: 'audacious'

char result result
'' False
'a' '*' True
'u' '*' True
'd' '*d' False
'a' '*d*' True
'c' '*d*c' False
'i' '*d*c*' True
'o' '*d*c*' True
'u' '*d*c*' True
's' '*d*c*s' False

Recall that the first row of an iteration table shows the values of state variables before the loop begins, and each other row shows their values after of executing all the loop body statements in each iteration of the loop. In the above tables, char has no value in the first row because it is only defined during each iteation of the loop.

Define replaceVowelSequences using a for loop with the state variables shown in the above iteration tables. Assume there is an correctly defined isVowel predicate.

A completely correct solution has the following properties:

Background: A correct definition for replaceVowelSequences

Here is one of many possible correct solutions to replaceVowelSequences. We give it the short name rVSCorrect to allow us to distinguish many versions of function definitions for this problem.

def rVSCorrect(word):
    result = '' # initialize state variable for accumulating result string
    inVowelSequence = False # initialize state variable that determines when to add '*'
    for char in word: # iterate over each character in word, using char as iteration variable
        if isVowel(char):
            if not inVowelSequence: # add '*' only when previous char was not vowel
                result += '*'
                inVowelSequence = True # For next time, indicate previous char *was* a vowel
        else: # use else rather than testing `not isVowel(char)`
            result += char # always add a nonvowel to result
            inVowelSequence = False # For next time, indicate previous char was *not* a vowel
    return result

Background: counterexamples

In this problem you will study some correct and incorrect definitions for replaceVowelSequences and determine why the incorrect ones don't work. Incorrect programs are said to be buggy because they contain bugs = reasons why they don't work. So your goal is to track down the bugs in each of the buggy function definitions, or convince yourself that a definition is correct.

One way to show that a function definition is buggy is to provide a counterexample, which is a particular input on which the function does not behave correctly. For a counterexample, the buggy function might return a wrong answer, or it might crash with an error when the correct function does not.

First buggy function example: rVSBuggy1

Here is a function rVSBuggy1 that is an incorrect version of replaceVowelSequences:

def rVSBuggy1(word):
    result = ''
    inVowelSequence = False
    for char in word:
        if isVowel(char):
            result += '*'
            inVowelSequence = True
        else:
            result += char
            inVowelSequence = False
    return result

The bug in this function is that it doesn't check the state variable inVowelSequence to determine whether * should be added to result, so it replaces every vowel by *. For example: rVSBuggy1('seafood') returns the incorrect result 's**f**d' rather than the correct result 's*f*d'. 'seafood' is a counterexample for rVSBuggy1 because it illustrates that the function does not behave correctly. Any string with two or more consecutive vowels is a counterexample for rVSBuggy1, such as 'loud', 'amnesia', or 'aa'.

rVSBuggy1 will work correctly on strings that do not contain two vowels in a row, so such strings are not counterexamples. For example, 'dog', 'stethoscope', 'a', 'dry', and '' are not counterexamples for rVSBuggy1.

A counterexample is minimal if it the shortest counterexample for a function. For rVSBuggy1, any string consisting of exactly two vowels is a minimal counterexample, such as 'aa' or 'ou'.

Second buggy function example: rVSBuggy2

Here is another incorrect definition of replaceVowelSequences :

def rVSBuggy2(word):
    i = 0 # i is index of current char                                                                       
    while i < len(word):
        if isVowel(word[i]):
            result += '*' # Add * for first vowel in sequence                                                
            i += 1
            while isVowel(word[i]) and i < len(word): 
                # Skip to next nonvowel or end of word                                                       
                i += 1
        else:
            result += word[i] # Add nonvowel                                                                 
            i += 1
    return result

This function ignores the strategy illustrated by the iteration table, and violates the requirements by using nested while loops rather than a single for loop. Nevertheless, it is close to having the correct behavior. It uses an index variable i to traverse the characters word[i] in the string. It copies nonvowels to result. When it encounters a vowel, it adds '*' to result, and then uses the nested while loop to find the next nonvowel or end of the word. Because it checks isVowel(word[i]) before i < len(word), it will crash with an Index Error when i becomes equal to len(word). This will happen for any string that ends in a vowel, such as 'like', 'amnesia', 'sequoia', and 'a'. Minimal counterexamples for rVSBuggy2 are strings with a single vowel, such as 'a' or 'e'.

Interestingly, rVSBuggy2 behaves correctly for strings in which at least one nonvowel follows every sequence of values, such as 'dog', 'seafood', and 'audacious'. And it would have the correct behavior on all strings if the inner while loop test were changed to i < len(word) and isVowel(word[i])

Your Task

The file replaceVowelSequences.py contains 12 definitions of the replaceVowelSequences function, which are named rVS01 through rVS12. Some of these definitions are correct and some are buggy. These 12 functions are shown below.

At the bottom of the file are 12 variables named counterexample01 through counterexample12 that are by default assigned to be None, and 12 variables named explanation01 through explanation12 that are by default assigned to be None.

Your task is to change the assignment of these 12 pairs of variables as follows.

Below are the 12 versions of replaceVowelSequences you will study in this problem. Almost all of these functions are based on actual student solutions from a previous midterm exam, though in many cases they have been edited to simplify them, correct bugs, rename variables consistently, etc.

def rVS01(word):
    result = ''
    inVowelSequence = False
    for char in word:
        if isVowel(char) and inVowelSequence:
            result += '*'
            inVowelSequence = True
        elif not isVowel(char):
            result += char
            inVowelSequence = False
    return result

def rVS02(word):
    result = ''
    inVowelSequence = False
    for char in word:
        if isVowel(char):
            result += ''
            inVowelSequence = True
            if inVowelSequence:
                result += '*'
                else:
            result += char
    return result

def rVS03(word):
    result = ''
    inVowelSequence = False
    for char in word:
        if inVowelSequence:
            if not isVowel(char):
                result += '*'
                inVowelSequence = False
        elif isVowel(char):
            inVowelSequence = True
        else:
            result += char
    return result

def rVS04(word):
    result = ''
    inVowelSequence = False
    for char in word:
        if inVowelSequence:
            if not isVowel(char):
                result += char
                inVowelSequence = False
        elif isVowel(char):
            result += '*'
            inVowelSequence = True
        else:
            result += char
            inVowelSequence = False
    return result

def rVS05(word):
    result = ''
    inVowelSequence = False
    for char in word:
        if not isVowel(char):
            result += char
            inVowelSequence = False
        else:
            inVowelSequence = True
        if inVowelSequence:
            if result[-1] != '*':
                result += '*'
    return result

def rVS06(word):
    result = ''
    inVowelSequence = False
    for char in word:
        if inVowelSequence:
            if not isVowel(char):
                inVowelSequence = False
                result += char
        elif isVowel(char):
            inVowelSequence = True
            result += '*'
    return result

def rVS07(word):
    result = ''
    inVowelSequence = False
    for char in word:
        if not isVowel(char):
            result += char
        elif inVowelSequence:
            result += '*'
            inVowelSequence = True
        else:
            inVowelSequence = True
    return result

def rVS08(word):
    result = ''
    for char in word:
        if not isVowel(char):
            result += char
        else:
            inVowelSequence = '*' in result
            if not inVowelSequence:
                result += '*'
    return result

def rVS09(word):
    result = ''
    inVowelSequence = False
    counter = 0
    for char in word:
        if isVowel(char):
            inVowelSequence = True
        else:
            inVowelSequence = False
        if not inVowelSequence:
            result += char
        elif counter == 0 or not isVowel(word[counter-1]):
            result += '*'
        counter += 1
    return result

def rVS10(word):
    result = ''
    vowels = ''
    for char in word:
        if isVowel(char):
            vowels = '*'
        else:
            result += vowels
            vowels = ''
            result += char
    return result

def rVS11(word):
    result = ''
    vowelSequence = ''
    for char in word:
        if isVowel(char):
            vowelSequence += char
        else:
            vowelSequence = ''
        for element in vowelSequence:
            result += '*'
        if not isVowel(char):
            result += char
    return result

def rVS12(word):
    result = ''
    i = 0 # i is index of current char                                                                       
    while i < len(word):
        if isVowel(word[i]):
            if not isVowel(word[i-1]):
                result += '*' # Add * only for first vowel in sequence                                       
        else:
            result += word[i] # Add nonvowel                                                                 
        i += 1
    return result

 


Task 5: Honor Code Form

As in the previous psets, your honor code submission for this pset will involve defining entering values for the variables in the honorcode.py file.


How to turn in this Problem Set

Softcopy (electronic) submission

Hardcopy (paper) submission

There is no hardcopy submission. Problem set submission is entirely electronic.