如何在PHP中重复制作随机名称列表?

时间:2016-07-02 09:54:14

标签: php list loops random

我的任务很简单 - 我得到一个名单列表:

约翰
玫瑰
戴夫
翡翠

我需要按照这些规则为每个名字分配两个其他名称:

  1. 每个名字不能重复两次以上
  2. subname!= root name
  3. 根名称不能具有相同的子名称。
  4. 表示:

    ------ this is valid: --------------------------------------- this is not: -------
    
    John - Rose, Dave  -------------------------------  John - Dave, Dave  
    Rose - John, Jade    -------------------------------- Rose - Rose, Jade  
    Dave - Jade, Rose    ------------------------------- Dave - Jade, John  
    Jade - John, Dave   -------------------------------- Jade - John, Dave  
    
    (dave's showing more than twice,
    and John got him twice
    and Rose got herself)
    

    我一直试图解决这个问题几个小时 - 为subnames1和subnames2分配名称很简单但是当试图将它们分配给根名称时,一切都变得混乱。

    这是我最近的失败:

    $arr1 = $arr2 = $names = $arr;
            shuffle($arr1);
            shuffle($arr2);
    
            foreach ($arr1 as $key => $value) {
                $arr1[$key]['name2'] = $arr2[$key]['name'];
                $count = 0;
                foreach ($arr1 as $name) {
                    if (in_array($arr2[$key]['name'], $name)) {
                        $count++;
                    }
                }
    
    
                while ($arr1[$key]['name2'] == $arr1[$key]['name'] || $count > 2) {
                    shuffle($arr2);
                    $arr1[$key]['name2'] = $arr2[$key]['name'];
                    foreach ($arr1 as $name) {
                        if (in_array($arr2[$key]['name'], $name)) {
                            $count++;
                        }
                    }
                }
            }
    
            foreach ($names as $key => $name) {
                $randName = $names[array_rand($names)]['name'];
                while (in_array($randName, $arr1[$key]) || array_key_exists($randName, $arr1)) {
                    $randName = $names[array_rand($names)]['name'];
                }
                $arr1[$randName] = $arr1[$key];
                unset($arr1[$key]);
            }
    

    知道如何解决这个问题吗?

2 个答案:

答案 0 :(得分:0)

这个怎么样?

<?php
        $names = array("John","Rose","Dave","Jade");
        $pickedupOnce = array();
        $pickedupTwice = array();

        for($i=0; $i <count($names); $i++) {
            echo "$names[$i] <br/>";
            // this is rootname
            // now pick two random subnames

            $loop =0;
            do {
                $subOne = array_rand($names,1);
                $loop++;
            } while($subOne === $i || in_array($subOne, $pickedupTwice) && $loop<10 );

            if(in_array($subOne, $pickedupOnce)) {
                array_push($pickedupTwice, $subOne);
            }
            else {
                array_push($pickedupOnce, $subOne);
            }

            $loop = 0;
            do {
                $subTwo = array_rand($names,1);
                $loop++;

            } while($subTwo === $i || $subTwo === $subOne || in_array($subTwo, $pickedupTwice) && $loop<10 );

            if(in_array($subTwo, $pickedupOnce)) {
                array_push($pickedupTwice,$subTwo);
            }
            else {
                array_push($pickedupOnce, $subTwo);
            }

            echo "Group = $names[$i] -- $names[$subOne],$names[$subTwo] <br/>\n";
            echo "Picked Once - ";
            for($j=0; $j<count($pickedupOnce); $j++) {
                echo "$pickedupOnce[$j],";
            }

            echo "<br />Picked Twice - ";
            for($j=0; $j<count($pickedupTwice); $j++) {
                echo "$pickedupTwice[$j],";
            }
            echo "<br/>";
        }



        ?>

希望这会有所帮助......

答案 1 :(得分:0)

我不熟悉PHP语法,所以我会尝试伪代码实现,希望对你没问题

Input: nameList as string[].
Output: resultList as string[]

def secNames as string[]
    name1 as string
    name2 as string 

// make a list with two copies of all names 
for (i=0;i<length(nameList);i+1)
{ 
  secNames[i]=nameList[i]
  secNames[2*length(nameList)-i-1]=nameList[i]
}
// N.B.: first half of secondary names list is the same 
// as original, the second half is reversed so in your
// example we get: 
// "John","Rose","Dave","Jade","Jade","Dave","Rose","John"


// scan list of primary names 
for (i=0;i<length(nameList);i+1)
{
   resultList[i]=nameList[i]+" - "
   name1=""
   name2=""

   for (j=0;j<length(secNames);j+1) // scan secondary names
   {
     if (name1 <> secNames[j] and 
         name1 ="" and // skip this if found 1st sec.name 
         nameList[i] <> secNames[j]) // never pick main name
          {
            name1=secNames[j] // found first name
            secNames[j]="" // make this choice not  
                           // available on next pass
          }
       if (name2 <> secNames[j] and 
          name2 ="" and // skip this if found 2nd sec.name 
          nameList[i] <> secNames[j] and //never pick main 
          name1 <> secNames[j] // name is not used already 
          {                 
            name2=secNames[j])
            secNames[j]="" // remove choice for next pass
          }
    }
    if (name1="" or name2="")
    {
       //input does not allow for solution
       throw("Problem cannot be solved!!!") 
    }
    //assembly result
    resultList[i]=nameList[i]+name1+","+name2 

}

基本上,从名称列表中我们创建了第二个列表,其中所有名称都是重复的(但第二个副本的顺序相反)。 我们扫描该列表以进行第一和第二选择,每次我们选择一个名称时,我们都会从二级名称列表中删除它。 你的例子应该返回:

John - Rose,Dave
Rose - John,Jade
Dave - Jade,Rose
Jade - Dave,John

请注意,这不是“随机” - 当使用相同的输入调用时,它将始终返回相同的列表,但它也将始终尝试满足您的要求。