After playing a given song, use a pseudo-append to place it near the end of the list. You'll probably want about 1/2 to 2/3 to be truly appended and the other 1/3 to 1/2 spread within the last 5 or so items in the list.
Obviously this won't work for very short lists, but should be fine for lists of 10 or more.
Edit (provide more detail about 'PseudoAppend'):
The following pseudo-code uses a mix of language constructs but should be easy enough to turn into real code.
Given List[songs]
While(PLAY)
Play(List[0])
PseudoAppend(List[], 0)
def PseudoAppend(List[], index)
# test to verify length of list, valid index, etc.
song = List[index].delete # < not safe
List.append(song)
target = -1
While( (random() < (1/3)) && (target > -3) )
Swap(List[target], List[target-1])
target -= 1
Removing the just-completed song from the list without first having a backup list can result in information loss, but this is just pseudo-code meant to convey an idea.
As you can see, 2/3 of the time the song that was just played will be moved to the back of the list, and 1/3 of the time it will be moved ahead of the last song.
Of the 1/3 chance that the song is moved forward, 2/3 of the time it will only be moved ahead of one song, and the other 1/3 of the time it will be moved ahead of two or more songs. Chance that song moves to last position=66%, second to last position=22%, third to last=12%.
The actual behavior of the PseudoAppend is all governed within the condition of the While
statement. You can change the value to compare against the random
number generator to make it more or less likely that a song is moved ahead of others, and you can change the value compared to target
to adjust how far the just-completed song can move ahead in the list.
Edit II (Python 3 code and sample output for a list of 11 items)
songlist=[0,1,2,3,4,5,6,7,8,9,10]
import random
def pseudoappend(locallist, index):
song=locallist[index]
del(locallist[index])
locallist.append(song)
target=-1
while (random.randint(1,3)==1) and (target> -3):
locallist[target],locallist[target-1] = locallist[target-1],locallist[target]
target-=1
for x in range(len(songlist)*9):
print("%3d" % x, ': ', "%2d" % songlist[0], ': ', songlist)
pseudoappend(songlist, 0)
print( 'end : ', "%2d" % songlist[0], ': ', songlist)
Here's a sample output running through the list ~9 times. The first column is simply a running index, the second column shows the currently selected song, and the third column shows the current order of the list:
>>> ================================ RESTART ================================
>>>
0 : 0 : [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
1 : 1 : [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 0]
2 : 2 : [2, 3, 4, 5, 6, 7, 8, 9, 10, 0, 1]
3 : 3 : [3, 4, 5, 6, 7, 8, 9, 10, 0, 1, 2]
4 : 4 : [4, 5, 6, 7, 8, 9, 10, 0, 1, 2, 3]
5 : 5 : [5, 6, 7, 8, 9, 10, 0, 1, 2, 3, 4]
6 : 6 : [6, 7, 8, 9, 10, 0, 1, 2, 3, 4, 5]
7 : 7 : [7, 8, 9, 10, 0, 1, 2, 3, 4, 5, 6]
8 : 8 : [8, 9, 10, 0, 1, 2, 3, 4, 5, 6, 7]
9 : 9 : [9, 10, 0, 1, 2, 3, 4, 5, 6, 7, 8]
10 : 10 : [10, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
11 : 0 : [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
12 : 1 : [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 0]
13 : 2 : [2, 3, 4, 5, 6, 7, 8, 9, 10, 1, 0]
14 : 3 : [3, 4, 5, 6, 7, 8, 9, 10, 1, 0, 2]
15 : 4 : [4, 5, 6, 7, 8, 9, 10, 1, 0, 2, 3]
16 : 5 : [5, 6, 7, 8, 9, 10, 1, 0, 2, 3, 4]
17 : 6 : [6, 7, 8, 9, 10, 1, 0, 2, 3, 4, 5]
18 : 7 : [7, 8, 9, 10, 1, 0, 2, 3, 4, 6, 5]
19 : 8 : [8, 9, 10, 1, 0, 2, 3, 4, 6, 7, 5]
20 : 9 : [9, 10, 1, 0, 2, 3, 4, 6, 7, 5, 8]
21 : 10 : [10, 1, 0, 2, 3, 4, 6, 7, 5, 8, 9]
22 : 1 : [1, 0, 2, 3, 4, 6, 7, 5, 10, 8, 9]
23 : 0 : [0, 2, 3, 4, 6, 7, 5, 10, 8, 9, 1]
24 : 2 : [2, 3, 4, 6, 7, 5, 10, 8, 9, 1, 0]
25 : 3 : [3, 4, 6, 7, 5, 10, 8, 9, 2, 1, 0]
26 : 4 : [4, 6, 7, 5, 10, 8, 9, 2, 1, 0, 3]
27 : 6 : [6, 7, 5, 10, 8, 9, 2, 1, 0, 3, 4]
28 : 7 : [7, 5, 10, 8, 9, 2, 1, 0, 3, 4, 6]
29 : 5 : [5, 10, 8, 9, 2, 1, 0, 3, 4, 6, 7]
30 : 10 : [10, 8, 9, 2, 1, 0, 3, 4, 5, 6, 7]
31 : 8 : [8, 9, 2, 1, 0, 3, 4, 5, 10, 6, 7]
32 : 9 : [9, 2, 1, 0, 3, 4, 5, 10, 6, 7, 8]
33 : 2 : [2, 1, 0, 3, 4, 5, 10, 6, 7, 9, 8]
34 : 1 : [1, 0, 3, 4, 5, 10, 6, 7, 9, 8, 2]
35 : 0 : [0, 3, 4, 5, 10, 6, 7, 9, 8, 2, 1]
36 : 3 : [3, 4, 5, 10, 6, 7, 9, 8, 2, 1, 0]
37 : 4 : [4, 5, 10, 6, 7, 9, 8, 2, 1, 0, 3]
38 : 5 : [5, 10, 6, 7, 9, 8, 2, 1, 0, 3, 4]
39 : 10 : [10, 6, 7, 9, 8, 2, 1, 0, 3, 4, 5]
40 : 6 : [6, 7, 9, 8, 2, 1, 0, 3, 4, 5, 10]
41 : 7 : [7, 9, 8, 2, 1, 0, 3, 4, 5, 10, 6]
42 : 9 : [9, 8, 2, 1, 0, 3, 4, 5, 7, 10, 6]
43 : 8 : [8, 2, 1, 0, 3, 4, 5, 7, 10, 6, 9]
44 : 2 : [2, 1, 0, 3, 4, 5, 7, 10, 6, 9, 8]
45 : 1 : [1, 0, 3, 4, 5, 7, 10, 6, 2, 9, 8]
46 : 0 : [0, 3, 4, 5, 7, 10, 6, 2, 9, 8, 1]
47 : 3 : [3, 4, 5, 7, 10, 6, 2, 9, 8, 1, 0]
48 : 4 : [4, 5, 7, 10, 6, 2, 9, 8, 1, 3, 0]
49 : 5 : [5, 7, 10, 6, 2, 9, 8, 1, 3, 0, 4]
50 : 7 : [7, 10, 6, 2, 9, 8, 1, 3, 5, 0, 4]
51 : 10 : [10, 6, 2, 9, 8, 1, 3, 5, 0, 7, 4]
52 : 6 : [6, 2, 9, 8, 1, 3, 5, 0, 7, 4, 10]
53 : 2 : [2, 9, 8, 1, 3, 5, 0, 7, 6, 4, 10]
54 : 9 : [9, 8, 1, 3, 5, 0, 7, 6, 4, 10, 2]
55 : 8 : [8, 1, 3, 5, 0, 7, 6, 4, 10, 2, 9]
56 : 1 : [1, 3, 5, 0, 7, 6, 4, 10, 2, 9, 8]
57 : 3 : [3, 5, 0, 7, 6, 4, 10, 2, 9, 1, 8]
58 : 5 : [5, 0, 7, 6, 4, 10, 2, 9, 3, 1, 8]
59 : 0 : [0, 7, 6, 4, 10, 2, 9, 3, 1, 8, 5]
60 : 7 : [7, 6, 4, 10, 2, 9, 3, 1, 8, 5, 0]
61 : 6 : [6, 4, 10, 2, 9, 3, 1, 8, 5, 0, 7]
62 : 4 : [4, 10, 2, 9, 3, 1, 8, 5, 0, 7, 6]
63 : 10 : [10, 2, 9, 3, 1, 8, 5, 0, 7, 6, 4]
64 : 2 : [2, 9, 3, 1, 8, 5, 0, 7, 6, 4, 10]
65 : 9 : [9, 3, 1, 8, 5, 0, 7, 6, 4, 10, 2]
66 : 3 : [3, 1, 8, 5, 0, 7, 6, 4, 10, 2, 9]
67 : 1 : [1, 8, 5, 0, 7, 6, 4, 10, 2, 9, 3]
68 : 8 : [8, 5, 0, 7, 6, 4, 10, 2, 9, 3, 1]
69 : 5 : [5, 0, 7, 6, 4, 10, 2, 9, 8, 3, 1]
70 : 0 : [0, 7, 6, 4, 10, 2, 9, 8, 3, 1, 5]
71 : 7 : [7, 6, 4, 10, 2, 9, 8, 3, 0, 1, 5]
72 : 6 : [6, 4, 10, 2, 9, 8, 3, 0, 1, 5, 7]
73 : 4 : [4, 10, 2, 9, 8, 3, 0, 1, 5, 7, 6]
74 : 10 : [10, 2, 9, 8, 3, 0, 1, 5, 7, 6, 4]
75 : 2 : [2, 9, 8, 3, 0, 1, 5, 7, 6, 4, 10]
76 : 9 : [9, 8, 3, 0, 1, 5, 7, 6, 4, 10, 2]
77 : 8 : [8, 3, 0, 1, 5, 7, 6, 4, 10, 2, 9]
78 : 3 : [3, 0, 1, 5, 7, 6, 4, 10, 2, 9, 8]
79 : 0 : [0, 1, 5, 7, 6, 4, 10, 2, 3, 9, 8]
80 : 1 : [1, 5, 7, 6, 4, 10, 2, 3, 9, 8, 0]
81 : 5 : [5, 7, 6, 4, 10, 2, 3, 9, 8, 1, 0]
82 : 7 : [7, 6, 4, 10, 2, 3, 9, 8, 1, 0, 5]
83 : 6 : [6, 4, 10, 2, 3, 9, 8, 1, 0, 7, 5]
84 : 4 : [4, 10, 2, 3, 9, 8, 1, 0, 7, 5, 6]
85 : 10 : [10, 2, 3, 9, 8, 1, 0, 7, 5, 6, 4]
86 : 2 : [2, 3, 9, 8, 1, 0, 7, 5, 6, 4, 10]
87 : 3 : [3, 9, 8, 1, 0, 7, 5, 6, 4, 2, 10]
88 : 9 : [9, 8, 1, 0, 7, 5, 6, 4, 2, 10, 3]
89 : 8 : [8, 1, 0, 7, 5, 6, 4, 2, 10, 3, 9]
90 : 1 : [1, 0, 7, 5, 6, 4, 2, 10, 8, 3, 9]
91 : 0 : [0, 7, 5, 6, 4, 2, 10, 8, 3, 1, 9]
92 : 7 : [7, 5, 6, 4, 2, 10, 8, 3, 1, 9, 0]
93 : 5 : [5, 6, 4, 2, 10, 8, 3, 1, 9, 0, 7]
94 : 6 : [6, 4, 2, 10, 8, 3, 1, 9, 0, 7, 5]
95 : 4 : [4, 2, 10, 8, 3, 1, 9, 0, 7, 6, 5]
96 : 2 : [2, 10, 8, 3, 1, 9, 0, 7, 6, 4, 5]
97 : 10 : [10, 8, 3, 1, 9, 0, 7, 6, 4, 5, 2]
98 : 8 : [8, 3, 1, 9, 0, 7, 6, 4, 5, 2, 10]
end : 3 : [3, 1, 9, 0, 7, 6, 4, 5, 2, 10, 8]