微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

将所有分区迭代为k个组?

如何解决将所有分区迭代为k个组?

这可行,尽管它可能超级无效(我将它们全部排序以避免重复计算):

def clusters(l, K):
    if l:
        prev = None
        for t in clusters(l[1:], K):
            tup = sorted(t)
            if tup != prev:
                prev = tup
                for i in xrange(K):
                    yield tup[:i] + [[l[0]] + tup[i],] + tup[i+1:]
    else:
        yield [[] for _ in xrange(K)]

它还返回空簇,因此您可能希望将其包装起来以便仅获取非空簇:

def neclusters(l, K):
    for c in clusters(l, K):
        if all(x for x in c): yield c

计数只是为了检查:

def kamongn(n, k):
    res = 1
    for x in xrange(n-k, n):
        res *= x + 1
    for x in xrange(k):
        res /= x + 1
    return res

def Stirling(n, k):
    res = 0
    for j in xrange(k + 1):
        res += (-1)**(k-j) * kamongn(k, j) * j ** n
    for x in xrange(k):
        res /= x + 1
    return res

>>> sum(1 for _ in neclusters([2,3,5,7,11,13], K=3)) == Stirling(len([2,3,5,7,11,13]), k=3)
True

有用 !

输出

>>> clust = neclusters([2,3,5,7,11,13], K=3)
>>> [clust.next() for _ in xrange(5)]
[[[2, 3, 5, 7], [11], [13]], [[3, 5, 7], [2, 11], [13]], [[3, 5, 7], [11], [2, 13]], [[2, 3, 11], [5, 7], [13]], [[3, 11], [2, 5, 7], [13]]]

解决方法

说我有一个列表L。如何获得K组所有分区上的迭代器?

示例:L = [2,3,5,7,11,13],K = 3

3组的所有可能分区的列表:

[ [ 2 ],[ 3,5],[ 7,11,13] ]
[ [ 2,5 ],11],[ 13] ]
[ [ 3,11 ],[ 5,7],[ 2,13] ]
[ [ 3 ],[ 11 ],2,13] ]
etc...

===更新===

我正在研究一个似乎可行的解决方案,所以我只复制粘贴它即可

# -*- coding: utf-8 -*-

import itertools

# return ( list1 - list0 )
def l1_sub_l0( l1,l0 ) :
    """Substract two lists"""
    #
    copy_l1 = list( l1 )
    copy_l0 = list( l0 )

    #
    for xx in l0 :
        #
        if copy_l1.count( xx ) > 0 :
            #
            copy_l1.remove( xx )
            copy_l0.remove( xx )

    #
    return [ copy_l1,copy_l0 ]


#
def gen_group_len( n,k ) :
    """Generate all possible group sizes"""

    # avoid doubles
    stop_list = []
    #
    for t in itertools.combinations_with_replacement( xrange( 1,n - 1 ),k - 1 ) :
        #
        last_n = n - sum( t )

        # valid group size
        if last_n  >= 1 :
            res = tuple( sorted( t + ( last_n,) ) )
            #
            if res not in stop_list :
                yield res
                stop_list.append( res )


# group_len = (1,1,3)

def gen( group_len,my_list ) :
    """Generate all possible partitions of all possible group sizes"""

    #
    if len( group_len ) == 1 :
        yield ( tuple( my_list ),)

    #
    else :

        # need for a stop list if 2 groups of same size
        stop_list = []

        #
        for t in itertools.combinations( my_list,group_len[ 0 ] ) :
            #
            reduced_list = l1_sub_l0( my_list,t )[ 0 ]

            #
            for t2 in gen( group_len[ 1: ],reduced_list ) :
                #
                tmp = set( ( t,t2[ 0 ] ) )
                #
                if tmp not in stop_list :
                    yield ( t,) + t2
                    # avoid doing same thing twice
                    if group_len[ 1 ] == group_len[ 0 ] :
                        stop_list.append( tmp )


#
my_list = [ 3,13 ]
n = len( my_list )
k = 3

#
group_len_list = list( gen_group_len( n,k ) )
print "for %i elements,%i configurations of group sizes" % ( n,len(  group_len_list ) )
print group_len_list

#
for group_len in group_len_list :
    #
    print "group sizes",group_len
    #
    for x in gen( group_len,my_list ) :
        print x
    #
    print "==="

输出:

for 5 elements,2 configurations of group sizes
[(1,3),(1,2)]
group sizes (1,3)
((3,),(5,(7,13))
((3,(11,(13,11))
((5,(3,13))
((5,11))
((7,13))
((7,11))
((11,7))
===
group sizes (1,2)
((3,7),11),13),5),13))
((11,7))
((13,11))
((13,7))
===

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。