【发布时间】:2015-06-17 02:08:36
【问题描述】:
我想改组这样的列表:-
to_shuffle = [ a, b, b, b, b, a, c, b, a, b ]
尽量减少重复元素的数量。最初,我
考虑从to_shuffle 顶部弹出元素,或者
如果元素是,则将它们推送到另一个列表 shuffled
与先前推送的元素不同,否则将其推送到
to_shuffle 的底部并尝试另一个元素。这将导致
在:-
shuffled = [ a, b, a, c, b, a, b, b, b, b ]
在这个例子中,也好不到哪里去 - 仍然有 4 个 b 连续(尽管这种方法有时减少了重复元素)。
我当时的想法是首先为每个类别制作一个桶 元素:-
buckets = [ (a, [a, a, a]), (b, [b, b, b, b, b, b]), (c, [c]) ]
按大小对桶排序,降序
buckets = [ (b, [b, b, b, b, b, b]), (a, [a, a, a]), (c, [c]) ]
跟踪最后一个洗牌的元素
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)
【问题讨论】:
-
随机性是要求的一部分吗?您要实现的并不是真正的改组,而是避免连续出现相同的字符...
-
不,正如你所说,避免相同字符的连续出现是目标,而不是随机性。不是洗牌吗?你会怎么称呼它?
-
我称之为“无重复重排”...当您“洗牌”一副牌时,您是否期望随机性,或者您是否会检查牌以确保牌是按你想要的顺序?