I want to shuffle a list like this: -
to_shuffle = [ a, b, b, b, b, a, c, b, a, b ]
to minimize the number of repeating elements. Initially, I thought about popping items from the top to_shuffleand either clicking them on a different list shuffledif the item is different from the previously put forward item, or the bottom to_shuffleand try another item. This will result in: -
shuffled = [ a, b, a, c, b, a, b, b, b, b ]
which in this example is not better - there are still 4 b in a row (although this method sometimes reduces duplicate elements).
What I thought then was to begin by creating a bucket for each class element: -
buckets = [ (a, [a, a, a]), (b, [b, b, b, b, b, b]), (c, [c]) ]
sort buckets by size, descending
buckets = [ (b, [b, b, b, b, b, b]), (a, [a, a, a]), (c, [c]) ]
tracking the last item moved
last = None
,
, last, : -
sorted = [ b ]
buckets = [ (b, [b, b, b, b, b]), (a, [a, a, a]), (c, [c]) ]
last = b
sorted = [ b, a ]
buckets = [ (b, [b, b, b, b, b]), (a, [a, a]), (c, [c]) ]
last = a
sorted = [ b, a, b ]
buckets = [ (b, [b, b, b, b]), (a, [a, a]), (c, [c]) ]
last = b
sorted = [ b, a, b, a ]
buckets = [ (b, [b, b, b, b]), (a, [a]), (c, [c]) ]
.
.
.
sorted = [ b, a, b, a, b, a, b, c, b, b ]
.
, , python (2.7)?
: -
test = [ 'a', 'b', 'b', 'b', 'b', 'a', 'c', 'b', 'a', 'b' ]
expected = [ 'b', 'a', 'b', 'a', 'b', 'a', 'b', 'c', 'b', 'b' ]
def sort_buckets(buckets):
return sorted(buckets, key=lambda x: len(x[1]), reverse=True)
def make_buckets(to_shuffle):
h = {}
buckets = []
for e in to_shuffle:
if e not in h:
h[e] = []
h[e].append(e)
for k, elems in h.iteritems():
buckets.append((k, elems))
return buckets
def shuffle(to_shuffle):
buckets = make_buckets(to_shuffle)
shuffled = []
last = ''
while len(buckets) > 1:
buckets = sort_buckets(buckets)
for i in range(len(buckets)):
candidate = buckets[i][0]
if candidate == last:
continue
t = buckets.pop(i)
last = candidate
shuffled.append(t[1][-1])
if len(t[1]) > 1:
buckets.append((t[0], t[1][:-1]))
break
t = buckets.pop()
shuffled += t[1]
return shuffled
print expected
print shuffle(test)