PHP数组随机化但不复制名册

时间:2017-02-26 05:53:24

标签: php arrays

我试图制作一个随机的名单。我遇到了麻烦。

我需要1 C 2 P SS CF 3 LF RF

创建9个随机顺序,它们不按顺序重复,一个值也不会两次相同的位置。就像一个网格,每个位置使用9次,最多9次。但我希望能够将它随机化。所以它并不总是一样的。我的意思是我想我可以随机化这些名字,但名字通常是按照特定的顺序排列,而这些位置不一定是,但不是骗子。

123456789    
234567891    
345678912    
456789123    
567891234    
678912345   
789123456    
891234567    
912345678 

我从这开始,但没有任何意义。起初,我确保不重复任何职位,但我意识到它并非如此,我有点卡住了。

shuffle($positions);
    $p1 = $positions;
    echo '<table style="width:100%;"><tr>';
    foreach($p1 as $pA){
        echo '<td>'.$pA.'</td>';
    }   
    echo '</tr>';   


    shuffle($positions);
    $p2 = $positions;
    if($p2 === $p1){    
        while($p2 === $p1){
            shuffle($positions);
            $p2 = $positions; 
            $a++; 
            echo '<br>=a=<br>'.$a.'<br>==<br>';
            //if($p2 == $p1){continue;}else{break;}
        }       
    }
    echo '<tr>';
    foreach($p2 as $pB){
        echo '<td>'.$pB.'</td>';
    }   
    echo '</tr>';




    shuffle($positions);
    $p3 = $positions;
    if($p3 === ($p1 || $p2)){   
        while($p3 === ($p1 || $p2)){
            shuffle($positions);
            $p3 = $positions; 
            $b++; 
            echo '<br>=b=<br>'.$b.'<br>==<br>';
            //if($p2 == ($p1 || $p2)){continue;}else{break;}
        }       
    }
    echo '<tr>';
    foreach($p3 as $pC){
        echo '<td>'.$pC.'</td>';
    }   
    echo '</tr>';



    shuffle($positions);
    $p4 = $positions;
    if($p4 === ($p1 || $p2 || $p3)){    
        while($p4 === ($p1 || $p2 || $p3)){
            shuffle($positions);
            $p4 = $positions; 
            $c++; 
            echo '<br>=c=<br>'.$c.'<br>==<br>';
            //if($p2 == ($p1 || $p2)){continue;}else{break;}
        }       
    }
    echo '<tr>';
    foreach($p4 as $pD){
        echo '<td>'.$pD.'</td>';
    }   
    echo '</tr>';



    shuffle($positions);
    $p5 = $positions;
    if($p5 === ($p1 || $p2 || $p3 || $p4)){ 
        while($p5 === ($p1 || $p2 || $p3 || $p4)){
            shuffle($positions);
            $p5 = $positions; 
            $d++; 
            echo '<br>=d=<br>'.$d.'<br>==<br>';
            //if($p2 == ($p1 || $p2)){continue;}else{break;}
        }       
    }
    echo '<tr>';
    foreach($p5 as $pE){
        echo '<td>'.$pE.'</td>';
    }   
    echo '</tr>';


    shuffle($positions);
    $p6 = $positions;
    if($p6 === ($p1 || $p2 || $p3 || $p4 || $p5)){  
        while($p6 === ($p1 || $p2 || $p3 || $p4 || $p5)){
            shuffle($positions);
            $p6 = $positions; 
            $e++; 
            echo '<br>=d=<br>'.$e.'<br>==<br>';
            //if($p2 == ($p1 || $p2)){continue;}else{break;}
        }       
    }
    echo '<tr>';
    foreach($p6 as $pF){
        echo '<td>'.$pF.'</td>';
    }   
    echo '</tr>';



    shuffle($positions);
    $p7 = $positions;
    if($p7 === ($p1 || $p2 || $p3 || $p4 || $p5 || $p6)){   
        while($p7 === ($p1 || $p2 || $p3 || $p4 || $p5 || $p6)){
            shuffle($positions);
            $p7 = $positions; 
            $f++; 
            echo '<br>=d=<br>'.$f.'<br>==<br>';
            //if($p2 == ($p1 || $p2)){continue;}else{break;}
        }       
    }
    echo '<tr>';
    foreach($p7 as $pG){
        echo '<td>'.$pG.'</td>';
    }   
    echo '</tr>';

    shuffle($positions);
    $p8 = $positions;
    if($p8 === ($p1 || $p2 || $p3 || $p4 || $p5 || $p6 || $p7)){    
        while($p8 === ($p1 || $p2 || $p3 || $p4 || $p5 || $p6 || $p7)){
            shuffle($positions);
            $p8 = $positions; 
            $g++; 
            echo '<br>=d=<br>'.$g.'<br>==<br>';
            //if($p2 == ($p1 || $p2)){continue;}else{break;}
        }       
    }
    echo '<tr>';
    foreach($p8 as $pH){
        echo '<td>'.$pH.'</td>';
    }   
    echo '</tr>';



    shuffle($positions);
    $p9 = $positions;
    if($p9 === ($p1 || $p2 || $p3 || $p4 || $p5 || $p6 || $p7 || $p8)){ 
        while($p9 === ($p1 || $p2 || $p3 || $p4 || $p5 || $p6 || $p7 || $p8)){
            shuffle($positions);
            $p9 = $positions; 
            $h++; 
            echo '<br>=d=<br>'.$h.'<br>==<br>';
            //if($p2 == ($p1 || $p2)){continue;}else{break;}
        }       
    }
    echo '<tr>';
    foreach($p9 as $pI){
        echo '<td>'.$pI.'</td>';
    }   
    echo '</tr>';



    shuffle($positions);
    $p10 = $positions;
    if($p10 === ($p1 || $p2 || $p3 || $p4 || $p5 || $p6 || $p7 || $p8 || $p9)){ 
        while($p10 === ($p1 || $p2 || $p3 || $p4 || $p5 || $p6 || $p7 || $p8 || $p9)){
            shuffle($positions);
            $p10 = $positions; 
            $i++; 
            echo '<br>=d=<br>'.$i.'<br>==<br>';
            //if($p2 == ($p1 || $p2)){continue;}else{break;}
        }       
    }
    echo '<tr>';
    foreach($p10 as $pJ){
        echo '<td>'.$pJ.'</td>';
    }   
    echo '</tr>';


    echo '</table>';


?>

1 个答案:

答案 0 :(得分:1)

詹姆斯,我知道当你拥有一堆allstars并且你想成为一个公平的教练时会很难,这样每个人都能得到同样的机会。随机化代码以拯救。这张桌子唯一没有考虑的是名单波动 - 如果你有一个生病/受伤的球员,你将不得不进行调整。

此代码将输出您要查找的网格。虽然它没有针对速度进行优化,但只需要约0.25秒即可完成 - 因此性能不会成为您的问题。 Performance Test

<?php
$players=array(
    "Mickey Mantle",
    "Babe Ruth",
    "Yogi Berra",
    "Lou Gehrig",
    "Joe DiMaggio",
    "Derek Jeter",
    "Whitey Ford",
    "Roger Maris",
    "Reggie Jackson"
);
$positions=array("P","C","1","2","SS","3","LF","CF","RF");
$batch=array();

echo "<table border=1>";
echo "<tr><th>#</th><th>",implode("</th><th>",$players),"</th></tr>";
    for($week=1; $week<11; ++$week){
        if($week==9){
            // see what's missing (use remaining value versus needless looping)
            foreach($players as $i=>$v){
                $batch[$week][$i]=current(array_diff($positions,array_column($batch,$i)));
            }
        }elseif($week==10){
            // purely random, as every player has played every position by now.
            shuffle($positions);
            $batch[$week]=$positions;           
        }else{    // weeks 1 - 8
            while(!isset($batch[$week])){
                shuffle($positions);
                $batch[$week]=$positions;
                //echo "<tr><td>",implode("</td><td>",$batch[$week]),"</td></tr>";
                if($week>1){     // check for no duplicate positions for any player
                    foreach($batch[$week] as $i=>$v){
                        //echo "<tr><td colspan=9>",implode(', ',array_column($batch,$i)),"</td></tr>";
                        if(sizeof(array_unique(array_column($batch,$i)))<$week){  // if vertical duplicates
                            unset($batch[$week]);   // trash the week, trigger rerun of loop
                            break;  // don't bother to assign positions for remaining players
                        }
                    }
                }
            }
        }
        echo "<tr><th>$week</th><td>",implode("</td><td>",$batch[$week]),"</td></tr>";
    }
echo "</table>";
?>

输出:

PositionSchedule

如果我的代码没有获得批准的绿色标记,请通过编辑澄清您的问题。如果您有疑问,我很乐意解释任何问题。事实是,我喜欢这个挑战;我每周都喜欢其中一个!

  

答案扩展 - 具有更高灵活性和效率的功能

说实话,我从来没有真正放弃过这方面的工作 - 我只是不太擅长让事情无法解决。您的发票在邮件中;)

这完全没有意义 - 不要去尝试卖掉它!我已经使用9个局/周期,9个位置和(9,13和18)球员测试了以下功能/代码,我无法打破它。

当我将时间段设置为4而名单和位置要高得多时,它确实会中断。这可能是一个逻辑问题,数学家可以详细解释 - 我不会去那个兔子洞。

我将留下所有评论和调试回声,以防将来有人需要了解/修改/改进它。

请在函数调用之前阅读fineprint。

function fairRotation($roster=[],$positions=[],$rotations=9,$off="X"){
    $roster_count=sizeof($roster);
    $positions_count=sizeof($positions);
    echo "<div>roster_count=$roster_count, positions_count=$positions_count</div>";
    $ons_avg=$positions_count/$roster_count;
    $ons_max=ceil($ons_avg);
    $ons_min=floor($ons_avg);
    echo "<div>ons_avg=$ons_avg, ons_max=$ons_max, ons_min=$ons_min</div>";
    $off_avg=($roster_count-$positions_count)*$rotations/$roster_count;
    $off_max=ceil($off_avg);
    $off_min=floor($off_avg);
    echo "<div>off_avg=$off_avg, off_max=$off_max, off_min=$off_min</div><br>";
    $positions=array_pad($positions,$roster_count,$off);  // sync positions with roster using sub identifier    
    $positions_count=sizeof($positions);    // overwrite with updated count
    for($r=0; $r<$rotations; ++$r){
        shuffle($positions);
        $result[$r]=$positions;
    }
    //$color_result=$result;
    // unfiltered result:
    /*echo "<table border=1>";
        echo "<tr><th>#</th><th>",implode("</th><th>",$roster),"</th></tr>";
        foreach($result as $key=>$row){
            echo "<tr><th>",($key+1),"</th><td>",implode("</td><td>",$row),"</td></tr>";
        }
    echo "</table>";    */

    // Assess result and address conflicts...
    $iterations=0;
    $fair="?";
    $must_drop_count=0;
    $must_gain_count=0;
    while($fair!="true" && $iterations<500){
        $must_gain=$must_drop=$may_gain=$may_drop=[];  // reset
        for($c=0; $c<$roster_count; ++$c){  // triage each column
            $col=array_column($result,$c);
            $val_counts[$c]=array_merge(array_fill_keys($positions,0),array_count_values($col));
            foreach($val_counts[$c] as $pos=>$cnt){
                if(($pos!=$off && $cnt<$ons_min) || ($pos==$off && $cnt<$off_min)){
                    $must_gain[$c][$pos]=array_keys($col,$pos);  // column/player must gain this position, but not where row = value(s)
                }elseif(($pos!=$off && $cnt>$ons_max) || ($pos==$off && $cnt>$off_max)){
                    $must_drop[$c][$pos]=array_keys($col,$pos);  // column/player must drop this position, but only where row = value(s)
                }elseif(($pos!=$off && $cnt<$ons_max) || ($pos==$off && $cnt<$off_max)){
                    $may_gain[$c][$pos]=array_keys($col,$pos);  // column/player may gain this position, but not where row = value(s)
                }elseif(($pos!=$off && $cnt>$ons_min) || ($pos==$off && $cnt>$off_min)){
                    $may_drop[$c][$pos]=array_keys($col,$pos);  // column/player may drop this position, but only where row = value(s)
                }
            }
        }

        if(sizeof($must_gain)==0 && sizeof($must_drop)==0){
            $fair="true";
        }elseif(sizeof($must_drop)==$must_drop_count && sizeof($must_gain)==$must_gain_count){
            //var_export($must_drop);
            //echo "<br>Program Deadlock @ $iterations Iterations.";
            //echo "<br>Desperately reshuffle one of the deadlocked rows.";
            shuffle($positions);
            if($must_drop_count>0){
                $result[current(current(current($must_drop)))]=$positions;
                //$color_result[current(current(current($must_drop)))]=$positions;
            }else{
                $result[current(current(current($must_gain)))]=$positions;
                //$color_result[current(current(current($must_gain)))]=$positions;
            }
        }else{
            $must_drop_count=sizeof($must_drop);
            $must_gain_count=sizeof($must_gain);
            //echo "<br><div>MustDrop:$must_drop_count , MustGain:$must_gain_count</div>"; 

            foreach($must_drop as $d1col=>$d1array){  // $must_drop1[0]["SS"]=array(3,8);
                ++$iterations;
                //echo "<div>({$iterations}x): {$roster[$d1col]} must drop ";
                    //var_export($d1array);
                    foreach($d1array as $d1pos=>$d1keys){
                        foreach(array_diff_key($must_drop,array($d1col=>"")) as $d2col=>$d2array){  // dual-solution swap
                            foreach($d2array as $d2pos=>$d2keys){
                                //echo "<div>..seeking a new home for $d1pos</div>";
                                if($d1pos!=$d2pos && (isset($must_gain[$d1col][$d2pos]) || isset($may_gain[$d1col][$d2pos]))){
                                    //echo "<div>{$roster[$d1col]} may drop $d1pos for {$roster[$d2col]}'s $d2pos</div>";
                                    foreach($d2keys as $row){
                                        //echo "<div>checking {$roster[$d2col]}'s row($row) holding $d2pos vs {$roster[$d1col]}'s $d1pos ";
                                        //var_export($d1keys);
                                        //echo "</div>";
                                        if(in_array($row,$d1keys)){
                                            //echo "<div>row match on $row between {$roster[$d1col]} & {$roster[$d2col]}</div>";
                                            if(isset($must_gain[$d1col][$d2pos])){
                                                //echo "<div>Success: {$roster[$d1col]} must gain holds $d2pos</div>";
                                                //$color_result[$row][$d1col]="<span style='background-color:green;'>$d2pos</span>";
                                                //$color_result[$row][$d2col]="<span style='background-color:blue;'>$d1pos</span>";
                                                $result[$row][$d1col]=$d2pos;
                                                $result[$row][$d2col]=$d1pos;
                                                //var_export($result[$row]);
                                                //echo "<br>";
                                                //unset($must_drop[$d1col][$d1pos],$must_gain[$d2col][$d2pos],$must_gain[$d1col][$d2pos],$must_gain[$d2col][$d1pos]);
                                                break(5);
                                            }elseif(isset($may_gain[$d1col][$d2pos])){
                                                //echo "<div>Success: {$roster[$d1col]} may gain holds $d2pos</div>";
                                                //$color_result[$row][$d1col]="<span style='background-color:red;'>$d2pos</span>";
                                                //$color_result[$row][$d2col]="<span style='background-color:orange;'>$d1pos</span>";
                                                $result[$row][$d1col]=$d2pos;
                                                $result[$row][$d2col]=$d1pos;
                                                //var_export($result[$row]);
                                                //echo "<br>";
                                                //unset($must_drop[$d1col][$d1pos],$must_gain[$d2col][$d2pos],$may_gain[$d1col][$d2pos],$may_gain[$d2col][$d1pos]);
                                                break(5);
                                            }else{
                                                //echo "<div>No Eligible Swap: {$roster[$d1col]} doesn't need/want $d2pos @ row$row";
                                                //var_export(array_merge(array(),$must_gain[$d1col],$may_gain[$d1col]));
                                                //echo "</div>";
                                            }
                                        }
                                        //echo "<br>";
                                    }
                                }
                            }
                        }                   
                    }
                //echo "</div><br>";
            }

        }
    }
    if($fair=="true"){
        echo "<div>FAIR! after $iterations adjustments</div>";
        return $result;  // $color_result for color
    }else{
        echo "Runaway Deadlock, Call Full Rerun<br>";
        return false;
    }
}

$roster=array(
    "Mickey Mantle","Babe Ruth","Yogi Berra","Lou Gehrig","Joe DiMaggio",
    "Derek Jeter","Whitey Ford","Roger Maris","Reggie Jackson","sub1","sub2","sub3","sub4","sub5","sub6","sub7","sub8","sub9");
$positions=array("P","C","1st","2nd","SS","3rd","LF","CF","RF");
$rotations=9; // rotating each inning of a 9 inning baseball game

// roster array must be larger than positions array
// if roster is short, remove positions which will be vacant
// values in the positions array MUST NOT be purely numeric, due to array_fill_keys() type-feature/glitch
// subs/inactive assignments will be marked by an X, unless otherwise declared in the function call

$result=false;
while(!$result){
    $result=fairRotation($roster,$positions,$rotations);
}

echo "<table border=1>";
    echo "<tr><th>#</th><th>",implode("</th><th>",$roster),"</th></tr>";
    foreach($result as $key=>$row){
        echo "<tr><th>",($key+1),"</th><td>",implode("</td><td>",$row),"</td></tr>";
    }
echo "</table>";

显示如下内容:

PosSched2