Homework Five (retake)

Published

April 4, 2025

Due 2025-04-11 at 11:59p

Submit on Gradescope

This is your second shot at the problems from Homework Five. If you missed any of the problems, you are strongly advised to try again. Your goal is to complete (Satisfactory or Excellent) up to four problem across Homework Five and this set, but you are encouraged to do more – especially if you were challenged by the first set of problems. Remember that we evaluate each problem individually, so there are no issues if you only do a subset of the problems (including none).

Objectives

  • Demonstrate your ability to use lists
  • Demonstrate your ability to use dictionaries
  • Demonstrate your expanding ability to use loops

Getting started

For this assignment, we have another four functions for you to write. Please pay attention to all of these instructions. Even this front matter, which may look the same (and many of you skip over) has changed.

For this assignment, there is no starter code. Please do your work in a file called homework05r.py.

Feel free to work through the functions in any order. Problems 3 and 4 are linked but the ordering doesn’t matter. Whatever order you use, we suggest that you take the time to test each one as you go rather than trying to write all four out like they were part of an essay and then testing at the very end. Treat these are four totally separate and distinct problems (which they are).

Submit your solution on Gradescope using the button above. Feel free to resubmit as your complete each problem to check your progress. To repeat – you only need to submit homework05r.py.

Python subset

For this assignment, the allowed subset varies from problem to problem. Be sure to read each problem carefully.

Satisfactory vs. Excellence

A solution for these questions that is excellent will have the all of the following qualities

Style

An excellent function will have a docstring that is formatted in the way shown in the lectures. It should include:

  • the purpose of the function
  • the type and purpose of each parameter (if any)
  • the type and meaning of the output (if any)

In addition, you should follow some of the PEP8 guidelines on whitespace. The ones we will be looking at are:

  • no whitespace between names and ( or [ (e.g., f (5) should be f(5) and s [3:5] should be s[3:5])
  • there should be a single space around operators (e.g., x=4+1 should be x = 4 + 1 and y = 3 -2 should be y = 3 - 2)
  • there should be a space after commas, but not before (e.g., f(4 , 5) or f(4,5) should be f(4, 5))

Special cases and requirements

For some of the problems, we have identified special cases or requirements that we have deemed potentially more challenging and not essential to a satisfactory solution. An excellent solution will cover all cases. These cases will be identified in the autograder by tests with * at the end of the title (so make sure you submit frequently as you are working).

Problem 1: split

Write a function called split that takes three arguments: text, sep and maxsplit. The function will essentially be a reimplementation of the built in split function, which splits a string into a list of strings. The text parameter is the string to split. The sep parameter will be the string that you separate on (note that they are not included in the resulting strings). This can be more than one character long. The maxsplit parameter says how many splits to make, starting from the front. If this value is -1, it will make all possible splits.

Your solution should use a loop. The only external functions that you are allowed are len, range, and append.

Note: if you are using the built in split function for comparison testing (a good idea!), its behavior is different if you include the separator or not. Without the separator, split defaults to removing whitespace AND it collapses all runs of whitespace into one. if a sep is provided (even if it is a space), split will create empty strings to reflect that there are no characters between the separators. This later behavior is what yours should do.

split
Parameters
text str
sep str
maxsplit int
Return type list

Examples

>>> split("split everything on spaces", " ", -1)
['split', 'everything', 'on', 'spaces']
>>> split("split everything on spaces", " ", 2)
['split', 'everything', 'on spaces']
>>> split("This is another test", "is", -1)
['Th', ' ', ' another test']
>>> split("This is also         a test", " ", -1)
['This', 'is', 'also', '', '', '', '', '', '', '', '', 'a', 'test']

Problem 2: braid

Write a function called braid which takes two parameters, text (the string to be braided) and strands (a positive integer specifying the number of strands in the braid). This function should split the text into multiple pieces and “braid” them together. The braid is created by cycling through the pieces and and taking the next character from each piece.

As an example, use "ABCDEFGHI" as text and set strands to 3. Breaking this into three “strands” would give us "ABC", "DEF", and "GHI". We then cycle through taking the first character from each piece ("ADG"), and then the second ("ADGBEH"), and then finally the third, to give us "ADGBEHCFI".

In the case that the number of characters is not evenly divisible by the number of strands, the we add the spare to the strands from left to right. Consider the following if strands is 3.

text strands braid
"abcdef" "ab", "cd", "ef" "acebdf"
"abcdefg" "abc", "de", "fg" "adfbegc"
"abcdefgh" "abc", "def", "gh" "adgbehcf"
braid
Parameters
text str
strands int (> 0)
Return type str

Examples

>>> braid("abcdef", 3)
'acebdf'
>>> braid("abcdefg", 3)
'adfbegc'
>>> braid("abcdefh", 3)
'adfbehc'
>>> braid("abcdefhi", 3)
'adhbeicf'
>>> braid("abcdefhi", 4)
'acehbdfi'
>>> braid("1234567890", 2)
'1627384950'
>>> braid("ab", 3)
'ab'

Problem 3: find_tracks

Write a function called find_tracks that takes in a music library (library) and a string (query). Your function should find all tracks in the library that have a matching name and return a list of dictionaries describing the identified tracks. You should return any track that matches query, regardless of case. query can also be a partial match. For example, a query of "edge" would return information for "From the Edge of the Deep Green Sea".

The returned track list should contains dictionaries with the keys: "track" (full track name), "artist" (artist name), and "album" (the name of the album).

The library should be of the form we developed in class.

  • the library is a dictionary, where artist names are the keys
  • the values of the top level library are lists of albums
  • albums are dictionaries with the keys: "name", "year", and "tracks"
  • the value mapped to "name" is a string
  • the value mapped to "year" is an integer
  • the value mapped to "tracks" is a list of strings

So you don’t need to create your own library, we are including the sample that is basically the same one we were playing with in class. You can copy the data wherever you like. If you put the .py file in the same directory as your file, you can import it using import data in either your file or in the shell. The data can then be accessed with data.music_library. However, while you can pass this library in for testing, do not reference this library directly in your function.

data.py.zip

Hint: remember that the in operator works on strings.

find_tracks
Parameters
library dict (keys: artist names, values: list of albums)
query str
Return type list (of dictionaries with keys “track”, “artist”, “album”)

Examples

>>> find_tracks(data.music_library, "Open")
[{'track': 'Open', 'artist': 'The Cure', 'album': 'Wish'}]
>>> find_tracks(data.music_library, "Deeper into This")
[]
>>> find_tracks(data.music_library, "Day of the Lords")
[{'track': 'Day of the Lords', 'artist': 'Joy Division', 'album': 'Unknown Pleasures'}, {'track': 'Day of the Lords', 'artist': '16 Horsepower', 'album': 'Hoarse'}]
>>> find_tracks(data.music_library, "pig")
[{'track': 'Pigs on the Wing (part one)', 'artist': 'Pink Floyd', 'album': 'Animals'}, {'track': 'Pigs (Three Different Ones)', 'artist': 'Pink Floyd', 'album': 'Animals'}, {'track': 'Pigs on the Wing (part two)', 'artist': 'Pink Floyd', 'album': 'Animals'}]

Problem 4: reorganize

Write a function called reorganize that takes in a music library called library. This function we reorganize the data to use a different structure organized by year.

The input structure is the same music library found in the previous problem.

The output should be a new dictionary with this form:

  • the keys of the library are integers – the year
  • the values of the new library are lists of the albums from that year
  • the albums are dictionaries with keys for "artist", "album" and "tracks"
  • the value mapped to"artist" is a string (the name of the artist)
  • the value mapped to "album" is a string (the name of the album)
  • the value mapped to "tracks" is a list of strings (the track names)
reorganize
Parameters
library dict (keys: artist names, values: list of albums)
Return type dict (keys: year, values: list of albums)

Examples

>>> reorganize(data.music_library)
{1977: [{'artist': 'Pink Floyd', 'album': 'Animals', 'tracks': ['Pigs on the Wing (part one)', 'Dogs', 'Pigs (Three Different Ones)', 'Sheep', 'Pigs on the Wing (part two)']}], 1973: [{'artist': 'Pink Floyd', 'album': 'Dark Side of the Moon', 'tracks': ['Speak to Me', 'Breathe (In the Air)', 'On the Run', 'Time', 'The Great Gig in the Sky', 'Money', 'Us and Them', 'Any Colour You Like', 'Brain Damage', 'Eclipse']}], 1979: [{'artist': 'Joy Division', 'album': 'Unknown Pleasures', 'tracks': ['Disorder', 'Day of the Lords', 'Candidate', 'Insight', 'New Dawn Fades', "She's Lost Control", 'Shadowplay', 'Wilderness', 'Interzone', 'I Remember Nothing']}, {'artist': 'The Cure', 'album': 'Three Imaginary Boys', 'tracks': ['10:15 Saturday Night', 'Accuracy', 'Grinding Halt', 'Another Day', 'Object', 'Subway Song', 'Foxy Lady', 'Meat Hook', 'So What', 'Fire in Cairo', "It's Not You", 'Three Imaginary Boys', 'The Weedy burton']}], 2024: [{'artist': 'The Cure', 'album': 'Songs of a Lost World', 'tracks': ['Alone', 'And Nothing is Forever', 'A Fragile Thing', 'Warsong', 'Drone:nodrone', 'I Can Never Say Goodbye', 'All I Ever Am', 'Endsong']}], 1992: [{'artist': 'The Cure', 'album': 'Wish', 'tracks': ['Open', 'High', 'Apart', 'From the Edge of the Deep Green Sea', 'Wendy Time', 'Doing the Unstuck', "Friday I'm in Love", 'Trust', 'A Letter to Elise', 'Cut', 'To Wish Impossible Things', 'End']}], 2001: [{'artist': '16 Horsepower', 'album': 'Hoarse', 'tracks': ['American Wheeze', 'Black Soul Choir', "Bad Moon Risin'", 'Low Estate', "For Heaven's Sake", 'Black Lung', 'Horse Head', 'South Pennsylvania Waltz', 'Brimstone Rock', 'Fire Spirit', 'Day of the Lords']}]}