Reputation: 567
Suppose I have the array:
array(1,1,2,1,4,5,7,2,3);
What would be the fastest way to get these numbers into x arrays we'll use 3 and have the numbers be as equal as possible with the larger numbers at the end?
Example:
array(1, 1, 1, 5);
array(7, 2);
array(4, 2, 3);
I'm worried that this might be a p=np problem but it seems so simple that it shouldn't be. I just can't seem to figure it out.
Similar question: Algorithm to split an array into P subarrays of balanced sum
Upvotes: 5
Views: 1222
Reputation: 307
Not exactly what you're looking for, but this should help get you started:
$array = array(1,1,2,1,4,5,7,2,3);
asort($array);
$total = array_sum($array);
$array1 = array();
$array2 = array();
$array3 = array();
foreach($array as $number) {
if(array_sum($array1) < round($total / 3)) {
array_push($array1, $number);
} elseif(array_sum($array2) < round($total / 3)) {
array_push($array2, $number);
} else {
array_push($array3, $number);
}
}
for($i = 1; $i <= 3; $i++) {
switch($i) {
case 1:
$op1 = 2;
$op2 = 1;
break;
case 2:
$op1 = -1;
$op2 = 1;
break;
case 3:
$op1 = -2;
$op2 = -1;
break;
}
foreach(${'array' . $i} as $number) {
if((array_sum(${'array' . ($i + $op1)}) + $number) == round($total / 3)) {
unset(${'array' . $i}[array_search($number, ${'array' . $i})]);
array_push(${'array' . ($i + $op1)}, $number);
} elseif((array_sum(${'array' . ($i + $op2)}) + $number) == round($total / 3)) {
unset(${'array' . $i}[array_search($number, ${'array' . $i})]);
array_push(${'array' . ($i + $op2)}, $number);
}
}
}
print_r($array1);
print_r($array2);
print_r($array3);
New Output:
Array
(
[0] => 1
[1] => 1
[2] => 1
[4] => 2
[5] => 3
)
Array
(
[0] => 4
[1] => 5
)
Array
(
[0] => 7
[1] => 2
)
Upvotes: 2
Reputation: 5371
Essentially you can use array_slice
to strip out the chunks you need and asort
to sort the array from least to greatest first.
The code below will do the trick:
(edit: after a recent comment I'm confused, are you saying you want the sum of the numbers in the array to be close to the same? I thought you meant you wanted the arrays to be evenly split in size not sum?)
$arr = array(1,1,2,1,4,5,7,2,3);
asort($arr); // sort the array
$x = 3; // number of arrays
$offset = ceil(count($arr) / $x);
$newArrays = array();
for($i=0;$i<=count($arr)-1;$i+=$offset) {
$newArrays[] = array_slice($arr,$i,$offset);
}
var_dump($newArrays);
Result:
array(3) {
[0]=>
array(3) {
[0]=>
int(1)
[1]=>
int(1)
[2]=>
int(1)
}
[1]=>
array(3) {
[0]=>
int(2)
[1]=>
int(2)
[2]=>
int(3)
}
[2]=>
array(3) {
[0]=>
int(4)
[1]=>
int(5)
[2]=>
int(7)
}
}
Upvotes: 2