我的任务很简单 - 我得到一个名单列表:
约翰
玫瑰
戴夫
翡翠
我需要按照这些规则为每个名字分配两个其他名称:
表示:
------ 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]);
}
知道如何解决这个问题吗?
答案 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
请注意,这不是“随机” - 当使用相同的输入调用时,它将始终返回相同的列表,但它也将始终尝试满足您的要求。