0

我正在编写一个 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";
         }

    }
}

我在这里这里找到了类似的解决方案,但它们的条件与我不同。也可能有更好的方法来处理错误,但这可以在几次重新运行后完成。

我的问题是,有时它与您去年的同一个人配对(最常见的是最后一个结果与两年相同)。我的 while 循环有什么问题?

我假设以下 while 语句:

 $toList[$row] == $lastYear[$row]   

没有被解释成我想要的样子。但这在理论上似乎是正确的。

4

1 回答 1

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>";
于 2013-06-10T21:13:11.420 回答