如何对N个项目进行分组?

发布于 2024-10-26 11:36:53 字数 1261 浏览 1 评论 0原文

我正在研究一个集合分区问题,需要一种方法来定义无序存储桶大小的所有组合。给定 N 个元素和恰好 M 个组,找到组大小的每种组合,使得组大小之和为 N。注意:桶的大小不能为 0。

例如,假设需要将 6 个项目放入 3 个桶中。我正在寻找的解决方案是:

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

为了平等地映射这些,我使用映射函数,如下所示:

@grouping = map { int( ($items + $_) / $groups ) } 0 .. $groups-1;

为了获得所有组合,我正在考虑某种递归函数,其中递归的每个级别 N 找到元素 N 的可能值大批。每个级别可以插入的合格值是 >= previousLevel。这就是我的想法,但必须有更好的方法来做到这一点......

sub getList($$@){
    my $itemCount = shift;
    my $groupCount = shift;
    my @currentArray = @_;
    my $positionToFill= @currentArray;
    if($positionToFill == 0){
        my $minValue = 1;
    }
    else{
        my $minValue = currentArray[$positionToFill-1];
    }
    my $currentSum = sum(@currentArray);
    return undef if $currentSum + $minValue >= $items;

    my @possibleCombinations = ();
    for(my $i = $minValue; $i < $items - $currentSum; $i++){
        $currentArray[$positionToFill] = $i;
        if($positionToFill == $groupCount-1){
            push(@possibleCombinations, \@currentArray)
        }
        else{
            push(@possibleCombinations, getList($itemCount, $groupCount, @currentArray);
        }                        
    }
    return @currentArray;
}

I am working on a set partitioning problem and need a way to define all combinations of unordered bucket sizes. Given N elements and exactly M groups, find every combination of group sizes such that the sum of the group sizes is N. Note: The size of the bucket cannot be 0.

For example, assume 6 items need to be placed in 3 buckets. The solution I'm looking for is:

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

To map these equally, I use a map function as follows:

@grouping = map { int( ($items + $_) / $groups ) } 0 .. $groups-1;

To get all combinations I'm thinking some kind of recursive function where each level of recursion N finds the possible values for element N in the array. The eligible values each level can insert is >= previousLevel. This is sort of what I'm thinking but there has got to be a better way to do this....

sub getList($@){
    my $itemCount = shift;
    my $groupCount = shift;
    my @currentArray = @_;
    my $positionToFill= @currentArray;
    if($positionToFill == 0){
        my $minValue = 1;
    }
    else{
        my $minValue = currentArray[$positionToFill-1];
    }
    my $currentSum = sum(@currentArray);
    return undef if $currentSum + $minValue >= $items;

    my @possibleCombinations = ();
    for(my $i = $minValue; $i < $items - $currentSum; $i++){
        $currentArray[$positionToFill] = $i;
        if($positionToFill == $groupCount-1){
            push(@possibleCombinations, \@currentArray)
        }
        else{
            push(@possibleCombinations, getList($itemCount, $groupCount, @currentArray);
        }                        
    }
    return @currentArray;
}

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

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

发布评论

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

评论(1

爱已欠费 2024-11-02 11:36:53

要将 N 个项目分为 M 组,最终需要一个递归函数将 N-1(或更少)项目分为 M-1 组。

sub partition {
    # @results is a list of array references, the part of the partitions
    # created in previous iterations
    my ($N, $M, @results) = @_;

    if ($M == 1) {
        # only one group. All elements must go in this group.
        return map [ sort {$a <=> $b} @$_, $N ], @results;
    }

    # otherwise, put from 1 to $N/$M items in the next group,
    # and invoke this function recursively
    my @new_results = ();
    for (my $n = 1; $n <= $N/$M; $n++) {
        push @new_results, partition($N-$n, $M-1,
                                map [ @$_, $n ] @results);
    }
    return @new_results;
}

并通过像这样的调用来启动该过程,

@all_partitions = partition(6, 3, []);    #  [] = list with one ref to an empty array

此方法将产生一些重复项,您必须过滤掉这些重复项,但总的来说,它会非常有效。

To group N items into M groups, ultimately you need a recursive function that groups N-1 (or fewer) items into M-1 groups.

sub partition {
    # @results is a list of array references, the part of the partitions
    # created in previous iterations
    my ($N, $M, @results) = @_;

    if ($M == 1) {
        # only one group. All elements must go in this group.
        return map [ sort {$a <=> $b} @$_, $N ], @results;
    }

    # otherwise, put from 1 to $N/$M items in the next group,
    # and invoke this function recursively
    my @new_results = ();
    for (my $n = 1; $n <= $N/$M; $n++) {
        push @new_results, partition($N-$n, $M-1,
                                map [ @$_, $n ] @results);
    }
    return @new_results;
}

and start the process with a call like

@all_partitions = partition(6, 3, []);    #  [] = list with one ref to an empty array

This method will produce a few duplicates that you'll have to filter out, but overall it will be pretty efficient.

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