如何在python中受约束的列表内生成每个组合?

时间:2019-06-07 19:29:02

标签: python pandas data-science

我遇到一个问题,我需要根据给定的约束条件生成所有可能组合的列表,并且我不确定有什么方法会有所帮助。我有一个包含12个可用插槽的列表,我需要根据下面提到的约束填充每个插槽x和y。

x >= 7, x <= 9
y >= 4, y <= 9
list = [0,0,0,0,0,0,0,0,0,0,0,0]

我正在努力正确地表达问题,但我需要一个解决方案,其中list的连续值可以是x从1到至少7且最大值9,y可以从1到至少4且最大值9且list的连续值不能为0。因此,解决方案之一可能是:

# Solution 1 as x has occupied 9 continuous slots and y occupied 4
x = 1,1,1,1,1,1,1,1,1,0,0,0
y = 0,0,0,0,0,0,0,0,1,1,1,1
list= [1,1,1,1,1,1,1,1,2,1,1,1] 

# Solution 2 as x has occupied 8 continuous slots and y occupied 7 with no zero left
x = 0,0,0,0,1,1,1,1,1,1,1,1
y = 1,1,1,1,1,1,1,0,0,0,0,0
list= [1,1,1,1,2,2,2,1,1,1,1,1] 

我需要以上述方式生成所有可能的组合。有人可以帮忙还是至少给我一些有关如何在python中实现此目标的指示? 谢谢

3 个答案:

答案 0 :(得分:1)

只需天真地描述问题,一种简单的方法便是遍历每个长度对以及每个列表的每个可能的起始索引:

import numpy as np

def find_all():
    for x in range(7, 10):
        for y in range(4, 10):
            for xs in range(13 - x):
                for ys in range(13 - y):
                    a = np.zeros(12, int)
                    a[xs:xs+x] += 1
                    a[ys:ys+y] += 1
                    if 0 not in a:
                        yield x, y, xs, ys, a

list(find_all())

输出:

[(7, 5, 0, 7, array([1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1])),
 (7, 5, 5, 0, array([1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1])),
 (7, 6, 0, 6, array([1, 1, 1, 1, 1, 1, 2, 1, 1, 1, 1, 1])),
 (7, 6, 5, 0, array([1, 1, 1, 1, 1, 2, 1, 1, 1, 1, 1, 1])),
 (7, 7, 0, 5, array([1, 1, 1, 1, 1, 2, 2, 1, 1, 1, 1, 1])),
 (7, 7, 5, 0, array([1, 1, 1, 1, 1, 2, 2, 1, 1, 1, 1, 1])),
 (7, 8, 0, 4, array([1, 1, 1, 1, 2, 2, 2, 1, 1, 1, 1, 1])),
 (7, 8, 5, 0, array([1, 1, 1, 1, 1, 2, 2, 2, 1, 1, 1, 1])),
 (7, 9, 0, 3, array([1, 1, 1, 2, 2, 2, 2, 1, 1, 1, 1, 1])),
 (7, 9, 5, 0, array([1, 1, 1, 1, 1, 2, 2, 2, 2, 1, 1, 1])),
 (8, 4, 0, 8, array([1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1])),
 (8, 4, 4, 0, array([1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1])),
 (8, 5, 0, 7, array([1, 1, 1, 1, 1, 1, 1, 2, 1, 1, 1, 1])),
 (8, 5, 4, 0, array([1, 1, 1, 1, 2, 1, 1, 1, 1, 1, 1, 1])),
 (8, 6, 0, 6, array([1, 1, 1, 1, 1, 1, 2, 2, 1, 1, 1, 1])),
 (8, 6, 4, 0, array([1, 1, 1, 1, 2, 2, 1, 1, 1, 1, 1, 1])),
 (8, 7, 0, 5, array([1, 1, 1, 1, 1, 2, 2, 2, 1, 1, 1, 1])),
 (8, 7, 4, 0, array([1, 1, 1, 1, 2, 2, 2, 1, 1, 1, 1, 1])),
 (8, 8, 0, 4, array([1, 1, 1, 1, 2, 2, 2, 2, 1, 1, 1, 1])),
 (8, 8, 4, 0, array([1, 1, 1, 1, 2, 2, 2, 2, 1, 1, 1, 1])),
 (8, 9, 0, 3, array([1, 1, 1, 2, 2, 2, 2, 2, 1, 1, 1, 1])),
 (8, 9, 4, 0, array([1, 1, 1, 1, 2, 2, 2, 2, 2, 1, 1, 1])),
 (9, 4, 0, 8, array([1, 1, 1, 1, 1, 1, 1, 1, 2, 1, 1, 1])),
 (9, 4, 3, 0, array([1, 1, 1, 2, 1, 1, 1, 1, 1, 1, 1, 1])),
 (9, 5, 0, 7, array([1, 1, 1, 1, 1, 1, 1, 2, 2, 1, 1, 1])),
 (9, 5, 3, 0, array([1, 1, 1, 2, 2, 1, 1, 1, 1, 1, 1, 1])),
 (9, 6, 0, 6, array([1, 1, 1, 1, 1, 1, 2, 2, 2, 1, 1, 1])),
 (9, 6, 3, 0, array([1, 1, 1, 2, 2, 2, 1, 1, 1, 1, 1, 1])),
 (9, 7, 0, 5, array([1, 1, 1, 1, 1, 2, 2, 2, 2, 1, 1, 1])),
 (9, 7, 3, 0, array([1, 1, 1, 2, 2, 2, 2, 1, 1, 1, 1, 1])),
 (9, 8, 0, 4, array([1, 1, 1, 1, 2, 2, 2, 2, 2, 1, 1, 1])),
 (9, 8, 3, 0, array([1, 1, 1, 2, 2, 2, 2, 2, 1, 1, 1, 1])),
 (9, 9, 0, 3, array([1, 1, 1, 2, 2, 2, 2, 2, 2, 1, 1, 1])),
 (9, 9, 3, 0, array([1, 1, 1, 2, 2, 2, 2, 2, 2, 1, 1, 1]))]

例如,在第一个输出中,x数组的长度为7,从位置5开始,而y数组的长度为5,从位置7开始。

对于较大的输入值,这当然是非常低效的,并且可以通过以下方式实现完全相同的事情

def find_all():
    for x in range(7, 10):
        for y in range(max(12 - x, 4), 10):
            a = np.ones(12, int)
            a[12-y:x] = 2
            yield x, y, 0, 12-y, a
            yield x, y, 12-x, 0, a[::-1]

list(find_all())

答案 1 :(得分:0)

IIUC:

for i in range(7,10):
    x = np.repeat((1,0), (i, 12-i))
    for j in range(4,i):
        y = np.repeat((0,1), (j, 12-j))

        a = x + y

        print(x,y,a)

输出:

[1 1 1 1 1 1 1 0 0 0 0 0] [0 0 0 0 1 1 1 1 1 1 1 1] [1 1 1 1 2 2 2 1 1 1 1 1]
[1 1 1 1 1 1 1 0 0 0 0 0] [0 0 0 0 0 1 1 1 1 1 1 1] [1 1 1 1 1 2 2 1 1 1 1 1]
[1 1 1 1 1 1 1 0 0 0 0 0] [0 0 0 0 0 0 1 1 1 1 1 1] [1 1 1 1 1 1 2 1 1 1 1 1]
[1 1 1 1 1 1 1 1 0 0 0 0] [0 0 0 0 1 1 1 1 1 1 1 1] [1 1 1 1 2 2 2 2 1 1 1 1]
[1 1 1 1 1 1 1 1 0 0 0 0] [0 0 0 0 0 1 1 1 1 1 1 1] [1 1 1 1 1 2 2 2 1 1 1 1]
[1 1 1 1 1 1 1 1 0 0 0 0] [0 0 0 0 0 0 1 1 1 1 1 1] [1 1 1 1 1 1 2 2 1 1 1 1]
[1 1 1 1 1 1 1 1 0 0 0 0] [0 0 0 0 0 0 0 1 1 1 1 1] [1 1 1 1 1 1 1 2 1 1 1 1]
[1 1 1 1 1 1 1 1 1 0 0 0] [0 0 0 0 1 1 1 1 1 1 1 1] [1 1 1 1 2 2 2 2 2 1 1 1]
[1 1 1 1 1 1 1 1 1 0 0 0] [0 0 0 0 0 1 1 1 1 1 1 1] [1 1 1 1 1 2 2 2 2 1 1 1]
[1 1 1 1 1 1 1 1 1 0 0 0] [0 0 0 0 0 0 1 1 1 1 1 1] [1 1 1 1 1 1 2 2 2 1 1 1]
[1 1 1 1 1 1 1 1 1 0 0 0] [0 0 0 0 0 0 0 1 1 1 1 1] [1 1 1 1 1 1 1 2 2 1 1 1]
[1 1 1 1 1 1 1 1 1 0 0 0] [0 0 0 0 0 0 0 0 1 1 1 1] [1 1 1 1 1 1 1 1 2 1 1 1]

答案 2 :(得分:0)

以下内容将产生您想要的内容:

def get_array(arr_min, arr_max, length, end=False):
    arr_full = np.tril(np.ones((length, length)))
    if end:
        arr_full = arr_full[:, ::-1]
    arr_row_tot = arr_full.sum(axis=1)
    row_sel = (arr_row_tot >= arr_min) & (arr_row_tot <= arr_max)
    arr = arr_full[row_sel, :]
    return arr

def get_combos(x_min_max, y_min_max, length=12):
    X = get_array(*x_min_max, length)
    Y = get_array(*y_min_max, length, end=True)
    X = np.expand_dims(X, 1)
    combos = (X + Y).reshape(-1, length).astype("int")
    lists = [list(sub_arr) for sub_arr in combos]
    x_y_vals = [
        {"x": x, "y": y}
        for x in range(x_min_max[0], x_min_max[1] + 1)
        for y in range(y_min_max[0], y_min_max[1] + 1)
    ]
    return list(zip(x_y_vals, lists))

一些例子:

get_combos((4, 9), (5, 7), 12)输出:

[({'x': 4, 'y': 5}, [1, 1, 1, 1, 0, 0, 0, 1, 1, 1, 1, 1]),
 ({'x': 4, 'y': 6}, [1, 1, 1, 1, 0, 0, 1, 1, 1, 1, 1, 1]),
 ({'x': 4, 'y': 7}, [1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1]),
 ({'x': 5, 'y': 5}, [1, 1, 1, 1, 1, 0, 0, 1, 1, 1, 1, 1]),
 ({'x': 5, 'y': 6}, [1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1]),
 ({'x': 5, 'y': 7}, [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1]),
 ({'x': 6, 'y': 5}, [1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1]),
 ({'x': 6, 'y': 6}, [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1]),
 ({'x': 6, 'y': 7}, [1, 1, 1, 1, 1, 2, 1, 1, 1, 1, 1, 1]),
 ({'x': 7, 'y': 5}, [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1]),
 ({'x': 7, 'y': 6}, [1, 1, 1, 1, 1, 1, 2, 1, 1, 1, 1, 1]),
 ({'x': 7, 'y': 7}, [1, 1, 1, 1, 1, 2, 2, 1, 1, 1, 1, 1]),
 ({'x': 8, 'y': 5}, [1, 1, 1, 1, 1, 1, 1, 2, 1, 1, 1, 1]),
 ({'x': 8, 'y': 6}, [1, 1, 1, 1, 1, 1, 2, 2, 1, 1, 1, 1]),
 ({'x': 8, 'y': 7}, [1, 1, 1, 1, 1, 2, 2, 2, 1, 1, 1, 1]),
 ({'x': 9, 'y': 5}, [1, 1, 1, 1, 1, 1, 1, 2, 2, 1, 1, 1]),
 ({'x': 9, 'y': 6}, [1, 1, 1, 1, 1, 1, 2, 2, 2, 1, 1, 1]),
 ({'x': 9, 'y': 7}, [1, 1, 1, 1, 1, 2, 2, 2, 2, 1, 1, 1])]

get_combos((2, 6), (2, 5), 12)输出:

[({'x': 2, 'y': 2}, [1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1]),
 ({'x': 2, 'y': 3}, [1, 1, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1]),
 ({'x': 2, 'y': 4}, [1, 1, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1]),
 ({'x': 2, 'y': 5}, [1, 1, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1]),
 ({'x': 3, 'y': 2}, [1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 1, 1]),
 ({'x': 3, 'y': 3}, [1, 1, 1, 0, 0, 0, 0, 0, 0, 1, 1, 1]),
 ({'x': 3, 'y': 4}, [1, 1, 1, 0, 0, 0, 0, 0, 1, 1, 1, 1]),
 ({'x': 3, 'y': 5}, [1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 1]),
 ({'x': 4, 'y': 2}, [1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 1, 1]),
 ({'x': 4, 'y': 3}, [1, 1, 1, 1, 0, 0, 0, 0, 0, 1, 1, 1]),
 ({'x': 4, 'y': 4}, [1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1]),
 ({'x': 4, 'y': 5}, [1, 1, 1, 1, 0, 0, 0, 1, 1, 1, 1, 1]),
 ({'x': 5, 'y': 2}, [1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 1, 1]),
 ({'x': 5, 'y': 3}, [1, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1]),
 ({'x': 5, 'y': 4}, [1, 1, 1, 1, 1, 0, 0, 0, 1, 1, 1, 1]),
 ({'x': 5, 'y': 5}, [1, 1, 1, 1, 1, 0, 0, 1, 1, 1, 1, 1]),
 ({'x': 6, 'y': 2}, [1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1]),
 ({'x': 6, 'y': 3}, [1, 1, 1, 1, 1, 1, 0, 0, 0, 1, 1, 1]),
 ({'x': 6, 'y': 4}, [1, 1, 1, 1, 1, 1, 0, 0, 1, 1, 1, 1]),
 ({'x': 6, 'y': 5}, [1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1])]