无需重复使用子列表项的Python组合

时间:2019-01-25 17:09:48

标签: python

我有一些要合并的等于项。 我尝试用一​​个例子更好地解释:

我有一些人,每个人都有一个ID。 情况就是这样的5个人的名单

['A','A','B','B','C']

我需要将每个人都放在一个房间里。每个具有相同代码的人都必须位于同一房间。 例如,房间数是3:第一个房间有2个桌子,第二个房间有3个桌子,最后一个又有2个桌子。

所以最终我希望看到这样的组合列表:

[['A','A'],['B','B',None],['C',None]]
[['A','A'],['C',None,None],['B','B']]
[['A','A'],['B','B','C'],[None,None]]
[['B','B'],['A','A',None],['C',None]]
[['B','B'],['C',None,None],['A','A']]
[['B','B'],['A','A','C'],[None,None]]
[['C',None],['A','A',None],['B','B']]
[['C',None],['B','B',None],['A','A']]

“无”表示空桌子。

我不希望有最终的解决方案,我希望能对遵循的逻辑过程有所帮助,因为我对此感到非常疯狂。

非常感谢您。

4 个答案:

答案 0 :(得分:0)

peoples = ['A','A','B','B','C', "None", "None"]

import itertools

for x in itertools.permutations(peoples):
    rooma = x[:2]
    if rooma[0] == rooma[1] or "None" in rooma[:2]:
        roomb = x[2:5]
        if len(roomb) != len(set(roomb)):
            roomc = x[5:]
            if roomc[0] == roomc[1] or "None" in roomc[:2]:
                print([rooma,roomb,roomc])

如果有的话,这可以使您获得95%

答案 1 :(得分:0)

我创建了一个示例来解决您的问题:

import itertools
combs = ['AA','BB','C','X', 'X'] # i grouped AA becouse they are grouped and "X" = None

mylist = sorted(list(itertools.permutations(combs))) #create all possible permutations

#split the groups
tuppleSet = set()
for line in mylist:
    t = ()
    for string in line:
        string.split("\\")
        t = t + tuple(string)
    tuppleSet.add(t)

newlist = sorted(tuppleSet)
for line in newlist:
    if line[0] == "C" or line[0] == "X" and line[1] == "A" or line[1] == "B": #restricton with table size 
        continue
    elif line[6] == "X" or line[6] == "C" and line[4] == "A" or line[4] == "B": #restricton with table size 
        continue
    print(line)

Output:
('A', 'A', 'B', 'B', 'X', 'X', 'C')
('A', 'A', 'C', 'X', 'X', 'B', 'B')
('A', 'A', 'X', 'C', 'X', 'B', 'B')
('A', 'A', 'X', 'X', 'C', 'B', 'B')
('X', 'C', 'A', 'A', 'X', 'B', 'B')
('X', 'C', 'B', 'B', 'X', 'A', 'A')
('X', 'C', 'X', 'A', 'A', 'B', 'B')
('X', 'X', 'A', 'A', 'C', 'B', 'B')
('X', 'X', 'B', 'B', 'C', 'A', 'A')
('X', 'X', 'C', 'A', 'A', 'B', 'B')

我强烈建议更深入地研究Itertools,因为我不太深...

答案 2 :(得分:0)

from itertools import combinations,permutations,repeat,groupby,zip_longest
Peop = [["A001_B","A001_B"],["A004_A","A004_A"],["A003_A","A003_A","A003_A","A003_A","A003_A","A003_A"],["A002_A","A002_A","A002_A","A002_A"],["A001_C","A001_C"],["A001_A","A001_A","A001_A"],["A002_B","A002_B"]];
RPla = [4,10,2,4,8]
Comb = []
for r in RPla:
    out,out1,l1,s1 = [],[],[],[]
    for s in Peop:
        l = len(s)
        if l > r:
            continue
        elif l == r:
            out.append(s)
        else:
            s1.append(s) # ======== new purged Peop
            l1.append(l) # ======== len same people Peop
    indL,tempC,diff = [],[],[]
    for z in range(2,len(l1)-1):
        for k,y in zip(combinations(range(len(l1)),z),combinations(l1,z)):
            indL.append(k)
            tempC.append(y)
            if sum(y) > r:
                continue # <<<<<==== WILL DO SOMETHING ======================
            elif sum(y) == r:
                tempL1 = []
                for h in k:
                    tempL1.append(s1[h])
                tempL1 = [item for sublist in tempL1 for item in sublist] #flatten
                out.append(tempL1)
            else:
                diff = r - sum(y)
                tempL1 = []
                for h in k:
                    tempL1.append(s1[h])
                tempL1 = [item for sublist in tempL1 for item in sublist] #flatten
                tempL1.extend(repeat("Empty Desk",diff))
                out.append(tempL1)
    s1.append(repeat("Empty Desk",r))
    tempL2 = [list(row) for row in zip_longest(*s1, fillvalue='Empty Desk')]
    tempL3 = [list(row) for row in zip_longest(*tempL2, fillvalue='')]
    #tempL3 = tempL3[:len(s1)-1]
    out.extend(tempL3)
    Comb.append(out)
print(Comb)

我想向您展示我的正在进行的工作(上面)。

这样,对于每个房间,我都会找到所有可能的优化组合。问题在于,现在我必须不重复地组合房间之间的组合。 我没有找到办法,所以我也想改变主意。

与上一个示例相比,您可以看到人们可以改变,而且房间位置也可以。

这是使用Python 3的测试,尽管我使用的是Python 2

谢谢!

答案 3 :(得分:0)

这是基于Fabian方法的更快解决方案:

import itertools, sys

# combs = ['AA','BB','C','X', 'X'] # i grouped AA becouse they are grouped and "X" = None
# rooms = [2, 3, 2]
combs = ['AA', 'BBB', 'C', 'X', 'X', 'X', 'X']
rooms = [2, 3, 2, 3]

mylist = sorted(list(itertools.permutations(combs))) #create all possible permutations

unique_assignments = []

# test if two assignemtns are equivalent
def equivalent_assignments(assignment1, assignment2):
    for i in range(0, len(assignment1)):
        if tuple(assignment1[i]) not in itertools.permutations(assignment2[i]):
            return False
    return True

# for every permutation
for line in mylist:
    fits = True
    rooms_ind = 0
    comb_ind = 0

    room = rooms[rooms_ind]
    comb = line[comb_ind]

    room_assignments = []
    room_assignment = []

    # see if this permutation will fit
    while True:
        if room < len(comb):
            break
        elif room == len(comb):
            comb_ind += 1
            rooms_ind += 1
            room_assignment.append(comb)
            room_assignments.append(room_assignment)
            room_assignment = []
            try:
                room = rooms[rooms_ind]
                comb = line[comb_ind]
            except:

                break
        else: # room > len(comb)
            room_assignment.append(comb)
            room -= len(comb)
            comb_ind += 1
            try:
                comb = line[comb_ind]
            except:
                break

    # if we have leftover people, they don't fit
    if comb_ind < len(line) - 1:
        fits = False

    # check for same assignments
    if fits:
        same_assignments = [x for x in unique_assignments if equivalent_assignments(x, room_assignments)]
        if len(same_assignments) == 0:
            unique_assignments.append(room_assignments)

# print results
for line in unique_assignments:
    print line

输出:

[['AA'], ['BBB'], ['C', 'X'], ['X', 'X', 'X']]
[['AA'], ['BBB'], ['X', 'X'], ['C', 'X', 'X']]
[['AA'], ['C', 'X', 'X'], ['X', 'X'], ['BBB']]
[['AA'], ['X', 'X', 'X'], ['C', 'X'], ['BBB']]
[['C', 'X'], ['AA', 'X'], ['X', 'X'], ['BBB']]
[['C', 'X'], ['BBB'], ['AA'], ['X', 'X', 'X']]
[['C', 'X'], ['BBB'], ['X', 'X'], ['AA', 'X']]
[['C', 'X'], ['X', 'X', 'X'], ['AA'], ['BBB']]
[['X', 'X'], ['AA', 'C'], ['X', 'X'], ['BBB']]
[['X', 'X'], ['AA', 'X'], ['C', 'X'], ['BBB']]
[['X', 'X'], ['BBB'], ['AA'], ['C', 'X', 'X']]
[['X', 'X'], ['BBB'], ['C', 'X'], ['AA', 'X']]
[['X', 'X'], ['BBB'], ['X', 'X'], ['AA', 'C']]
[['X', 'X'], ['C', 'X', 'X'], ['AA'], ['BBB']]

我以前效率低得多的解决方案:

import itertools, sys

people = ['A', 'A', 'B', 'B', 'C']
rooms = [2, 3, 2]
# people = ['A', 'A', 'B', 'B', 'B', 'C']
# rooms = [2, 3, 2, 3]
# people = ['A', 'A', 'B', 'B', 'C', 'C', 'C', 'C', 'C'] # takes absurdly long
# rooms = [2, 3, 2, 5]

total_room_space = sum(rooms)
print("total_room_space: " + str(total_room_space))

people_padded = people
for i in range(0, (total_room_space - len(people))):
    people_padded.append('None')
print('people_padded: ' + str(people_padded))

unique_assignments = []

for perm in itertools.permutations(people_padded):
    perm_index = 0

    room_assignments = []
    for room_size in rooms:
        room_assignment = []
        for i in range(0, room_size):
            room_assignment.append(perm[perm_index])
            perm_index += 1
        room_assignments.append(tuple(room_assignment))

    skipflag = False

    # check for multiple rooms
    for room_assignment in room_assignments:
        rest = [x for x in room_assignments if x is not room_assignment]
        for room_asgn in rest:
            for code in room_assignment:
                if code != 'None':
                    if code in room_asgn:
                        skipflag = True

    # skip if needed
    if skipflag:
        continue

    if room_assignments not in unique_assignments:
        unique_assignments.append(room_assignments)

# return true if two room assignments are the same
def same_assignment(assignment1, assignment2):
    for i in range(0, len(assignment1)):
        if assignment1[i] not in itertools.permutations(assignment2[i]):
            return False
    return True

# clean up same combinations in unique_assignments
indeces = range(0, len(unique_assignments))
delete_indeces = []
while indeces:
    curr_index = indeces.pop(0)
    equivalent_assignments = [x for x in indeces if same_assignment(unique_assignments[x], unique_assignments[curr_index])]
    for ind in equivalent_assignments:
        delete_indeces.append(ind)
    indeces = [x for x in indeces if x not in equivalent_assignments]

for index in reversed(sorted(delete_indeces)):
    del unique_assignments[index]

# print results
print("\n\nResults:")
for assignment in unique_assignments:
    print assignment