(有序)在固定大小的块中设置分区

发布于 2024-10-09 14:45:24 字数 2556 浏览 7 评论 0 原文

这是我想写的一个函数,但无法这样做。即使你 不/不能给出解决方案,如果有提示,我将不胜感激。例如, 我知道有序表示之间存在相关性 整数和有序集分区的总和,但仅此一点并不能帮助我 找到解决方案。所以这里是我需要的函数的描述:


任务

创建一个高效的*函数

List<int[]> createOrderedPartitions(int n_1, int n_2,..., int n_k)

,返回集合的所有集合部分的数组列表 {0,...,n_1+n_2+...+n_k-1} 位于 参数数量 大小的块中(在此 顺序)n_1,n_2,...,n_k(例如n_1=2, n_2=1, n_3=1 -> ({0,1},{3},{2 }),...)。

这是一个用法示例:

int[] partition = createOrderedPartitions(2,1,1).get(0);
partition[0]; // -> 0
partition[1]; // -> 1
partition[2]; // -> 3
partition[3]; // -> 2

请注意,列表中的元素数量是 (n_1+n_2+...+n_n 选择 n_1) * (n_2+n_3+...+n_n 选择 n_2) * ... * (n_k 选择 n_k)。此外,createOrderedPartitions(1,1,1) 将创建 {0,1,2} 的排列,因此会有 3! = 6 元素 列表。

* 通过高效我的意思是你不应该最初创建一个更大的列表 像所有分区一样,然后过滤掉结果。你应该直接这样做。

额外要求

如果参数为 0,则将其视为不存在,例如 createOrderedPartitions(2,0,1,1) 应该产生与以下相同的结果 createOrderedPartitions(2,1,1)。但至少有一个参数不能为 0。 当然,所有参数必须 >= 0。

备注

提供的伪代码是准 Java,但解决方案的语言 没关系。事实上,只要解决方案相当通用并且可以 能用其他语言复制是理想的。

实际上,更好的是 List> 返回类型(例如,当 在 Python 中创建这样的函数)。然而,随后的论点有 不得忽略 0 值。 createOrderedPartitions(2,0,2) 然后 创建

[({0,1},{},{2,3}),({0,2},{},{1,3}),({0,3},{},{1,2}),({1,2},{},{0,3}),...]


背景

我需要这个功能来使我的 mastermind-variation 机器人更加高效和 最重要的是代码更“漂亮”。看一下 filterCandidates 我的源代码中的函数。有不必要的 / 重复查询,因为我只是使用排列而不是 特别订购的分区。另外,我只是对如何写感兴趣 这个功能。


我对(丑陋的)“解决方案”的想法

创建 {0,...,n_1+...+n_k} 的幂集,过滤掉 size 的子集 n_1, n_2 等并创建 n 个子集的笛卡尔积。然而 这实际上行不通,因为会有重复项,例如 ({1,2},{1})...

首先选择 x = {0,...,n_1+n_2+... 中的 n_1 +n_n-1} 并将它们放入 第一组。然后选择 x 中的 n_2,不包含 n_1 个所选元素 事先等等。然后您会得到例如 ({0,2},{},{1,3},{4})。的 当然,必须创建每种可能的组合,因此 ({0,4},{},{1,3},{2}), 也是如此,等等。似乎很难实施,但也许是可能的。


研究

我猜这个 朝着我想要的方向发展,但我不知道如何将它用于我的 具体场景。

http://rosettacode.org/wiki/Combinations

Here is a function I would like to write but am unable to do so. Even if you
don't / can't give a solution I would be grateful for tips. For example,
I know that there is a correlation between the ordered represantions of the
sum of an integer and ordered set partitions but that alone does not help me in
finding the solution. So here is the description of the function I need:

The Task

Create an efficient* function

List<int[]> createOrderedPartitions(int n_1, int n_2,..., int n_k)

that returns a list of arrays of all set partions of the set
{0,...,n_1+n_2+...+n_k-1} in number of arguments blocks of size (in this
order) n_1,n_2,...,n_k (e.g. n_1=2, n_2=1, n_3=1 -> ({0,1},{3},{2}),...).

Here is a usage example:

int[] partition = createOrderedPartitions(2,1,1).get(0);
partition[0]; // -> 0
partition[1]; // -> 1
partition[2]; // -> 3
partition[3]; // -> 2

Note that the number of elements in the list is
(n_1+n_2+...+n_n choose n_1) * (n_2+n_3+...+n_n choose n_2) * ... *
(n_k choose n_k)
. Also, createOrderedPartitions(1,1,1) would create the
permutations of {0,1,2} and thus there would be 3! = 6 elements in the
list.

* by efficient I mean that you should not initially create a bigger list
like all partitions and then filter out results. You should do it directly.

Extra Requirements

If an argument is 0 treat it as if it was not there, e.g.
createOrderedPartitions(2,0,1,1) should yield the same result as
createOrderedPartitions(2,1,1). But at least one argument must not be 0.
Of course all arguments must be >= 0.

Remarks

The provided pseudo code is quasi Java but the language of the solution
doesn't matter. In fact, as long as the solution is fairly general and can
be reproduced in other languages it is ideal.

Actually, even better would be a return type of List<Tuple<Set>> (e.g. when
creating such a function in Python). However, then the arguments wich have
a value of 0 must not be ignored. createOrderedPartitions(2,0,2) would then
create

[({0,1},{},{2,3}),({0,2},{},{1,3}),({0,3},{},{1,2}),({1,2},{},{0,3}),...]

Background

I need this function to make my mastermind-variation bot more efficient and
most of all the code more "beautiful". Take a look at the filterCandidates
function in my source code. There are unnecessary
/ duplicate queries because I'm simply using permutations instead of
specifically ordered partitions. Also, I'm just interested in how to write
this function.

My ideas for (ugly) "solutions"

Create the powerset of {0,...,n_1+...+n_k}, filter out the subsets of size
n_1, n_2 etc. and create the cartesian product of the n subsets. However
this won't actually work because there would be duplicates, e.g.
({1,2},{1})...

First choose n_1 of x = {0,...,n_1+n_2+...+n_n-1} and put them in the
first set. Then choose n_2 of x without the n_1 chosen elements
beforehand
and so on. You then get for example ({0,2},{},{1,3},{4}). Of
course, every possible combination must be created so ({0,4},{},{1,3},{2}),
too, and so on. Seems rather hard to implement but might be possible.

Research

I guess this
goes in the direction I want however I don't see how I can utilize it for my
specific scenario.

http://rosettacode.org/wiki/Combinations

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

神仙妹妹 2024-10-16 14:45:24

您知道,表达您的想法通常有助于找到解决方案。似乎潜意识就开始处理任务,并在找到解决方案时通知你。所以这是我在 Python 中的问题的解决方案:

from itertools import combinations

def partitions(*args):
    def helper(s, *args):
        if not args: return [[]]
        res = []
        for c in combinations(s, args[0]):
            s0 = [x for x in s if x not in c]
            for r in helper(s0, *args[1:]):
                res.append([c] + r)
        return res
    s = range(sum(args))
    return helper(s, *args)

print partitions(2, 0, 2)

输出是:

[[(0, 1), (), (2, 3)], [(0, 2), (), (1, 3)], [(0, 3), (), (1, 2)], [(1, 2), (), (0, 3)], [(1, 3), (), (0, 2)], [(2, 3), (), (0, 1)]]

它足以将算法翻译为 Lua/Java。这基本上是我的第二个想法。

算法

正如我在问题中已经提到的,基本思想如下:

首先选择集合 s := {0,...,n_1+n_2+...+ 的 n_1 个元素n_n-1} 并将它们放入
结果列表中第一个元组的第一组(例如,如果所选元素为 0,1,2,则 [({0,1,2},...)然后选择集合 s_0 := s 中的 n_2 个元素,而无需事先选择 n_1 个元素,这样的元组可能是 ({0,2。 },{},{1,3},{4})
当然,每种可能的组合都会被创建,因此 ({0,4},{},{1,3},{2}) 是另一个这样的元组,依此类推。

实现

首先创建要使用的集合(s = range(sum(args)))。然后这个集合和参数被传递给递归辅助函数helper

helper 执行以下操作之一: 如果处理了所有参数,则返回“某种空值”以停止递归。否则,迭代传递的长度 args[0] 的集合 s 的所有组合(helper 中 s 之后的第一个参数)。在每次迭代中创建不包含 c 中的元素的集合 s0 := sc 中的元素是从 s 中选择的元素),其中然后用于 helper 的递归调用。

那么 helper 中的参数会被一一处理。 helper 可能首先以 helper([0,1,2,3], 2, 1, 1) 开头,在下一次调用中它是 helper ([2,3], 1, 1),然后是 helper([3], 1),最后是 helper([])。当然,另一个“树路径”是 helper([0,1,2,3], 2, 1, 1), helper([1,2], 1, 1 ) 、 helper([2], 1)helper([])。创建所有这些“树路径”,从而生成所需的解决方案。

You know, it often helps to phrase your thoughts in order to come up with a solution. It seems that then the subconscious just starts working on the task and notifies you when it found the solution. So here is the solution to my problem in Python:

from itertools import combinations

def partitions(*args):
    def helper(s, *args):
        if not args: return [[]]
        res = []
        for c in combinations(s, args[0]):
            s0 = [x for x in s if x not in c]
            for r in helper(s0, *args[1:]):
                res.append([c] + r)
        return res
    s = range(sum(args))
    return helper(s, *args)

print partitions(2, 0, 2)

The output is:

[[(0, 1), (), (2, 3)], [(0, 2), (), (1, 3)], [(0, 3), (), (1, 2)], [(1, 2), (), (0, 3)], [(1, 3), (), (0, 2)], [(2, 3), (), (0, 1)]]

It is adequate for translating the algorithm to Lua/Java. It is basically the second idea I had.

The Algorithm

As I already mentionend in the question the basic idea is as follows:

First choose n_1 elements of the set s := {0,...,n_1+n_2+...+n_n-1} and put them in the
first set of the first tuple in the resulting list (e.g. [({0,1,2},... if the chosen elements are 0,1,2). Then choose n_2 elements of the set s_0 := s without the n_1 chosen elements beforehand and so on. One such a tuple might be ({0,2},{},{1,3},{4}). Of
course, every possible combination is created so ({0,4},{},{1,3},{2}) is another such tuple and so on.

The Realization

At first the set to work with is created (s = range(sum(args))). Then this set and the arguments are passed to the recursive helper function helper.

helper does one of the following things: If all the arguments are processed return "some kind of empty value" to stop the recursion. Otherwise iterate through all the combinations of the passed set s of the length args[0] (the first argument after s in helper). In each iteration create the set s0 := s without the elements in c (the elements in c are the chosen elements from s), which is then used for the recursive call of helper.

So what happens with the arguments in helper is that they are processed one by one. helper may first start with helper([0,1,2,3], 2, 1, 1) and in the next invocation it is for example helper([2,3], 1, 1) and then helper([3], 1) and lastly helper([]). Of course another "tree-path" would be helper([0,1,2,3], 2, 1, 1), helper([1,2], 1, 1), helper([2], 1), helper([]). All these "tree-paths" are created and thus the required solution is generated.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文