skip to Main Content

I have a 2d array of "packs" with their own specified size in centimeters. I need to optimally distribute these packs into a new 3d array to represent pallets of packs which each have a maximum capacity of 265cm.

Current code which works with a 1d array of sizes:

$default_cc_height_fa = 265; // size of the pallet in cm
$sh_array = [50, 45, 30, 60, 70, 80]; // array of packs

// sort the array of packs in decreasing order of size
usort($sh_array, function($a, $b) {
    return $b - $a;
});

// initialize the array of pallets
$mix_cc_array = [];

// iterate through the array of packs
foreach ($sh_array as $pack) {
    // try to fit the pack into an existing pallet
    $packed = false;
    foreach ($mix_cc_array as &$pallet) {
        if ($pack <= $default_cc_height_fa - array_sum($pallet)) {
            $pallet[] = $pack;
            $packed = true;
            break;
        }
    }
    // if the pack does not fit into any existing pallet, create a new one
    if (!$packed) {
        $mix_cc_array[] = [$pack];
    }
}

print_r($mix_cc_array);

How is it possible to adjust the above code to accommodate a 2d array like this:

$sh_array = [
    ['id_product' => 13, 'size' => 50],
    ['id_product' => 13, 'size' => 45],
    ['id_product' => 13, 'size' => 30],
    ['id_product' => 13, 'size' => 60],
    ['id_product' => 13, 'size' => 70],
    ['id_product' => 13, 'size' => 80]
];
// array of array of packs

Of course, I need to manage the sizes, but I need entire rows of data (packs) to be pushed into the subarrays (pallets).

2

Answers


  1. With minor modifications, we can loop through an array of packs that have both id and size attributes. To make the comparison between the size of the current pack and the maximum height constant, we can also add attributes to the pack to accumulate everything.

    Finally, because I was interested in exiting both loops, I used continue 2 although you could keep your original $packed = false; approach as well.

    <?php
    const DEFAULT_CC_HEIGHT_FA = 265; // size of the pallet in cm
    
    // define array of products to add
    $sh_array = [["id_product" => 13, "size" => 50],
                ["id_product" => 13, "size" => 45],
                ["id_product" => 13, "size" => 30],
                ["id_product" => 13, "size" => 60],
                ["id_product" => 13, "size" => 70],
                ["id_product" => 13, "size" => 80]];
    
    // sort the array of packs in decreasing order of size
    usort($sh_array, function($a, $b) {
        return $b["size"] - $a["size"];
    });
    
    // initialize the array of pallets
    $mix_cc_array = [];
    
    // iterate through the array of packs
    foreach ($sh_array as $listRow) {
        // try to fit the pack into an existing pallet
        foreach ($mix_cc_array as &$pallet) {
    
            $newHeight = $listRow["size"] + $pallet["totalHeight"];
    
            if ($newHeight <= DEFAULT_CC_HEIGHT_FA) {
                // add new pack to this pallet
                array_push($pallet["pallets"],$listRow);
                
                // update accumulators
                $pallet["palletsStored"] += 1;
                $pallet["totalHeight"] = $newHeight;
    
                // continue the outer loop
                continue 2;
            }
        }
    
        // if the pack does not fit into any existing pallet, create a new one
        $mix_cc_array[] = array("totalHeight"=> $listRow["size"],
            "palletsStored" => 1, "pallets" => [$listRow]);
    }
    
    print_r($mix_cc_array);
    
    Login or Signup to reply.
  2. The only difference between my earlier answer and this answer is how to sort and count the array data. The algorithm remains the same.

    Code: (Demo)

    $pallet_limit = 111;
    $packs = [
        ['id_product' => 13, 'size' => 50],
        ['id_product' => 13, 'size' => 45],
        ['id_product' => 13, 'size' => 30],
        ['id_product' => 13, 'size' => 60],
        ['id_product' => 13, 'size' => 70],
        ['id_product' => 13, 'size' => 80]
    ];
    
    usort($packs, fn($a, $b) => $b["size"] <=> $a["size"]);
    
    $pallets = [];
    foreach ($packs as $pack) {
        foreach ($pallets as &$pallet) {
            if ((array_sum(array_column($pallet, 'size')) + $pack["size"]) <= $pallet_limit) {
                $pallet[] = $pack;
                continue 2;
            }
        }
        $pallets[] = [$pack];
    }
    var_export($pallets);
    
    1. Sort the rows by size value in a descending direction.
    2. Iterate your array of products.
    3. Iterate a new array where pallets will be stored.
    4. If a given pack "fits" in an encountered pallet, push it into that pallet; otherwise check the subsequent pallets; if no pallet is suitable, create a new pallet and push the pack into it.
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search