Я пытаюсь рассчитать выигрышный порядок игроков в гольф, когда они связаны в соревновании.
В этих соревнованиях по гольфу используется система начисления очков «стабильным», в которой вы набираете очки за лунку с наибольшим выигрышем. По сравнению с обычной «игрой в удар» в гольфе, где выигрывает наименьший счет (хотя здесь также есть система обратного отсчета, вычисляющая только самый низкий счет в случае ничьей …)
Правила должны использовать «обратный отсчет». то есть, если результаты привязаны после 9 лунок, наилучшее расположение связей — лучший результат из последних 8 лунок. потом 7 лунок и т. д.
Лучшее, что я могу придумать, это 2 массива.
Я перебираю массив 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 (данные оценки) выглядит следующим образом:
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 очков), поэтому 1-е и 2-е места должны быть между ними. Игрок 79 должен затем быть 1-м в обратном отсчете 6-й лунки (14 очков, по сравнению с 13 очками). То же самое должно произойти для 3-го и 4-го места с 2 оставшимися другими игроками.
Здесь могут быть и другие сценарии, в которых в рамках соревнования, вероятно, будет много групп игроков (разного количества) с разными связанными точками в таблице лидеров.
Также обратите внимание, что в таблице лидеров будут некоторые игроки, которые НЕ связаны и остаются в своей текущей прямой позиции.
Основы рабочего кода у меня есть:
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...
}
Заранее спасибо за любые полезные идеи, советы, мысли и т.д …
Роберт Катей попросил больше сценариев. Так вот еще один …
В таблице лидеров на самом деле больше участников (у игрока 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 — 2-й. В следующей связанной группе игроки 73 и 1 набрали 20 очков, а игрок 73 выиграет эту группу при обратном отсчете 8-й лунки и финиширует 3-м (18 очков против 17 очков), а игрок 1 — четвертым. игрок 26 — 5-й.
Обратите внимание, что $ tie_loop добавляется в другой массив для расчета конечных позиций с 1-го по 5-е, так что это работает.
Надеюсь, этого достаточно, чтобы помочь.
Хорошо, я вообще не понимаю гольф … хахаха, НО! Я думаю, что я понял суть этой проблемы, так что вот мое решение.
<?php
/**
* Author : Carlos Alaniz
* Email : [email protected]
* 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 : [email protected]
* 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
)
)
Других решений пока нет …