цикл по многомерному массиву и порядку подмассива по баллам

Я пытаюсь рассчитать выигрышный порядок игроков в гольф, когда они связаны в соревновании.

В этих соревнованиях по гольфу используется система начисления очков «стабильным», в которой вы набираете очки за лунку с наибольшим выигрышем. По сравнению с обычной «игрой в удар» в гольфе, где выигрывает наименьший счет (хотя здесь также есть система обратного отсчета, вычисляющая только самый низкий счет в случае ничьей …)

Правила должны использовать «обратный отсчет». то есть, если результаты привязаны после 9 лунок, наилучшее расположение связей — лучший результат из последних 8 лунок. потом 7 лунок и т. д.

Лучшее, что я могу придумать, это 2 массива.

  1. Массив со всеми игроками, которые участвовали в данном раунде. ($ связи)
  2. Тот, который имеет полные данные счета (со ссылкой на playerid базы данных) для всех 9 лунок. ($ 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 (данные оценки) выглядит следующим образом:

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-е, так что это работает.

Надеюсь, этого достаточно, чтобы помочь.

1

Решение

Хорошо, я вообще не понимаю гольф … хахаха, НО! Я думаю, что я понял суть этой проблемы, так что вот мое решение.

<?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
)

)
1

Другие решения

Других решений пока нет …