我有以下列表:
[[a,b,c],[b],[d,a,b,e],[a,c]]
此列表代表拼图问题中的迷你世界。在这个例子中,世界包含4堆堆叠在一起的物体。我只能移动顶部对象并将其放在其他堆栈的顶部。字母代表一种对象,例如可能是摇滚和b。 我需要为这个迷你世界生成所有可能存在的状态。我试图在python中这样做,但不知道如何实现它。
答案 0 :(得分:0)
您可以将itertools.combinations_with_replacement与列表理解结合使用:
import itertools
ll = [['a','b','c'],['b'],['d','a','b','e'],['a','c']]
print [list(itertools.combinations_with_replacement(item,len(item))) for item in ll]
它为列表列表中的每个元素提供组合。
输出:
[[('a', 'a', 'a'), ('a', 'a', 'b'), ('a', 'a', 'c'), ('a', 'b', 'b'), ('a', 'b', 'c'), ('a', 'c', 'c'), ('b', 'b', 'b'), ('b', 'b', 'c'), ('b', 'c', 'c'), ('c', 'c', 'c')],
[('b',)],
[('d', 'd', 'd', 'd'), ('d', 'd', 'd', 'a'), ('d', 'd', 'd', 'b'), ('d', 'd', 'd', 'e'), ('d', 'd', 'a', 'a'), ('d', 'd', 'a', 'b'), ('d', 'd', 'a', 'e'), ('d', 'd', 'b', 'b'), ('d', 'd', 'b', 'e'), ('d', 'd', 'e', 'e'), ('d', 'a', 'a', 'a'), ('d', 'a', 'a', 'b'), ('d', 'a', 'a', 'e'), ('d', 'a', 'b', 'b'), ('d', 'a', 'b', 'e'), ('d', 'a', 'e', 'e'), ('d', 'b', 'b', 'b'), ('d', 'b', 'b', 'e'), ('d', 'b', 'e', 'e'), ('d', 'e', 'e', 'e'), ('a', 'a', 'a', 'a'), ('a', 'a', 'a', 'b'), ('a', 'a', 'a', 'e'), ('a', 'a', 'b', 'b'), ('a', 'a', 'b', 'e'), ('a', 'a', 'e', 'e'), ('a', 'b', 'b', 'b'), ('a', 'b', 'b', 'e'), ('a', 'b', 'e', 'e'), ('a', 'e', 'e', 'e'), ('b', 'b', 'b', 'b'), ('b', 'b', 'b', 'e'), ('b', 'b', 'e', 'e'), ('b', 'e', 'e', 'e'), ('e', 'e', 'e', 'e')],
[('a', 'a'), ('a', 'c'), ('c', 'c')]]
如果您想避免在组合中使用重复的相同元素,可以使用itertools.permutation:
[list(itertools.permutations(item,len(item))) for item in ll]
输出:
[[('a', 'b', 'c'), ('a', 'c', 'b'), ('b', 'a', 'c'), ('b', 'c', 'a'), ('c', 'a', 'b'), ('c', 'b', 'a')],
[('b',)],
[('d', 'a', 'b', 'e'), ('d', 'a', 'e', 'b'), ('d', 'b', 'a', 'e'), ('d', 'b', 'e', 'a'), ('d', 'e', 'a', 'b'), ('d', 'e', 'b', 'a'), ('a', 'd', 'b', 'e'), ('a', 'd', 'e', 'b'), ('a', 'b', 'd', 'e'), ('a', 'b', 'e', 'd'), ('a', 'e', 'd', 'b'), ('a', 'e', 'b', 'd'), ('b', 'd', 'a', 'e'), ('b', 'd', 'e', 'a'), ('b', 'a', 'd', 'e'), ('b', 'a', 'e', 'd'), ('b', 'e', 'd', 'a'), ('b', 'e', 'a', 'd'), ('e', 'd', 'a', 'b'), ('e', 'd', 'b', 'a'), ('e', 'a', 'd', 'b'), ('e', 'a', 'b', 'd'), ('e', 'b', 'd', 'a'), ('e', 'b', 'a', 'd')],
[('a', 'c'), ('c', 'a')]]
答案 1 :(得分:0)
您可以使用递归生成器执行此操作。逻辑的工作原理如下:
这有一个问题:可以回到起点(移动' c'右边一个堆叠,然后移动' c'离开一个堆叠),会导致无限递归。我只考虑一个方向的移动来解决这个问题,但更一般的方法是跟踪你已经看过的所有状态,如果你回到一个状态就会挽救。
这就是我所拥有的:
def shuffle_stacks(state):
'''
shuffle_stacks([[a], [b, c]]) ->
[[a, b], [c]],
[[a], [c, b]],
[[], [c, b, a]]
yield all possible states that can be given by moving an item off
the top of a sublist to the top of any other sublist, recursively.
Currently only moves items to the right of their starting point.
'''
yield state
# Find all the possible states we can be in if we move
# one item off the top of a stack to any stack to its right
# Apply recursively to each such state
for i, source in enumerate(state):
unchanged_state = state[:i]
targets = state[i+1:]
source = source[:]
if not source or not targets:
continue
item = source.pop()
for j, target in enumerate(targets):
# Copy mutables to isolate changes
target = target[:]
targets = targets[:]
targets[j] = target
target.append(item)
next_state = unchanged_state + [source] + targets
yield from shuffle_stacks(next_state)
请注意,{2.7}中不存在yield from
,但如果升级到至少3.3不是您的选项,则可以将其替换为循环:
for new_state in shuffle_stacks(next_state):
yield new_state