Download the ICStunes program (http://www.ics.uci.edu/~harris/python/ICStunes0.p
ID: 666781 • Letter: D
Question
Download the ICStunes program (http://www.ics.uci.edu/~harris/python/ICStunes0.py) on the lab machine (or whatever machine you and your partner are using) and run it to make sure it works. As you work on this part, make your changes in (copies of) the ICStunes.py file you downloaded; use your lab8.py file for the other parts of this assignment.
(2) As we did previously with the albums' year, title, length, and ID, write a key function and a call to the sort() method to sort the collection MUSIC by the number of tracks on each album, lowest to highest; then print the resulting collection using Album_str.
Next, sort the collection MUSIC by some other key to rearrange it. Then perform the number-oftracks sorting task by calling collection_sort and then printing the resulting sorted collection
(3) Write a function called unplayed_songs that takes a music collection (a list of albums) and returns a list of Songdisplays, one for each song that has never been played. Print the resulting list using Songdisplay_str. [Please note: At this point it should be clear to everyone that the print statement does not go inside the unplayed_songs function. That function, as specified above, returns a list of Songdisplays; you print that result in the calling program—where you call the function. That's what this problem specifies.]
(4) Write a function called length_from_songdisplay that takes a Songdisplay and returns the length of the song. (This is quick and easy.)
(5) Write a function called favorite_album that takes a list of albums and returns the album that is the "favorite." We'll define the favorite album as the one that the user has spent the most time listening to. [The total time the user has spent listening to an album is computed from the play counts and the song lengths.]
Figure out by hand which album in the collection MUSIC has the greatest listening time (it's okay to collaborate with your classmates outside of your partnership on this specific fact); then print (using Album_str, of course) the result of calling favorite_album on the collection MUSIC and see if it matches. [Hint: Songdisplays aren't involved in this part.]
Explanation / Answer
Note:
Solution:
from collections import namedtuple
#######################################
# Album, Song
#######################################
Album = namedtuple('Album', 'id artist title year songs')
# id is a unique ID number; artist and title are strings; year is a number,
# the year the song was released; songs is a list of Songs
Song = namedtuple('Song', 'track title length play_count')
# track is the track number; title is a string; length is the number of
# seconds long the song is; play_count is the number of times the user
# has listened to the song
MUSIC = [
Album(1, "Peter Gabriel", "Up", 2002,
[Song(1, "Darkness", 411, 5),
Song(2, "Growing Up", 453, 5),
Song(3, "Sky Blue", 397, 2),
Song(4, "No Way Out", 473, 2),
Song(5, "I Grieve", 444, 2),
Song(6, "The Barry Williams Show", 735, 1),
Song(7, "My Head Sounds Like That", 389, 1),
Song(8, "More Than This", 362, 1),
Song(9, "Signal to Noise", 456, 2),
Song(10, "The Drop", 179, 1)]),
Album(2, "Simple Minds", "Once Upon a Time", 1985,
[Song(1, "Once Upon a Time", 345, 9),
Song(2, "All the Things She Said", 256, 10),
Song(3, "Ghost Dancing", 285, 7),
Song(4, "Alive and Kicking", 326, 26),
Song(5, "Oh Jungleland", 314, 13),
Song(6, "I Wish You Were Here", 282, 12),
Song(7, "Sanctify Yourself", 297, 7),
Song(8, "Come a Long Way", 307, 5)]),
Album(3, "The Postal Service", "Give Up", 2003,
[Song(1, "The District Sleeps Alone", 284, 13),
Song(2, "Such Great Heights", 266, 13),
Song(3, "Sleeping In", 261, 12),
Song(4, "Nothing Better", 226, 18),
Song(5, "Recycled Air", 269, 13),
Song(6, "Clark Gable", 294, 12),
Song(7, "We Will Become Silhouettes", 300, 11),
Song(8, "This Place is a Prison", 234, 9),
Song(9, "Brand New Colony", 252, 9),
Song(10, "Natural Anthem", 307, 7)]),
Album(4, "Midnight Oil", "Blue Sky Mining", 1989,
[Song(1, "Blue Sky Mine", 258, 12),
Song(2, "Stars of Warburton", 294, 11),
Song(3, "Bedlam Bridge", 266, 11),
Song(4, "Forgotten Years", 266, 8),
Song(5, "Mountains of Burma", 296, 9),
Song(6, "King of the Mountain", 231, 8),
Song(7, "River Runs Red", 322, 9),
Song(8, "Shakers and Movers", 268, 9),
Song(9, "One Country", 353, 7),
Song(10, "Antarctica", 258, 6)]),
Album(5, "The Rolling Stones", "Let It Bleed", 1969,
[Song(1, "Gimme Shelter", 272, 3),
Song(2, "Love In Vain", 259, 2),
Song(3, "Country Honk", 187, 0),
Song(4, "Live With Me", 213, 2),
Song(5, "Let It Bleed", 327, 2),
Song(6, "Midnight Rambler", 412, 1),
Song(7, "You Got the Silver", 170, 0),
Song(8, "Monkey Man", 251, 13),
Song(9, "You Can't Always Get What You Want", 448, 10)])
]
#######################################
# Sorting the collection
#######################################
# Sort the collection into chronological order
# The 'key=' argument of sort() takes a function---that function
# takes an album and produces the value that will be used for
# comparisons in the sort.
# So first we define that function
def Album_year(A: Album) -> int:
''' Return the album's year
'''
return A.year
MUSIC.sort(key=Album_year) # Oldest to newest
assert(MUSIC[0].title == "Let It Bleed") # Kind of a half-hearted test
assert(MUSIC[-1].title == "Give Up")
MUSIC.sort(key=Album_year, reverse=True) # Newest to oldest
assert(MUSIC[0].title == "Give Up") # Kind of a half-hearted test
assert(MUSIC[-1].title == "Let It Bleed")
# Sort the collection by Album title
def Album_title(A: Album) -> str:
''' Return the album's title
'''
return A.title
MUSIC.sort(key=Album_title)
assert(MUSIC[0].title == "Blue Sky Mining") # Kind of a half-hearted test
assert(MUSIC[-1].title == "Up")
# Sort the collection by length (playing time) of album
def Album_length(a: Album) -> int:
''' Return the total length of all the songs in the album
'''
total_length = 0
for s in a.songs:
total_length += s.length
return total_length
MUSIC.sort(key=Album_length)
assert(MUSIC[0].title == "Once Upon a Time") # Kind of a half-hearted test
assert(MUSIC[-1].title == "Up")
# Sort the collection by Album id (as above)
def Album_id(A: Album) -> str:
''' Return the album's number
'''
return A.id
MUSIC.sort(key=Album_id)
## We can also write a conventional function to sort a collection, so
## we could say collection_sort(MUSIC, Album_length) instead of using
## the method notation MUSIC.sort(key=Album_length). We do this by
## PASSING A FUNCTION AS A PARAMETER (like the interchangeable
## attachment on a robot arm).
def collection_sort(C: 'list of Album', keyfunction: 'Function on Albums') -> None:
''' Sort collection according to specified key function
Note that this function, like the sort() method, sorts the collection
IN PLACE (by reference), so it changes the argument it was called with.
That's why it doesn't RETURN anything.
'''
C.sort(key=keyfunction)
return
collection_sort(MUSIC, Album_title)
assert(MUSIC[0].title == "Blue Sky Mining") # Kind of a half-hearted test
assert(MUSIC[-1].title == "Up")
collection_sort(MUSIC, Album_id) # Just to put it back in the original order
#######################################
# Top 10 most frequently played songs
#######################################
# Collect all the songs out of all the albums.
# To find the MOST frequent, just use the find-largest (king-of-the-hill) algorithm
# To find the top N is hard to code that way.
# Better: Take the list of songs, sort by play_count, take first 10 -- songlist[:10]
def Song_play_count(s: Song) -> int:
''' Return the number of times this song has been played
'''
return s.play_count
def all_songs(MC: 'list of Album') -> 'list of Song':
''' Return a list of all the Songs in a music collection (list of Album)
'''
result = [ ]
for a in MC:
result.extend(a.songs)
return result
Songlist = all_songs(MUSIC)
assert(Songlist[0] == Song(1, "Darkness", 411, 5))
assert(Songlist[1] == Song(2, "Growing Up", 453, 5))
assert(Songlist[-1] == Song(9, "You Can't Always Get What You Want", 448, 10))
def top_n_played_songs(MC: 'list of Album', n: int) -> 'list of Song':
''' Return a list of the n most frequently played songs in MC
'''
Songlist = all_songs(MC)
Songlist.sort(key=Song_play_count, reverse=True)
return Songlist[:n]
assert(top_n_played_songs(MUSIC, 5) ==
[Song(4, "Alive and Kicking", 326, 26),
Song(4, "Nothing Better", 226, 18),
Song(5, "Oh Jungleland", 314, 13),
Song(1, "The District Sleeps Alone", 284, 13),
Song(2, "Such Great Heights", 266, 13)])
###################################
# Song-displays
###################################
# But these songs don't have their album information! We removed it when we created
# the list of all songs. If we want to display selected songs on our iPod screen,
# we'd want to have the album information along with the song information.
# We could flatten out our data structure, storing a copy of the album
# information with each song:
# 1 Up Peter Gabriel 2002 1 Darkness 411 5
# 1 Up Peter Gabriel 2002 2 Growing Up 453 8
# 1 Up Peter Gabriel 2002 3 Sky Blue 397 2
# ...
# This would work, but there's a lot of duplicate data---it would be wasteful of storage
# and error-prone to store our music data this way permanently.
# Instead, let's just get the album info that goes with a song WHEN WE NEED IT,
# during the computation. To do this, we define a structure that contains the
# info we need to display a song (on our iPod screen, e.g.)---song details plus
# the info we need from that song's album:
Songdisplay = namedtuple('Songdisplay', 'artist a_title year track s_title length play_count')
# We'll create these structures as we need them during the computation,
# discarding them as we're done; this doesn't affect the main, permanent
# list of albums (like the one we defined as MUSIC above).
def all_Songdisplays(MC: 'list of Album') -> 'list of Songdisplay':
''' Return a list of all the songs in the collection MC, in Songdisplay form
'''
result = [ ]
for a in MC:
result.extend(Album_to_Songdisplays(a))
return result
def Album_to_Songdisplays(a: Album) -> 'list of Songdisplay':
''' Return a list of Songdisplays, one for each song in the album
'''
result = [ ]
for s in a.songs:
result.append(Songdisplay(a.artist, a.title, a.year,
s.track, s.title, s.length, s.play_count))
return result
def play_count_from_songdisplay(sd: Songdisplay) -> int:
''' Return the play_count from a Songdisplay
'''
return sd.play_count
def top_n_played(MC: 'list of Album', n: int) -> 'list of Songdisplay':
''' Return the top n most frequently played songs in MC
'''
list_of_Songdisplays = all_Songdisplays(MC)
list_of_Songdisplays.sort(key=play_count_from_songdisplay, reverse=True)
return list_of_Songdisplays[:n]
test_list = top_n_played(MUSIC, 3)
assert(test_list[0].s_title == "Alive and Kicking")
assert(test_list[0].a_title == "Once Upon a Time")
assert(test_list[-1].s_title == "Oh Jungleland")
assert(test_list[-1].a_title == "Once Upon a Time")
#Q2
'''Method to return number of tracks'''
def Album_tracknum(al:Album)->int:
counttrack = 0
for s in al.songs:
counttrack+=1
return counttrack
collection_sort(mu,Album_tracknum)
for in in mu:
print(Album_str(in))
mu.sort(key = Album_id)
print(collection_sort(MUSIC,Album_tracknum))
#Q3
'''Method to returns list of Song displays'''
def unplayed_songs(mic:'List of Albums')->list:
tre = []
for album in mic:
for song in album.songs:
if Song_play_count(song) == 0:
tre.append(song)
return tre
print(Songdisplay_str(unplayed_songs(MUSIC)))
#Q4
''' Method to return the length '''
def length_from_songdisplay(sd:Songdisplay)->int:
return sd.length
#Q5
'''Method to returns total time of listening '''
def Song_listening_time(s:Song)->int:
return s.play_count * s.length
'''Method to returns total time'''
def Album_listening_time(al:Album)->int:
tottime = 0
for in in al.songs:
tottime += Song_listening_time(in)
return tottime
''' Method to Returns favorite album'''
def favorite_album(mic:'List of Albums')->list:
f_albm = []
collection_sort(mic,Album_listening_time)
f_albm.append(mic[-1])
return f_albm
for in in favorite_album(mu):
print("Favorite Album: " , Album_str(in))
#Q6
'''Method to returns a list'''
def top_n(mic: 'list of Album', n:int, funcname,Bool)->'list of Songdisplay':
lstsng_dsply = all_Songdisplays(mic)
lstsng_dsply.sort(key = funcname, reverse = Bool)
return lstsng_dsply[:n]
Songdisplay_str(top_n(mu, 3, play_count_from_songdisplay, True))
#Q7
'''Method to returns a list'''
def favorite_album2(mic:'List of album',fav_measure)->list:
nwlst = []
collection_sort(mic,fav_measure)
nwlst.append(mic[-1])
return(nwlst)
def Song_count(s:Song)->int:
return s.play_count
def Album_count(al:Album)->int:
totcnt = 0
for in in al.songs:
totcnt += Song_count(in)
return totcnt
for in in (favorite_album2(mu,Album_count)):
print(Album_str(in))
Related Questions
drjack9650@gmail.com
Navigate
Integrity-first tutoring: explanations and feedback only — we do not complete graded work. Learn more.