我有一个女巫看起来像这样:
---------------------------------------- | index | players | date | score | ---------------------------------------- | 1 | jan | 2013-01-13 | 5 | ---------------------------------------- | 2 | piet | 2013-01-13 | 6 | ---------------------------------------- | 3 | klaas | 2013-01-13 | 5 | ---------------------------------------- | 4 | kees | 2013-01-13 | 7 | ---------------------------------------- | 5 | william | 2013-01-13 | 8 | ---------------------------------------- | 6 | john | 2013-01-13 | 4 | ----------------------------------------
现在我想做一些棘手的事情,为了像2013-01-14的比赛一样打下一场比赛,我们想让2支球队成为平等的球队。
每个日期有12名球员,所以2013-01-13是12名球员,而在2013-01-14还有相同的球员。
他们必须离婚成2支球队,所以12/2 = 6人。现在这不是问题,问题是两支球队的总得分必须相等或相近。
如果12名球员的所有得分都是77,则两队的总得分必须几乎相等,如77/2 = 38,5
队伍1 - 队员6 - 总成绩37第2队 - 队员6 - 总分40
最后,查询输出必须如下:
----------------------------------------------- | index | players | date | score | team | ----------------------------------------------- | 1 | jan | 2013-01-13 | 5 | 1 | ----------------------------------------------- | 2 | piet | 2013-01-13 | 6 | 1 | ----------------------------------------------- | 3 | klaas | 2013-01-13 | 8 | 1 | ----------------------------------------------- | 4 | kees | 2013-01-13 | 7 | 1 | ----------------------------------------------- | 5 | william | 2013-01-13 | 5 | 1 | ----------------------------------------------- | 6 | john | 2013-01-13 | 6 | 1 | ----------------------------------------------- | 7 | gerrit | 2013-01-13 | 6 | 2 | ----------------------------------------------- | 8 | maartje | 2013-01-13 | 6 | 2 | ----------------------------------------------- | 9 | shara | 2013-01-13 | 8 | 2 | ----------------------------------------------- | 10 | els | 2013-01-13 | 7 | 2 | ----------------------------------------------- | 11 | allen | 2013-01-13 | 5 | 2 | ----------------------------------------------- | 12 | steven | 2013-01-13 | 8 | 2 | -----------------------------------------------
和
----------------------------------------------- | team | score | date | players | ----------------------------------------------- | Team 1 | 37 | 2013-01-13 | 6 | ----------------------------------------------- | Team 2 | 40 | 2013-01-13 | 6 | -----------------------------------------------
借助#Danack的灵感,我做到了这一点:
$difference = 10;
$team_smnstlln = array();
for($q=0; $q<1000; $q++){
$players = array();
$team_smnstlln[$q] = array(
'team1' => array(),
'team2' => array(),
'total' => 0
);
$count1 = 0;
for($w=0; $w<6; $w++){
$player = pick_random(true);
$score1 = $team_smnstlln[$q]['team1'][$player] = $data[$player]['score'];
$count1 = $count1 + $score1;
}
$count2 = 0;
for($w=6; $w<12; $w++){
$player = pick_random(true);
$score2 = $team_smnstlln[$q]['team2'][$player] = $data[$player]['score'];
$count2 = $count2 + $score2;
}
if($count1 > $count2){
$total = $count1 - $count2;
}
elseif($count2 > $count1){
$total = $count2 - $count1;
}
else{
$total = 0;
}
$team_smnstlln[$q]['total'] = $total;
if($team_smnstlln[$q]['total'] == 0){
$difference = 0;
$winner = $q;
break;
}
elseif($team_smnstlln[$q]['total'] < $difference){
$difference = $team_smnstlln[$q]['total'];
$winner = $q;
}
}
echo "Kleinst gekozen set met score verschil van $difference punten. array $winner is gekozen<br>";
$team1 = $team_smnstlln[$winner]['team1'];
$team2 = $team_smnstlln[$winner]['team2'];
print_r($team1);
print_r($team2);
// random player picker
function pick_random($gonogo){
global $players;
$go = true;
$total_players = 11;
while($go){
$player = rand(0, $total_players);
if(!in_array($player, $players)){
$players[] = $player;
$go = false;
}
}
return $player;
}
此代码运行1000个不同的团队设置。当得分差为0时,它将停止回应最佳平等的队伍比赛。否则,当没有0差异时,它将返回最低结果
答案 0 :(得分:4)
正如moonwave99所说,在PHP中执行此操作比尝试在SQL中执行此操作要好得多。
问题在于这是一个难以解决的问题。您可以通过重新询问您的问题来看到:
“1支队伍中的6名队员和其他队伍中的6名队员的组合将在分数上有最小的差异?”
从12个中挑选6个玩家的组合数量是(12!/ 6!)或665,280个组合,每个组合都需要计算得分。
您需要完成所有可能的组合,并计算每个组合的得分以找到“最佳”组合。
//An array to record whether each player has already been selected for a combination
$playersChosen = array();
//Initialise the array
for($x=0 ; $x<12 ; $x++){
$playersChosen[$x] = FALSE;
}
//Need to store lowest score somewhere - and have a flag for the first calculation
$lowestScore = FALSE;
chooseAnotherPlayer(6, 0);
//$GLOBALS['bestCombination'] - will now contain the best combination of players.
//Recursive function that either:
//goes through each player in turn and then calls itself or
//calculates the 'score' when all the players are chosen for one team
//$playersToChoose - how many players left to choose.
//$minimumPlayerNumber - index to start searching for players not yet chosen - as the choice, 3 + 5 is identical to 5 + 3
function chooseAnotherPlayer($playersToChoose, $minimumPlayerNumber){
//We have 6 pl
if($playersToChoose == 0){
//Calculate Score from which players are selected in $GLOBALS['playersChosen']
if($lowestScore === FALSE ||
$score < $lowestScore){
$GLOBALS['bestCombination'] = $GLOBALS['playersChosen']; //Arrays are copied by value, not reference
//So this saves a snapshot of the best selection.
}
return;
}
//Go through each of the players
for($x=$minimumPlayerNumber ; $x<12; $x++){
//Select them if they're available
$playerAvailable = selectPlayer($x);
if($playerAvailable == TRUE){
//Pick another player
chooseAnotherPlayer($playersToChose - 1, $x + 1);
//Release this player, so he's available for other combinations
unselectPlayer($x);
}
}
}
function selectPlayer($x){
if($GLOBALS['playersChosen'][$x] == TRUE){
//Player has already been selected in this combination.
return FALSE;
}
return TRUE;
}
如果您不介意花几秒钟处理该代码将完全解决您的问题。但是,如果您需要快速,那么您最好随机选择团队,评估“得分”并进行足够的迭代以获得合理的结果。
$playersChosen = array();
resetArray();
$playersToChose = 6;
$lowestScore = FALSE;
for($n=0 ; $n<10000 ; $n++){
chooseAnotherPlayers(6);
resetArray();
}
function chooseAnotherPlayer($playersToChoose){
if($playersToChoose == 0){
//Calculate Score from which players are selected in $GLOBALS['playersChosen']
if($lowestScore === FALSE ||
$score < $lowestScore){
$GLOBALS['bestCombination'] = $GLOBALS['playersChosen'];
return;
}
}
selectPlayerAtRandom($x);
chooseAnotherPlayer($playersToChose - 1);
}
function selectPlayer($x){
$playerSelected = FALSE;
while($playerSelected == FALSE){
$x = rand(0, 12 - 1);
if($GLOBALS['playersChosen'][$x] == FALSE){
$GLOBALS['playersChosen'][$x] = TRUE;
return $x;
}
}
}
function resetArray(){
for($x=0 ; $x<12 ; $x++){
$GLOBALS['playersChosen'][$x] = FALSE;
}
}
除非您需要让团队精确匹配,否则即使只覆盖了一小部分不同组合,这也可能会给您非常接近的结果,因为标准偏差和分布背后的数学。
您可以通过“经验法则”确定可接受的总分差异,并搜索直到您找到满足该条件的一个玩家组合或运行最长搜索时间,才能使该功能更加智能化(可能会生成一个警报,表示搜索超时,且比赛不均匀。)
答案 1 :(得分:1)
这在SQL中很容易做到,在数据库中执行它有一定的优势 - 值得注意的是,数据库可以利用并行性。以下是其中一个团队的6名团队成员。其余的应该很容易理解:
select t1.index, t2.index, t3.index, t4.index, t5.index, t6.index,
(t1.score+t2.score+t3.score+t4.score+t5.score+t6.score) as TeamScore
from t t1 join
t t2
on t1.index < t2.index join
t t3
on t2.index < t3.index join
t t4
on t3.index < t4.index join
t t5
on t4.index < t5.index join
t t6
on t5.index < t6.index cross join
(select cast(sum(score)/2 as integer) as score from t) as Half
where Half.Score - TeamScore in (0, 1)
order by (Half.score - TeamScore)
limit 1
答案 2 :(得分:0)
触发以下查询,它将在团队1中放置6条记录
update table1 t1 set t1.team="1" where id IN(
SELECT y.id
FROM (SELECT t.id,
t.scores,
(SELECT SUM(x.scores)
FROM table1 x
WHERE x.id <= t.id) AS running_total
FROM table1 t
ORDER BY t.id) y
WHERE y.running_total > (select * from (SELECT SUM(scores)/2 FROM table1) as sum)
ORDER BY y.id);
现在,下面的查询将在团队2中放入其他6条记录
update table1 t1 set t1.team="2" where id NOT IN(
SELECT y.id
FROM (SELECT t.id,
t.scores,
(SELECT SUM(x.scores)
FROM table1 x
WHERE x.id <= t.id) AS running_total
FROM table1 t
ORDER BY t.id) y
WHERE y.running_total > (select * from (SELECT SUM(scores)/2 FROM table1) as sum)
ORDER BY y.id);