Python 生成仅包含一个公共项的列表

Python 生成仅包含一个公共项的列表,python,Python,在Python中,我提出了一个想法,但我不确定如何正确地实现它 我有26个字母('a'-'Z'),每个字母可以根据需要使用任意多次。我想用这些字母创建列表;每个列表将有10个字母长,其中没有重复,我想保证,如果我比较生成的任何两个列表,将恰好有一个相同的字母 问题: 有没有一种简单的方法可以做到这一点(即使用库函数) 给定池的大小(pool_size)和列表的长度(list_length),我能计算出我能创建的列表的最大数量吗 如有任何相关材料的提示,将不胜感激;我不需要太多的地方来实现我的

在Python中,我提出了一个想法,但我不确定如何正确地实现它

我有26个字母('a'-'Z'),每个字母可以根据需要使用任意多次。我想用这些字母创建列表;每个列表将有10个字母长,其中没有重复,我想保证,如果我比较生成的任何两个列表,将恰好有一个相同的字母

问题:

  • 有没有一种简单的方法可以做到这一点(即使用库函数)
  • 给定池的大小(pool_size)和列表的长度(list_length),我能计算出我能创建的列表的最大数量吗
如有任何相关材料的提示,将不胜感激;我不需要太多的地方来实现我的阿基米德杠杆(被理解为:我需要一个基础才能建立我的想法)。 “给我一个立足之地,我将移动地球。”-阿基米德


更新:我真天真,竟然认为字母表就足够了。让我们将池扩展到300个符号,但保持列表的长度为10。这行吗?

只有26个字母可供选择,因此只能生成两个列表

随机选择一个字母并将其放入两个列表中。然后再选择18个不同的字母,在每个列表中随机放置9个。然后,您的列表将如下所示:

ABCDEFGHIJ
AKLMNOPQRS
如果您添加第三个列表,就不可能满足您的约束条件,因为只有七个未使用的字母。第三个列表必须与其他列表中的一个共享至少两个字母,这是您不允许的


更新

这只是部分回答了您更新的问题,但我还是会发布它,因为它可能会帮助您或其他人找到最佳解决方案

一般来说,使用
n
符号和长度列表
x
,您可以使用上述算法(选择1个字母并将其添加到所有列表中)轻松生成至少
楼层((n-1)/(x-1))
列表。对于300个长度为10的符号和列表,可以生成33个列表

但可以通过使用不同的算法对此进行改进。例如,如果n为10,x为4,则上述算法仅给出三个列表:

ABCD
AEFG
AHIJ
但一种更有效地重用字母的算法可以生成五个列表:

ABCD
AEFG
BEHI
CFHJ
DGIJ
我使用贪婪算法生成了这些列表:对于每个新列表,重复使用以前列表中尽可能多的不同字母,这意味着添加的新字母尽可能少

第二个列表重用第一个列表中的一个字母并添加三个新字母。第三个列表重用前两个列表中每个列表中的一个不同字母,因此只引入两个新字母。第四个列表重用以前出现过的三个字母,并添加一个新字母。最后一个列表现在可以重用每个列表中的一个字母f以前的列表,不需要添加任何新字母


更新2

贪婪算法肯定不是最优解

让我们试试:n=26,x=2

简单的解决方案给出了最佳的25个列表:

AB
AC
AD
..
AZ
但是,贪婪算法只生成3个列表:

AB
AC
BC

现在,如果不打破其中一条规则,就不可能再添加任何列表。

这是我为所有Set和Line Length值找到的一般解决方案。第一个假设您不希望两个解决方案共享同一个公共元素,但希望每个解决方案都有一个与其他解决方案相同的元素。给定一个无限的共享池选择形式时,解决方案的总数受每个解决方案的长度限制

SET_LENGTH = 10
CHOICE_LENGTH = 300

data = set(range(CHOICE_LENGTH))
solutions =[]
solution_sets = []
used = set()

while True:
    new_solution = []
    #Try to get unique values from each previous set
    try:
        for sol_set in solution_sets:
            while True:
                candidate = sol_set.pop()
                if not candidate in used:
                    new_solution.append(candidate)
                    used.update([candidate])
                    break
    except KeyError, e:
        print e
        break
    #Fill with new data until the line is long enough
    try:
        while len(new_solution) < SET_LENGTH:
            new_solution.append(data.pop())
    except KeyError, e:
        print e
        break
    solutions.append(new_solution)
    solution_sets.append(set(new_solution))
#Show the results
for solution in solutions:
    print solution
print "Orphans %s" % len(data)   
如果您不在乎有多少解决方案共享同一个公共元素,那么就更容易了:

SET_LENGTH = 2
CHOICE_LENGTH = 300

data = set(range(CHOICE_LENGTH))
solutions =[]
alpha = data.pop()
while True:
    new_solution = [alpha]
    try:
        [new_solution.append(data.pop()) for x in range(SET_LENGTH-1)]
    except KeyError, e:
        break
    solutions.append(new_solution)

for solution in solutions:
    print solution
print "Solutions: %s" % len(solutions)
print "Orphans: %s" % len(data)

如果你只有26个字母(A-Z),每个列表的长度为10个字母,那么当您生成第三个列表时,它保证与至少一个其他列表有多个相同的字母。您也可以很容易地按顺序遍历池,只需使用最后一个字母两次:
ABCDEFGHIJ
JKLMNOPQRST
。这就是我正在寻找的例如,当我第一次尝试这个方法时,我生成了更新后第一个示例的列表,但我认识到必须有更多的列表。是否有一个通用算法可以生成类似于第二个示例的列表?@taserian:我对如何解决这个问题有一些模糊的想法,但我想知道是否有其他人可以想出一些聪明的方法。。。希望其他人能给出一个很好的答案,这个答案很简单,并且能够以最佳方式解决
n=26,x=2
n=10,x=4
。第二个算法有时给出的结果比第一个算法少,例如在n=10 x=4的情况下,正如Mark Byers所证明的那样。
SET_LENGTH = 2
CHOICE_LENGTH = 300

data = set(range(CHOICE_LENGTH))
solutions =[]
alpha = data.pop()
while True:
    new_solution = [alpha]
    try:
        [new_solution.append(data.pop()) for x in range(SET_LENGTH-1)]
    except KeyError, e:
        break
    solutions.append(new_solution)

for solution in solutions:
    print solution
print "Solutions: %s" % len(solutions)
print "Orphans: %s" % len(data)