我正在编写一个PHP脚本,它基本上是一个礼品袋(从帽子中拉出名字)。但是有一些条件:
- 你不能与你的配偶配对
- 你不能拥有去年的人
- 你不能拥有自己(显然)
我写了一个代码:
// I'm using a multidimensional array so I can check the spouses
$array = array(
array('Husband1', 'Wife1'),
array('Husband2', 'Wife2'),
array('Husbad3', 'Wife3'),
array('Single1'),
array('Single2'),
);
// if you were to sort the above array - here is their recipients lastYear
$lastYear = array(
'Single1',
'Husbad3',
'Single2',
'Wife3',
'Husband1',
'Wife2',
'Husband2',
'Wife1',
);
// declaring an empty values
$that = array();
$n = 0;
// converts multidimensional array to 2 identical arrays
for ($row = 0; $row < count($array); $row++)
{
for ($col = 0; $col < 2; $col++)
{
if (isset($array[$row][$col]))
{
$toList[] = $array[$row][$col];
$fromList[] = $array[$row][$col];
}
}
}
echo "Last Year \n";
// creates a list for last year
for ($row = 0; $row < count($toList); $row++)
{
echo $toList[$row] . " had " . $lastYear[$row] . "\n";
}
// randomly mixes up the to the toList
shuffle($toList);
echo "This Year \n";
// pairs the multidimensional array 1 index at a time
for ($row = 0; $row < count($array); $row++)
{
for ($col = 0; $col < 2; $col++)
{
// if it exists then print it out
if (isset($array[$row][$col]))
{
// if the toList index is the same person (as in $array), or already paired (in $that array), or a spouse (in $array), or the same person as last year - RESHUFFLE
while ($array[$row][$col] == $toList[$row] or in_array($toList[$row], $that) or in_array($toList[$row],$array[$row]) or $toList[$row] == $lastYear[$row])
{
// if it takes more then 200 Shuffles - BREAK
if ($n > 200)
{
echo "I'm Broke!! \n";
exit;
}
shuffle($toList);
$n++;
}
// once you find a match, add it to $that array and move on
$that[] = $toList[$row];
echo $array[$row][$col] . " has " . $toList[$row] . "\n";
}
}
}
我找到了类似的解决方案here和here,但它们的条件与我没有相同。可能有更好的方法来处理错误,但这可以在几次重新运行后完成工作。
我的问题是,有时它与你去年的同一个人配对(最常见的是最后一个结果与两年相同)。我的while循环有什么问题?
我假设以下语句:
$toList[$row] == $lastYear[$row]
没有被解释为我想要它。但这似乎在理论上是正确的。
答案 0 :(得分:0)
这应该让你开始:
$lastYear = array(
"Husband1" => "Single1",
"Wife1" => "Husbad3",
"Husband2" => "Single2",
"Wife2" => "WIfe3",
"Husbad3" => "Husband1",
"Wife3" => "Wife2",
"Single1" => "Husband2",
"Single2" => "Wife1");
$spouses = array(
'Husband1' => 'Wife1',
'Husband2' => 'Wife2',
'Husbad3' => 'Wife3',
'Single1' => null,
'Single2' => null);
// Add corresponding spouses to $spouses
foreach($spouses as $key => $value)
if($value !==null)
$spouses[$value] = $key;
$thisYear = array(); // To hold this year's assignments
$tos = array(); // Temp var to hold potential assignment
$iterations=0; // Count number of times through the loop (fail after 100)
do
{
$success=true; // will set to false if anyone can't be assigned
foreach(array_keys($lastYear) as $key)
{
$thisYear[$key] = null; // null out all "to"s
$tos[] = $key; // create temp array with copy of "from" list
}
// go through each "from" person
foreach(array_keys($thisYear) as $from)
{
// shuffle the "to" array which contains remaining potential "to" people
shuffle($tos);
// start with the last item in $to[]. If it's ineligible for any reason, then we'll check the previous one, and so on
$checkTo=count($tos)-1;
do
{
$to = $tos[$checkTo];
if($to !== $from
&& $spouses[$from] !== $to
&& $lastYear[$from] !== $to)
{
// $to is an eligible assignment for $from. Add it to $thisYear, and remove it from $tos[]
$thisYear[$from] = $to;
array_splice($tos,$checkTo,1);
break;
}
} while (--$checkTo >= 0);
// if checkTo < 0, then there are no eligible assignments for $from. Set $success=false so we'll try again
if($checkTo<0)
{
$success=false;
break;
}
}
} while($success==false && $iterations++ < 100);
foreach($thisYear as $key => $value)
echo "$key is assigned to $value<br>";