I have an array with the ids of x cakes and another associative array with the ids of y people. I want to ensure that each cake is enjoyed by exactly 2 people and that each person gets a fair share of cake overall. However, cakes must be kept whole (i.e. if the average cake per person is a fraction, this fraction will be rounded up for some, and down for others). No person can be assigned the same cake twice. For example:
$cake = array(''1','2')
$people = array('1','2','3')
In order to do so, I wish to create a new array where each row represents a cake-person assignment. As each cake is being assigned to two people, the number of rows in this table should be exactly twice the number of cakes. There will not be exactly 1 solution to this problem but a solution to the above example would be:
$cake_person = array(
'1'=>array('1', '1'),
'2'=>array('1', '2'),
'3'=>array('2', '2'),
'4'=>array('2', '3'),
)
Notice that people 1 and 3 are losing out but that is because there is no more cake to go around! Each cake must be given exactly twice.
How can I generate such a solution reliably for larger numbers of people and cakes?
Having implemented Artefacto’s useful response, I’ve decided to post my code below just in case anybody else finds it useful.
Data
//Create people array with 25 people
$people = range(1,25);
//Create cake array with 77 cakes
$cake = range(1,77);
Code
$people_cakes = array();
$totalPeople = count($people);
$idp = 0;
foreach($cakes as $cake) {
$id1 = $idp % $totalPeople;
$id2 = ($idp + 1) % $totalPeople;
$people_cakes[] = array($people[$id + 1], $cake);
$people_cakes[] = array($people[$id + 2], $cake);
$idp = $idp + 2;
}
Implement an algorithm that iterates through the cakes and assigns parts in order:
This will not give the same result as your example (person 1 will get two halves), but that was not a requirement.
Example script: