简体   繁体   English

用于y标签桶中x标签球的Python迭代器

[英]Python iterator for x labeled balls in y labeled buckets

I need a Python iterator to yield all combinations of X labeled balls in Y labeled buckets, where X is greater than or equal to Y, and all buckets contain one or more balls. 我需要一个Python迭代器来生成Y标记的存储桶中X标记的球的所有组合,其中X大于或等于Y,并且所有存储桶都包含一个或多个球。

For a case of X = 4 and Y = 3, with balls labeled ABCD, and buckets labeled 1-2-3, some of the possible combinations would be: 对于X = 4和Y = 3的情况,如果球标记为ABCD,而铲斗标记为1-2-3,则一些可能的组合为:

Bucket 1: A, B 时段1:A,B
Bucket 2: C 时段2:C
Bucket 3: D 时段3:D

Bucket 1: A 时段1:A
Bucket 2: C, B 时段2:C,B
Bucket 3: D 时段3:D

Bucket 1: A 时段1:A
Bucket 2: C 时段2:C
Bucket 3: D, B 时段3:D,B

Bucket 1: A, C 时段1:A,C
Bucket 2: B 时段2:B
Bucket 3: D 时段3:D

... ...

A comment on the original question by AR has helped to find an answer, except instead of "all Y-partitions of X", it is "all permutations of all Y-partitions of X" that I needed. AR对原始问题的评论帮助找到了一个答案,除了我需要的是“ X的所有Y分区的所有排列”,而不是“ X的所有Y分区”。 The Knuth algorithm here is a Python 2 implementation of "all Y-partitions of X". 这里Knuth算法是“ X的所有Y分区”的Python 2实现。 I needed to create the Python 3 implementation of that (by swapping all xrange with range ), and then wrap the function in a new generator that applies itertools.permutations at each iteration. 我需要创建xrange的Python 3实现(通过将所有xrangerange交换),然后将该函数包装在一个新的生成器中,该生成器在每次迭代时都应用itertools.permutations The code below is the result. 下面的代码是结果。

def algorithm_u(ns, m):
    """
    - Python 3 implementation of
        Knuth in the Art of Computer Programming, Volume 4, Fascicle 3B, Algorithm U
    - copied from Python 2 implementation of the same at
        https://codereview.stackexchange.com/questions/1526/finding-all-k-subset-partitions
    - the algorithm returns
        all set partitions with a given number of blocks, as a python generator object

    e.g.
        In [1]: gen = algorithm_u(['A', 'B', 'C'], 2)

        In [2]: list(gen)
        Out[2]: [[['A', 'B'], ['C']],
                  [['A'], ['B', 'C']],
                  [['A', 'C'], ['B']]]
    """

    def visit(n, a):
        ps = [[] for i in range(m)]
        for j in range(n):
            ps[a[j + 1]].append(ns[j])
        return ps

    def f(mu, nu, sigma, n, a):
        if mu == 2:
            yield visit(n, a)
        else:
            for v in f(mu - 1, nu - 1, (mu + sigma) % 2, n, a):
                yield v
        if nu == mu + 1:
            a[mu] = mu - 1
            yield visit(n, a)
            while a[nu] > 0:
                a[nu] = a[nu] - 1
                yield visit(n, a)
        elif nu > mu + 1:
            if (mu + sigma) % 2 == 1:
                a[nu - 1] = mu - 1
            else:
                a[mu] = mu - 1
            if (a[nu] + sigma) % 2 == 1:
                for v in b(mu, nu - 1, 0, n, a):
                    yield v
            else:
                for v in f(mu, nu - 1, 0, n, a):
                    yield v
            while a[nu] > 0:
                a[nu] = a[nu] - 1
                if (a[nu] + sigma) % 2 == 1:
                    for v in b(mu, nu - 1, 0, n, a):
                        yield v
                else:
                    for v in f(mu, nu - 1, 0, n, a):
                        yield v

    def b(mu, nu, sigma, n, a):
        if nu == mu + 1:
            while a[nu] < mu - 1:
                yield visit(n, a)
                a[nu] = a[nu] + 1
            yield visit(n, a)
            a[mu] = 0
        elif nu > mu + 1:
            if (a[nu] + sigma) % 2 == 1:
                for v in f(mu, nu - 1, 0, n, a):
                    yield v
            else:
                for v in b(mu, nu - 1, 0, n, a):
                    yield v
            while a[nu] < mu - 1:
                a[nu] = a[nu] + 1
                if (a[nu] + sigma) % 2 == 1:
                    for v in f(mu, nu - 1, 0, n, a):
                        yield v
                else:
                    for v in b(mu, nu - 1, 0, n, a):
                        yield v
            if (mu + sigma) % 2 == 1:
                a[nu - 1] = 0
            else:
                a[mu] = 0
        if mu == 2:
            yield visit(n, a)
        else:
            for v in b(mu - 1, nu - 1, (mu + sigma) % 2, n, a):
                yield v

    n = len(ns)
    a = [0] * (n + 1)
    for j in range(1, m + 1):
        a[n - m + j] = j - 1
    return f(m, n, 0, n, a)

class algorithm_u_permutations:
    """
    generator for all permutations of all set partitions with a given number of blocks
    e.g.
        In [4]: gen = algorithm_u_permutations(['A', 'B', 'C'], 2)

        In [5]: list(gen)
        Out[5]:
        [(['A', 'B'], ['C']),
         (['C'], ['A', 'B']),
         (['A'], ['B', 'C']),
         (['B', 'C'], ['A']),
         (['A', 'C'], ['B']),
         (['B'], ['A', 'C'])]
    """

    from itertools import permutations

    def __init__(self, ns, m):

        self.au = algorithm_u(ns, m)
        self.perms = self.permutations(next(self.au))

    def __next__(self):

        try:
            return next(self.perms)

        except StopIteration:
            self.perms = self.permutations(next(self.au))
            return next(self.perms)

    def __iter__(self):
        return self

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 枚举 Python 中标记球和标记箱问题中的所有可能组合 - Enumerate all possible combinations in labeled balls and labeled bins problem in Python python绘图频率,连续整数标记为x轴 - python plot frequency with continuous integer labeled x-axis 如何在 yellowbrick plot 中标记 X 轴和 Y 轴? 我使用的代码如下所示 - How can I labeled the X axis and Y axis in yellowbrick plot? The code is I used is show below Python MatplotLib 绘制 x 轴,第一个 x 轴值标记为 1(而不是 0) - Python MatplotLib plot x-axis with first x-axis value labeled as 1 (instead of 0) Python colorbar ticks标记为+1的偏移量而不是指定的值 - Python colorbar ticks are labeled with an offset of +1 and not with specifed values Python - 在标记的多维数组上应用函数 - Python - Apply a function over a labeled multidimensional array 将 for 循环的输出保存在 Python 中的标记列表中 - Saving the output of a for loop in a labeled list in Python 如何获取列表中的最大值,然后将其标记为 PYTHON? - How to get the max value in list then labeled it in PYTHON? 在matplotlib / Python中为条形图单独标记的条形图 - Individually labeled bars for bar graphs in matplotlib / Python 如何切片标记的索引+ 1,python? - How to slice over a labeled index + 1, python?
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM