PHP将变量除以多个多维数组以不产生余数

The project I have is a reimbursement of materials in a game. The materials come in various packages listed in the array below. Part of my code gives me the total number of units I need to reimburse, and I have to use the "packages" from the array below.

This is the multi dimensional array. The $item['ore'][100] array indicates that the item listed gives 100 units when used and stacks to only 100 (key => stacksize). Likewise for $item['ore'][500] gives 500 units when used and only stacks to 100:

$item = array(
 'ore'  =>  array(
    100 => array(
        'name'  => "Item 1",
        'stacksize' => 100,
    ),
    500 => array(
        'name'  =>  "Item 2",
        'stacksize' => 100,
    ),
    1000    =>  array(
        'name'  => "Item 3",
        'stacksize' => 100,
    ),
),

So, 1x Item 1 gives 100 units, 1x Item 2 gives 500 units and 1x Item 3 gives 1000 units. My $totalOre variable from part of my code dictates that I have 15,825 units to reimburse total (as an example). Obviously I'll have some extra that will be reimbursed as I don't have an item that gives smaller than 100 units (not a big deal if the user gets a bit more in this case).

So I need a code snippet to tell me that I need to reimburse 15x Item 3, 1x Item 2 and 4x Item 1 for a total of 15,900 units.

Additionally, if I have say....$totalOre = 219,427, I need my code to dictate that I send 100x Item 3, then 100x Item 3, then 19x Item 3, then 1x Item 2 for a total of 219,500 units, because of the 'stacksize' limitation of 100 (I can't send a user more than 100x of these items or they won't get them).

I assume some sort of loop would be needed in addition the Modulus (%) operator. I tried

$reimburseOre = 0;
$reimburseOre = $reimburseOre % $items['ore'][1000];

and came up with 0. Any assistance you can provide would be greatly appreciated, even just a hand in the right direction.

Thank you.

EDIT: Tried adding a 'Qty' key to my array (set to 1000) and then the following snippet of code and the result was -523 (not correct at all):

    $oreReimbursement = 0;
    if ($totalOre % $items['ore'][1000]['Qty'] != 0) {
        $oreReimbursement -= $totalOre % $items['ore'][1000]['Qty'];
    }
    echo $oreReimbursement; ?>

Here's some code to get you on your way. You'll have to work out the stacks, but this should help with knowing what combination of ore lots you have to repay.

# $target is the amount of ore to be repaid
$target = 481726;

# first, reverse sort the keys of 'ore' so they're in descending numerical order
krsort( $item['ore'] );
# initialise an array to contain our "order" of ore.
$order = [];

# for every value of ore, starting with the largest amount
foreach ( $item['ore'] as $a => $v ) {
    # if the target to be reached is larger than the amount, $a
    if ($target > $a) {
        # floor( $target / $a ) means round down $target/$a to the nearest integer
        # add the name (Item x) and the rounded down number to the order.
        $order[ $v["name"] ] = floor($target / $a);
        # reset $target to the remainder
        $target = $target % $a;
    }
}

# if we still have some ore left to give, add one lot of the smallest ore quantity
if ($target) {
    ( isset($order[ $v["name"] ]) )
    ? $order[ $v["name"] ]++
    : $order[ $v["name"] ] = 1;
}

print_r($order);

Output for 481726:

Array
(
    [Item 3] => 481
    [Item 2] => 1
    [Item 1] => 3
)

You should be able to work out how to divide the 485 stacks into sets of 100.

$totalOre = 15825;
$totalWood = 219427;

reimburse($item['ore'], $totalOre);
reimburse($item['wood'], $totalWood);

function reimburse($units, $total) {
$unitSizes = array_keys($units);
rsort($unitSizes); // order from high to low
$temp = $total;
$actual = array();
$reimbursed = 0;
foreach($unitSizes AS $unitSize) {
  $stacks = floor($temp / $unitSize);
  $stacksize = $units[$unitSize]['stacksize'];
  $itemName = $units[$unitSize]['name'];
  while($stacks > $stacksize) {
    $actual[$itemName] += $stacksize;
    $reimbursed += $stacksize * $unitSize;
    $stacks -= $stacksize;
    $temp -= $stacksize * $unitSize;
  }
  if ($stacks > 0) {
    $actual[$itemName] += $stacks;
    $reimbursed += $stacks * $unitSize;
    $temp -= $stacks * $unitSize;
    $stacks = 0;
  }
}
if ($temp > 0) {
  $actual[$itemName]++;
  $reimbursed += $unitSize;
}
print 'Total: ' . $reimbursed . ' (' . $total . ')' . "
";
print_r($actual);
}

Output:

Total: 15900 (15825)
Array
(
    [Item 3] => 15
    [Item 2] => 1
    [Item 1] => 4
)
Total: 219500 (219427)
Array
(
    [Item 6] => 219
    [Item 4] => 5
)

See the demo.

As you can see, it has one flaw: instead of 5 times Item 4 in the wood example it should be one Item 5. To get around that, one needs to determine the final total reimbursement first.

sort($unitSizes); // order from low to high to get lowest unitsize
$smallestUnit = $unitSizes[0];
$total = ceil($total / $smallestUnit) * $smallestUnit;

See the demo.