phparraysdistribution

Distribute total amount to a flat array of "container" elements with predefined limits


I'm trying to split items evenly through groups with a max on each group.

I have a function which receives a $groups array which declares the maximum capacity of each "group" and an $items integer which declares the total value which can be distributed across the elements of $groups.

This is my function so far:

public static function splitItems($groups, $items) {
    $n = count($groups);
    $res = array_fill(0, $n, 0);

    while ($items >= $groups[0]) {
        for ($i = $n - 1; $i >= 0; $i--) {
            if ($items >= $groups[$i]) {
                $res[$i]++;
                $items -= $groups[$i];
            }
        }
    }

    if ($items > 0) {
        $res[0]++;
    }
    return $res;
}

My function isn't properly taking into account the VALUE of array as max value. What I'm looking for are this results:

Input:

splitItems([14, 2], 10);
splitItems([6, 8, 2], 14);

Output:

Array
(
    [0] => 8
    [1] => 2
)
Array
(
    [0] => 6
    [1] => 6
    [2] => 2
)

Solution

  • This should work:

    function splitItems($groups, $items)
    {
        $n = count($groups);
        $res = array_fill(0, $n, 0);
        $groupsFilled = array_fill(0, $n, 0);;
    
        while ($items > 0 && count(array_keys($groupsFilled, 1)) < count($groupsFilled))
        {
            for ($i = $n-1; $i >= 0; $i--)
            {
                if ($res[$i] < $groups[$i])
                {
                    if ($items > 0) {
                        $res[$i]++;
                        $items--;
                    }
                }
                else $groupsFilled[$i] = 1;
            }
        }
    
        return $res;
    }
    
    print_r(splitItems([14,2],10));
    print_r(splitItems([6,8,2],14));
    print_r(splitItems([6,4,2],14)); //not enough space for all the items!
    

    Outputs:

    Array
    (
        [0] => 8
        [1] => 2
    )
    Array
    (
        [0] => 6
        [1] => 6
        [2] => 2
    )
    Array
    (
        [0] => 6
        [1] => 4
        [2] => 2
    )
    

    Key points:

    Live demo: https://3v4l.org/R8BOg