我正在尝试计算高尔夫球手在比赛中平局时的获胜顺序。
这些高尔夫比赛使用"stableford"计分系统,你每洞得分,得分最高的获胜。与一般的高尔夫"杆数比赛"相比,最低杆数获胜(尽管这也有计数系统,只计算平局时的最低杆数…)
规则是使用"countback"。也就是说,如果在9洞之后比分持平,那么最好的位置就是最后8洞的最好成绩。然后7个孔,等等
我能想到的最好的是2个数组。
- 一个数组,其中包含在给定回合中并列的所有玩家。(关系)
- 拥有所有9洞的完整得分数据(参考数据库playerid)的一个。(tie_perhole美元)
我循环遍历数组1,从数组2中提取数据,并使用以下公式创建得分最高的临时数组:
$max = array_keys($array,max($array));
如果$max只有1件物品,这个玩家是最高的得分者。通过第一个数组的循环是"通过引用",所以在循环的下一次迭代中,他的playerid现在在数组中更长,因此被忽略。直到第一个数组中只剩下1个playerid为止。
然而,它只有在每次迭代中都有一个玩家获胜时才有效。如果一组玩家在任何迭代/回滚上绑定,那么这种情况就行不通了。
我认为我的问题是我目前的结构需要原来的$ties数组被分割,然后继续以同样的方式迭代分割数组…
作为一个例子…
$ties数组如下:
Array
(
[18] => Array
(
[0] => 77
[1] => 79
[2] => 76
[3] => 78
)
)
$tie_perhole (score data)数组如下:
Array
(
[18] => Array
(
[77] => Array
(
[9] => 18
[8] => 16
[7] => 14
[6] => 12
[5] => 10
[4] => 8
[3] => 6
[2] => 4
[1] => 2
)
[79] => Array
(
[9] => 18
[8] => 17
[7] => 15
[6] => 14
[5] => 11
[4] => 9
[3] => 7
[2] => 5
[1] => 3
)
[76] => Array
(
[9] => 18
[8] => 16
[7] => 14
[6] => 12
[5] => 10
[4] => 8
[3] => 6
[2] => 4
[1] => 2
)
[78] => Array
(
[9] => 18
[8] => 17
[7] => 15
[6] => 13
[5] => 11
[4] => 9
[3] => 7
[2] => 5
[1] => 3
)
)
)
所以在这场比赛中,78号和79号球员在第8洞的倒数赛中得分最高(17分),所以第一名和第二名应该在他们之间。79号球员在第6洞的倒数中应该是第一名(14分,对13分)。对于第三名和第四名,剩下的两名选手也应如此。
这里还可能发生其他情况,在比赛中,可能会有许多组玩家(数量不同)在排行榜上获得不同的积分。
还要注意的是,排行榜上会有一些玩家没有并列,而是保持在他们目前的位置。
我所拥有的基本工作代码是:
foreach ($ties as $comparekey => &$compareval) {
$tie_loop = 0;
for ($m = 9; $m >= 1; $m--) {
$compare = array();
foreach ($compareval as $tie) {
$compare[$tie] = $tie_perhole[$comparekey][$tie][$m];
}
$row = array_keys($compare,max($compare));
if (count($row) == 1) {
$indexties = array_search($row[0], $ties[$comparekey]);
unset($ties[$comparekey][$indexties]);
// Now update this "winners" finishing position in a sorted array
// This is a multidimensional array too, with custom function...
$indexresults = searchForId($row[0], $comp_results_arr);
$comp_results_arr[$indexresults][position] = $tie_loop;
$tie_loop++;
}
// I think I need conditions here to filter if a subset of players tie
// Other than count($row) == 1
// And possibly splitting out into multiple $ties arrays for each thread...
if (empty($ties[$comparekey])) {
break;
}
}
}
usort($comp_results_arr, 'compare_posn_asc');
foreach($comp_results_arr as $row) {
//echo an HTML table...
}
提前感谢任何有用的见解,提示,想法等…
Robert Cathay要求更多的场景。这是另一个…
排行榜实际上有更多的参赛者(玩家26有一个糟糕的回合…),但我需要帮助的代码只关心排行榜内的关系。
总结排行榜:
Points Player
21 48
21 75
20 73
20 1
13 26
这个例子生成了一个$tie_perhole数组:
Array
(
[21] => Array
(
[75] => Array
(
[9] => 21
[8] => 19
[7] => 16
[6] => 14
[5] => 12
[4] => 9
[3] => 7
[2] => 5
[1] => 3
)
[48] => Array
(
[9] => 21
[8] => 19
[7] => 16
[6] => 13
[5] => 11
[4] => 9
[3] => 8
[2] => 5
[1] => 3
)
)
[20] => Array
(
[73] => Array
(
[9] => 20
[8] => 18
[7] => 16
[6] => 13
[5] => 11
[4] => 8
[3] => 6
[2] => 5
[1] => 3
)
[1] => Array
(
[9] => 20
[8] => 17
[7] => 16
[6] => 14
[5] => 12
[4] => 9
[3] => 7
[2] => 4
[1] => 2
)
)
)
在这个例子中,数组显示球员75和48得到21分,球员75最终将在第6洞的倒数中获胜(14分对13分),球员48是第二名。在第二组比赛中,73号和1号选手各得20分,73号选手将在第8洞的倒数击球中获胜,获得第3名(18分),1号选手获得第4名。球员26是第5名。
注意,$tie_loop被添加到另一个数组中来计算第一到第五名的结束位置,所以它是工作的。
好吧,我根本不懂高尔夫…哈哈哈但是!我想我了解了这个问题的要点,所以这是我的解决方案。
<?php
/**
* Author : Carlos Alaniz
* Email : Carlos.glvn1993@gmail.com
* Porpuse : Stackoverflow example
* Date : Aug/04/2015
**/
$golfers = [
"A" => [1,5,9,1,1,2,3,4,9],
"B" => [2,6,4,2,4,4,1,9,3],
"C" => [3,4,9,8,1,1,5,1,3],
"D" => [1,5,1,1,1,5,4,5,8]
];
//Iterate over scores.
function get_winners(&$golfers, $hole = 9){
$positions = array(); // The score numer is the key!
foreach ($golfers as $golfer=>$score ) { // Get key and value
$score_sub = array_slice($score,0,$hole); // Get the scores subset, first iteration is always all holes
$total_score = (string)array_sum($score_sub); // Get the key
if(!isset($positions[$total_score])){
$positions[$total_score] = array(); // Make array
}
$positions[$total_score][] = $golfer; // Add Golpher to score.
}
ksort($positions, SORT_NUMERIC); // Sort based on key, low -> high
return array(end($positions), key($positions)); // The last shall be first
}
//Recursion is Awsome
function getWinner(&$golfers, $hole = 9){
if ($hole == 0) return;
$winner = get_winners($golfers,$hole); // Get all ties, if any.
if(count($winner[0]) > 1){ // If theirs ties, filter again!
$sub_golfers =
array_intersect_key($golfers,
array_flip($winner[0])); // Only the Worthy Shall Pass.
$winner = getWinner($sub_golfers,$hole - 1); // And again...
}
return $winner; // We got a winner, unless they really tie...
}
echo "<pre>";
print_R(getWinner($golfers));
echo "</pre>";
好吧…现在我来解释一下我的方法……因为我们需要知道最高分,而且它可能是平手,所以在单独的数组中维护所有这些对我来说是没有意义的,所以我只是颠倒了
高尔夫球手=>分数来Tota_score =>高尔夫球手
这样我们就可以按键对数组进行排序,并获得所有得分最高的高尔夫球手。
现在total_score是洞分数数组的一个子集的总和。所以…当这个函数第一次运行时,它将添加所有9个洞,在本例中有3个高尔夫球手最终获得相同的分数。
Array
(
[0] => Array
(
[0] => A
[1] => B
[2] => C
)
[1] => 35
)
由于高尔夫球手总数不是1,我们仍然在第9洞,我们再次运行这个,但这次只针对这3个高尔夫球手和当前洞- 1,所以我们这次只加到第8洞。
Array
(
[0] => Array
(
[0] => B
[1] => C
)
[1] => 32
)
我们有另一个平局....这个过程将一直持续,直到我们到达最后一个洞,或者获胜者。
Array
(
[0] => Array
(
[0] => C
)
[1] => 31
)
编辑
<?php
/**
* Author : Carlos Alaniz
* Email : Carlos.glvn1993@gmail.com
* Porpuse : Stackoverflow example
**/
$golfers = [
"77" => [2,4,6,8,10,12,14,16,18],
"79" => [3,5,7,9,11,14,15,17,18],
"76" => [2,4,6,8,10,12,14,16,18],
"78" => [3,5,7,9,11,13,15,17,18]
];
//Iterate over scores.
function get_winners(&$golfers, $hole = 9){
$positions = array(); // The score numer is the key!
foreach ($golfers as $golfer => $score) { // Get key and value
//$score_sub = array_slice($score,0,$hole); // Get the scores subset, first iteration is always all holes
$total_score = (string)$score[$hole-1]; // Get the key
if(!isset($positions[$total_score])){
$positions[$total_score] = array(); // Make array
}
$positions[$total_score][] = $golfer; // Add Golpher to score.
}
ksort($positions, SORT_NUMERIC); // Sort based on key, low -> high
return [
"winner"=> end($positions),
"score" => key($positions),
"tiebreaker_hole" => [
"hole"=>$hole,
"score"=> key($positions)],
]; // The last shall be first
}
//Recursion is Awsome
function getWinner(&$golfers, $hole = 9){
if ($hole == 0) return;
$highest = get_winners($golfers,$hole); // Get all ties, if any.
$winner = $highest;
if(count($winner["winner"]) > 1){ // If theirs ties, filter again!
$sub_golfers =
array_intersect_key($golfers,
array_flip($winner["winner"])); // Only the Worthy Shall Pass.
$winner = getWinner($sub_golfers,$hole - 1); // And again...
}
$winner["score"] = $highest["score"];
return $winner; // We got a winner, unless they really tie...
}
echo "<pre>";
print_R(getWinner($golfers));
echo "</pre>";
结果:Array
(
[winner] => Array
(
[0] => 79
)
[score] => 18
[tiebreaker_hole] => Array
(
[hole] => 6
[score] => 14
)
)