-1

I'm a guitarist who wants to create himself a playlist of songs to play from all songs that I know. Knowing a couple now, I just want to play for 30 min.

For this, my idea is to create a dictionary with song title and duration of the song. I would like to make a random choice of songs, whose duration doesn't surpass 30 min.

My issues are how do I write down the minutes and seconds of a song?

My idea is:

Playlist = {"Before I Forget": 4.21, "Unsainted":4.20.....}

But that stores the information as a float.

Any advice?

SiHa
  • 7,830
  • 13
  • 34
  • 43
  • "But that stores the information as a float" is that a problem ? why? – seralouk Jul 14 '20 at 11:49
  • 1
    Time has a strange counting system, it's probably easier if you do all calculations internally in seconds :-) – cel Jul 14 '20 at 11:51
  • Thanks for the seconds tip! Regarding as to why storing the information as a float is bad...A minute are 60 secodns...a float will sum numbers till its a 100..not 60. – Christian J.S. Schulze Aguiar Jul 14 '20 at 12:06
  • Check out https://stackoverflow.com/questions/51846547/how-to-convert-float-into-hours-minutes-seconds – ok4 Jul 14 '20 at 13:38

1 Answers1

0

Couple of different ways you can do this. There is an optimal solution that gets you as close to your target as possible but you want the playlist to be random and everything to get a play eventually so something like this should do the job...

from random import randint, shuffle

# create some tracks between 2-4 minutes for testing
tracks = { "Track {0}".format(i): "{0}:{1:02d}".format(randint(2, 3), randint(0, 59)) for i in range(20) }
print(tracks)

# covert to a list of elements with the time in seconds
def min_to_sec(x):
    m, s = x.split(":")
    return int(m) * 60 + int(s)
items = [ (k, min_to_sec(v)) for k, v in tracks.items() ]

# randomise
shuffle(items)

# a function that sums the lengths from an index position till
# it exceeds the max.
def select_tracks(items, index, max_seconds):
    total = 0
    selected = []
    for name, length in items[index:]:
        if total + length > max_seconds:
            break
        total += length
        selected.append(name)

    return total, selected


# run at each start position
results = [ select_tracks(items, i, 30*60) for i in range(len(items)) ]

# if we sort and select the last that is the best for this randomised order
results.sort()
playlist = results[-1]

print("\nPlaylist: {0} ({1} seconds)".format(", ".join(playlist[1]), playlist[0]))

Output:

{'Track 0': '2:51', 'Track 1': '2:25', 'Track 2': '3:21', 'Track 3': '3:03', 'Track 4': '3:22', 'Track 5': '3:03', 'Track 6': '3:32', 'Track 7': '3:58', 'Track 8': '3:40', 'Track 9': '2:16', 'Track 10': '3:32', 'Track 11': '3:52', 'Track 12': '3:03', 'Track 13': '2:37', 'Track 14': '2:45', 'Track 15': '2:57', 'Track 16': '3:19', 'Track 17': '3:06', 'Track 18': '2:15', 'Track 19': '3:05'}

Playlist: Track 5, Track 14, Track 18, Track 9, Track 8, Track 17, Track 10, Track 19, Track 2, Track 0 (1794 seconds)
Tris Forster
  • 152
  • 4