**Homework 5: dictionaries** **Reed CSCI 121 Spring 2025** *complete the exercises by 9am on 2/4* This week's lab exercises are a mix of problems that have you work with Python lists and with Python dictionaries. We ask you to write a function for each of them. Let me just remind you that lists and dictionaries are both *passed by reference* to a function. This means that it is possible to change the values stored in them, and to increase and decrease their size by applying certain operations to them, within a function's code. These changes can be noticed by the client code that uses the function that changes them. Because of this ability to modify lists and dictionaries, you need to pay careful attention as to whether we want your function to change the data structure it is given, and also whether or not we want you to build and return a new data structure. (#) Problems (##) `[Hw5 Ex1]` word count A Python string made up of words separated by spaces can be split into a list of strings made up of the words as they were strung together. To do so, you use a string operation called `split`, passing it the space character `' '` like so: ~~~ none >>> sentence = "the quick brown fox jumped over the lazy dogs" >>> print(sentence) the quick brown fox jumped over the lazy dogs >>> words = sentence.split(' ') >>> words ['the', 'quick', 'brown', 'fox', 'jumped', 'over', 'the', 'lazy', 'dogs'] >>> "hello there".split(' ') ['hello', 'there'] ~~~ Write a function `def word_count(s)` that takes a string `s` and gives back a dictionary that gives an integer count of the number of times each word appears in `s`. There should be a dictionary entry for every word that appears in `s` and each should have a value of 1 or more that corresponds to the number of times that word appears. ~~~ none >>> word_count("hello there") {'hello': 1, 'there': 1} >>> word_count("buffalo buffalo buffalo buffalo buffalo buffalo buffalo buffalo") {'buffalo': 8} >>> word_count("b a n a n a s") {'a': 3, 'b': 1, 'n': 2, 's': 1} >>> word_count("i am who i am as far as i know" {'as': 2, 'am': 2, 'far': 1, 'i': 3, 'know': 1, 'who': 1} ~~~ You can assume that the string consists of only the letters from `'a'` to `'z'` and spaces, that there are no spaces at the front or end of the string, and that there are never two consecutive spaces. Note that the ordering of dictionary entries produced by Python's report does not matter. Dictionary entries, unlike list entires, are unordered. This means that ~~~ none >>> word_count("hello there") {'there': 1, 'hello': 1} ~~~ is just as correct a result as the result listed before. (##) `[Hw5 Ex2]` word positions Now write a function `word_positions` that also returns a dictionary with an entry for each word that occurs in the text. Rather than a word count, it should instead give the list of positions where the word occurs in the text. (The first word in the text is at position 0.) ~~~ none >>> word_positions("hello there") {'hello': [0], 'there': [1]} >>> word_positions("buffalo buffalo buffalo buffalo buffalo buffalo buffalo buffalo") {'buffalo': [0, 1, 2, 3, 4, 5, 6, 7]} >>> word_positions("b a n a n a s") {'a': [1, 3, 5], 'b': [0], 'n': [2, 4], 's': [6]} >>> word_positions("i am who i am as far as i know") {'as': [5, 7], 'am': [1, 4], 'far': [6], 'i': [0, 3, 8], 'know': [9], 'who': [2]} ~~~ The positions should be listed in increasing odrer. (##) `[Hw5 Ex3]` replace Write a function `replace` that takes a string of text and a dictionary. Each entry in the dictionary is a string with a list of strings. (Each key is a string and its associated value is a list of strings.) The function should return the string of text that results from replacing words with other words as given by the dictionary. For example, if we take the Python string ~~~ ’I heard that name verb activity and activity’ ~~~ and the dictionary ~~~ {’name’:[’Adam’,’Jim’,’Erica’], ’activity ’:[’hiking ’,’biking ’,’liking ’], ’verb ’:[’likes ’,’bikes ’]} ~~~ then, fed these, `replace` would return the string ~~~ ’I heard that Adam likes hiking and biking’ ~~~ If instead we fed `replace` the string ~~~ ’name verb that name is activity and name is activity’ ~~~ with the same dictionary, it would return the string ~~~ ’Adam likes that Jim is hiking and Erica is biking’ ~~~ Your `replace` function should draw replacement words from the list in each dictionary entry in the order they appear in that dictionary entry. (For example, in the last example above, the names are inserted into the string in the same order they appear in the dictionary entry: first `Adam`, then `Jim`, then `Erica`.) You can assume that there are enough words in each entry to perform the replacement on the given string. You can use `split` to convert the text into a list of strings, just like in Exercise 1. A list of strings can be joined together into a single string by using the string `join` operation as shown below ~~~ none >>> words = ['the', 'quick', 'brown', 'fox', 'jumped', 'over', 'the', 'lazy', 'dogs'] >>> sentence = ' '.join(words) >>> sentence 'the quick brown fox jumped over the lazy dogs' >>> ' '.join(['ba','nan','a','s']) 'ba nan a s' ~~~ You don't need to use `join`, but you might try it out if it is convenient for your approach. It is okay to modify the dictionary in order to perform the work of this function. (##) `[Hw5 Ex4]` inverse Write a function `def inverse(d)` which takes a dictionary `d` and returns its "inverse" dictionary, a dictionary mapping values of entries in the given dictionary to lists of keys in the given dictionary. The keys of the dictionary it returns are the the values of the original dictionary and whose entries are lists of keys which mapped to that value in the original dictionary. For example: ~~~ none >>> inverse({'a':'b', 'c':'b', 'cats':'rest', 'world':'hello'}) {'hello':['world'], 'rest':['cats'], 'b':['a', 'c']} >>> inverse({}) {} >>> inverse({'a':'1','b':'1','c':'1','d':'1','e':'1','f':'1','g':'1'}) {'1':['e', 'c', 'f', 'g', 'a', 'd', 'b']} ~~~~ Note that the ordering of dictionary entries produced by Python's report does not matter. Dictionary entries, unlike list entires, are unordered. This means that ~~~ none >>> inverse({'a':'b', 'c':'b', 'cats':'rest', 'world':'hello'}) {'b':['a', 'c'], 'hello':['world'], 'rest':['cats']} ~~~ is just as correct a result as the result listed before. The ordering of the listed values in the inverse dictionary also does not matter. That means that the entry for `'b'` could instead have been `['c', 'a']` in the result reported just above.