如何组织一个不准确的分区?

时间:2017-03-02 03:09:42

标签: php

我有很多参与者和一些团体,我必须将参与者组织成小组。

示例:

10/3 = 3, 3 and 4.
10/9 = 2,2,2 and 4.
23/3 = 6,6,6 and 5.

我已尝试使用size参数作为参与者/群组的舍入结果使用array_chunk,但它没有正常工作。

编辑,我的问题解决了。

    $groups           = $this->request->data['phases_limit'];
    $classified_lmt   = $this->request->data['classified_limit'];

    $participants     = count($game->user_has_game);

    $participants_lmt = floor($participants / $groups);
    $remainders       = $participants % $groups;

    if ($groups > $participants) {
        throw new \Exception("Há mais grupos que participantes");
    }

    for ($i=0; $i < $groups; $i++) {
        $p = $this->Phase->newEntity();
        $p->name             = 'Grupo #' . $game->id;
        $p->game_id          = $game->id;
        $p->classified_limit = $classified_lmt;
        $this->Phase->save($p);

        // add the number of participants per group
        for ($j=0; $j < $participants_lmt; $j++) {
            $user_has_game = array_pop($game->user_has_game);
            $g                   = $this->Phase->GroupUserHasGame->newEntity();
            $g->group_id         = $p->id;
            $g->user_has_game_id = $user_has_game->id;
            $this->Phase->GroupUserHasGame->save($g);
        }

        // check if it is the last iteration
        if (($groups - 1) == $i) {
            // add the remainders on the last iteration
            for ($k=0; $k < $remainders; $k++) {
                $user_has_game  = array_pop($game->user_has_game);
                $g                   = $this->Phase->GroupUserHasGame->newEntity();
                $g->group_id         = $p->id;
                $g->user_has_game_id = $user_has_game->id;
                $this->Phase->GroupUserHasGame->save($g);
            }
        }
    }

2 个答案:

答案 0 :(得分:2)

您是否尝试过模数运算符?它将分子除以分母后给出余数。

例如,如果您想将10个人分成3组:

$("#memo").popover({
    trigger: 'click',
    placement: 'right',
    html: true,
    content: '<textarea class="popover-textarea"></textarea>',
    template: '<div class="popover"><div class="arrow"></div>' +
              '<h3 class="popover-title"></h3><div class="popover-content">' +
              '</div><div class="popover-footer"><button type="button" class="btn btn-primary popover-submit">' +
              '<span class="glyphicon glyphicon-ok" aria-hidden="true"></span></button>&nbsp;' +
              '<button type="button" class="btn btn-default popover-cancel">' +
              '<span class="glyphicon glyphicon-remove" aria-hidden="true"></span></button></div></div>'
})
.on('shown', function() {

    $('#memo').not(this).popover("hide");
    var $this = $(this);

    //attach the specialInstructions variable to the text
    $('.popover-textarea #memo').val((specialInstructions == null) ? '' : specialInstructions).focus();

    $('.popover-textarea #memo').val("testing").focus();

    // close on cancel
    $('.popover-cancel #memo').click(function() {
        $("#memo").popover('hide');
    });

    $('.popover-submit #memo').click(function() {
        specialInstructions = $('.popover-textarea').val();
        $("#memo").popover('hide');
    });
});

编辑 - 我将以下功能作为原始答案的一部分。这对OP不起作用,但是我想把它留在这里,因为它可能会帮助其他人。

floor(10 / 3) = 3; // people per group
10 % 3 = 1; // 1 person left over to add to an existing group.

答案 1 :(得分:0)

不确定是否有现成的库。如果您需要一些想法,我只是在Java中实现了类似的东西:

  public List<Integer> createDistribution(int population_size, int groups) {
        List<Integer> lst = new LinkedList();
        int total = 0;
        for (double d : createDistribution(groups)) {
            // this makes smaller groups first int i = new Double(population_size * d).intValue();
            int i = (int)Math.round(population_size * d);
            total += i;
            lst.add(i);
        }
        // Fix rounding errors
        while (total < population_size) {
            int i = r.nextInt(groups);
            lst.set(i, lst.get(i) + 1);
            total += 1;
        }
        while (total > population_size) {
            int i = r.nextInt(groups);
            if (lst.get(i) > 0) {
                lst.set(i, lst.get(i) - 1);
                total -= 1;
            }
        }
        return lst;
    }