Swiss Tournament. Team confrontation multiple rounds without repeat and ordered - php
I try to make a tournament based on Swiss method.
I have for example 12 teams, and in each round, every team has points (0 to 100) and wins, loses or draws.
I want to find which teams play against each other, with these conditions:
Ordered by wins, draws, and points.
Not to be played previously.
In each round, I got foreach team the possible teams to play against in an array like this: (The key indicates the team id, and the values indicate ll possible teams to play separated by ",")
[2] => 4,11,6,10,3,8,7,12,
[5] => 4,11,9,10,3,8,1,12,
[4] => 2,5,6,10,8,7,12,
[11] => 5,9,10,3,8,7,
[9] => 5,11,6,3,8,7,12,
[6] => 2,4,9,10,3,7,12,
[10] => 2,5,4,11,6,8,7,12,
[3] => 5,11,9,6,8,7,
[8] => 2,5,4,11,9,10,3,1,12,
[7] => 2,4,11,9,6,10,3,1,12,
[1] => 5,4,11,9,6,3,8,7,
[12] => 2,5,4,9,6,10,8,7,
First I have all teams played before in a array: (key indicates team id)
Array (
[1] => 2,10,12,
[2] => 1,9,5,
[3] => 4,12,10,
[4] => 3,11,9,
[5] => 6,7,2,
[6] => 5,8,11,
[7] => 8,5,8,
[8] => 7,6,7,
[9] => 10,2,4,
[10] => 9,1,3,
[11] => 12,4,6,
[12] => 11,3,1, )
Then, I get all teams ordered by wins, loses and points in a array: (Keys indicates also team id)
Array
(
[1] => 2
[2] => 5
[3] => 4
[4] => 11
[5] => 9
[6] => 6
[7] => 10
[8] => 3
[9] => 8
[10] => 7
[11] => 1
[12] => 12
)
Finaly I try to find the possible match against two teams.
$checks = array();
$pairs = array();
for ($i = 1; $i <= count($list); $i++) {
for ($j = 1; $j <= count($list); $j++) {
if(strpos($plays[$list[$i]], $list[$j]) !== false || $list[$i] == $list[$j] ) {
}else{
if(!in_array($list[$i],$checks) && !in_array($list[$j],$checks)){
$pairs[] = $list[$i].",".$list[$j];
$checks[] = $list[$i];
$checks[] = $list[$j];
}
}
}
}
And finaly I print the array "$pairs". It shows:
Array
(
[0] => 2,4
[1] => 5,11
[2] => 9,6
[3] => 10,8
[4] => 3,7
)
Thats not correct because the team_id 1 and team_id 12 can not play in this round because the played before:
I don't know how to solve this.
Thanks again!
Related
PHP Working with an array to find ranges and missing numbers
I have an array that looks like this: [0] => Array ( [1] => 5 [2] => 4 [3] => 3 [5] => 1 [7] => 1 [8] => 2 [9] => 3 [10] => 4 [11] => 5 ) [1] => Array ( [1] => 6 [2] => 5 [4] => 3 [5] => 2 [6] => 1 [8] => 3 [9] => 4 [10] => 5 [11] => 6 ) [2] => Array ( [1] => 7 [2] => 6 [3] => 5 [4] => 4 [5] => 3 [6] => 2 [7] => 3 [8] => 4 [11] => 7 ) I have an order of operations I'm trying to go through and I really don't know where to go from here. Any suggestions would be of great help. First I give my class the number of items I want to return. For example here we'll use 4. I want to loop through and find the item in the array that has the lowest value. I want to look at the keys to the items around (it included) and be sure they're not missing a number if they are..reject it.. In this example the first one you would come to would be: [5] => 1 Now looking around it you see that the keys are missing some numbers. So no combination of 4 will get that to match any 4 in the proper order. [1] => 5 [2] => 4 [3] => 3 [5] => 1 //this one [7] => 1 [8] => 2 [9] => 3 In this situation I want it to move onto the next case. [7] => 1 Notice this one will work due to the keys being 7,8,9,10. [7] => 1 [8] => 2 [9] => 3 [10] => 4 This is what I would like returned first..but I don't even know how to begin to get there. Further more there are situations like this..Say for example there are no 1's at all in the dataset..and only this lone 2 in the last one. [0] => Array ( [1] => 5 [2] => 4 [3] => 3 [5] => 3 [7] => 3 [8] => 3 [9] => 3 [10] => 4 [11] => 5 ) [1] => Array ( [1] => 6 [2] => 5 [4] => 3 [5] => 3 [6] => 3 [8] => 3 [9] => 4 [10] => 5 [11] => 6 ) [2] => Array ( [1] => 7 [2] => 6 [5] => 3 [6] => 2 // this one [7] => 3 [8] => 4 [11] => 7 ) The following wont work: [6] => 2 // this one [7] => 3 [8] => 4 [11] => 7 but this one will: [5] => 3 [6] => 2 // this one [7] => 3 [8] => 4 I have no idea on how to approach this.. If someone could offer some advice it would be GREATLY appreciated. Thanks so much in advance.
The following assumes your data is in an array called $data. I'll describe it in steps, then pull it all together as a function. Step 1 find the min value: $minValue=min($data); Step 2 loop through the array looking for all values that are that value: foreach($data as $index => $value){ if($value == $minValue){ // $index is a candidate! } } Step 3 Check if $valuesToReturn entries exist after index: $success=true; for($i=1;$i<=$valuesToReturn;$i++){ if(!array_key_exists($index + $i,$data)){ // Candidate failed. $success=false; break; } } Step 4 If the candidate was successful, return it. if($success){ return $index; } Putting that all together, we get this: function findSuitableIndex($data,$valuesToReturn){ // Min: $minValue=min($data); foreach($data as $index => $value){ if($value == $minValue){ // $index is a candidate! // test if index is actually suitable: $success=true; for($i=1;$i<=$valuesToReturn;$i++){ if(!array_key_exists($index + $i,$data)){ // Candidate failed. $success=false; break; } } if($success){ return $index; } } } // If we fell down here, we failed to find any successful results. return -1; } Working sample: Code on eval.in
Here are some suggestions. Your exact implementation would depend on your particular situation. To loop through each element in the array, you could use a foreach loop. foreach ($arr[0] as $index => $value) { // Here, $arr[0][$index] == $value; } To check if a key exists or not, you could use array_key_exists. if ( !array_key_exists($index - 1, $arr[0]) ) { // The previous index is missing in the array. } A simple (but inefficient) way to find a contiguous sequence of k indices with the smallest value at the first index would be to find the smallest element and check if the contiguous sequence exists; if not, find the next smallest element and recursively check until you have completed processing the largest element. You could also try finding all contiguous sequences of at least length k and then selecting the sequence with the smallest value at the first index. Hope this helps!
Re-order PHP array by middle key as start (Circular Sorting)
very basic question however I have had some trouble finding the answers on PHP.NET. I have the following array: Array ( [1] => Array ( [1] => 4 [2] => 1 [3] => 5 [4] => 3 ) [2] => Array ( [5] => 2 [6] => 8 [7] => 7 [8] => 6 ) [3] => Array ( [9] => 10 [10] => 9 [11] => 12 [12] => 11 ) [4] => Array ( [13] => 15 [14] => 16 [15] => 14 [16] => 13 ) ) I want the array to be re-ordered so that the key number 3 in the first series of the array becomes the first, then the rest to be re-ordered from there to eventually get the result of: Array ( [3] => Array ( [9] => 10 [10] => 9 [11] => 12 [12] => 11 ) [4] => Array ( [13] => 15 [14] => 16 [15] => 14 [16] => 13 ) [1] => Array ( [1] => 4 [2] => 1 [3] => 5 [4] => 3 ) [2] => Array ( [5] => 2 [6] => 8 [7] => 7 [8] => 6 ) ) I am looking for a way to do this so I can define the array, then the first level key I need to sort by, and then it will return the array in this way. The standard PHP keys didn't seem to offer something like this, so it would be good to be able to have a separate function such as $newArray = reorder_array($array, $key); I don't require any sorting of the second level, only the initial 4 main / first level array sections. You help is greatly appreciated as I have been sitting on this one for awhile without a clear and simple solution.
You re-ordering can be simply implemented with one foreach loop, like: function reorderArray($array, $key) { $found = false; foreach($array as $k=>$v) { $found = $found || $k===$key; if(!$found) { unset($array[$k]); $array[$k] = $v; } //else break can be added for performance issues } return $array; } with usage $array=[1=>'foo', 4=>'bar', 9=>'baz', 'test'=>51]; var_dump(reorderArray($array, 9)); var_dump(reorderArray($array, 'test')); var_dump(reorderArray($array, 'no_such_key'));//original array in result -check this demo. If keys are consecutive numerics, however, this can be easily implemented with array_slice() calls.
Creating a multidimensional array tree from MySQL table in PHP
I'm trying to organize my mysql table into a multidimension php tree array. For example, I'm trying to organize my products in a hierarchy for easy selection to narrow down the result the narrower they go in the result. I am returned mysql rows like this: Array ( [1] => Amazon [2] => Kindle Fire [3] => [4] => [5] => [6] => [7] => [8] => [9] => 1 ) Array ( [1] => Amazon [2] => Kindle Fire HD [3] => WiFi [4] => 7" [5] => [6] => 16GB [7] => [8] => [9] => 2 ) Array ( [1] => Amazon [2] => Kindle Fire HD [3] => WiFi [4] => 7" [5] => [6] => 32GB [7] => [8] => [9] => 3 ) Array ( [1] => Amazon [2] => Kindle Fire HD [3] => WiFi [4] => 8.9" [5] => [6] => 16GB [7] => [8] => [9] => 4 ) Array ( [1] => Amazon [2] => Kindle Fire HD [3] => WiFi [4] => 8.9" [5] => [6] => 32GB [7] => [8] => [9] => 5 ) Array ( [1] => Amazon [2] => Kindle Fire HD [3] => 4G LTE [4] => 8.9" [5] => [6] => 32GB [7] => [8] => [9] => 6 ) Array ( [1] => Amazon [2] => Kindle Fire HD [3] => 4G LTE [4] => 8.9" [5] => [6] => 64GB [7] => [8] => [9] => 7 ) Array ( [1] => Amazon [2] => Kindle Fire HDX [3] => Wifi [4] => 7" [5] => [6] => 16GB [7] => [8] => [9] => 8 ) Array ( [1] => Amazon [2] => Kindle Fire HDX [3] => Wifi [4] => 7" [5] => [6] => 32GB [7] => [8] => [9] => 9 ) Array ( [1] => Amazon [2] => Kindle Fire HDX [3] => Wifi [4] => 7" [5] => [6] => 64GB [7] => [8] => [9] => 10 ) ...etc Note the last array value is the Product ID. And I'm looking for help writing a recursive function that will result in an array that looks like: Array( 'Amazon' => Array( 'Kindle Fire' => 1, 'Kindle Fire HD' => Array( 'WiFi' => Array( '7"' => Array( '16GB' => 2, '32GB' => 3 ) '8.9"' => Array( '16GB' => 4, '32GB' => 5 ) ) ) ) ) I've tried something like: while($row = mysqli_fetch_row($res)) { $id = $row[0]; unset($row[0]); unset($row[count($row)]); $row[] = $id; // Moves id to last array value for($i = 1; $i < count($row); $i++) { if($i == 1) { if(!array_key_exists($row[$i], $data)) { // Insert key $data[$row[$i]] = array(); } } else { $level = $data[$row[$i-1]]; if(array_key_exists($row[$i], $level)) { // Key exists } else { // Insert key } } } }
I think your code has a good intention: using $level to hold the current depth. But at the moment this won't work, because you are copying via $level = $data[$row[$i-1]]; - instead you need to refer to it, e.g. with $level =& $data[$row[$i-1]];. $result = array(); while ($row = mysqli_fetch_row($res)) [ $id = array_shift($row); if (!isset($maxIterator)) $maxIterator = count($row)-1; $current =& $result; for ($i=0; $i<$maxIterator; $i++) { if (empty($row[$i])) break; if (!array_key_exists($row[$i], $current)) $current[ $row[$i] ] = array(); $current =& $current[ $row[$i] ]; } //for properly ended and wasn't broken out of sooner if ($i == $maxIterator) { if (!array_key_exists($row[$i], $current)) $current[ $row[$i] ] = 1; else $current[ $row[$i] ]++; } } array_shift basically does, what you needed two lines for: get the first element of an array and then remove it. Then I save the result of the count in a variable, so it doesn't need to be recalculated in every iteration of the for AND while. Also I would suggest setting $maxIterator manually. With the shown result a good default would be 5. This way all values before the 5th. will be used for nesting and the 5th itself will be used to count (in your example this is storage size). As the for will execute $i++ after the last iteration (and then it fails the condition and hence the loop breaks), it can be used for the counting. Personally I would overthink what exactly you are doing and maybe use a specifc structure for that. However, this code should give you a good impression how it can be solved using references.
PHP: Avg Grade by category
I'm fairly new to PHP and trying to sort a class project. I've banged away and can't see to sort it out, this is the last remaining piece. I have a form - submit essentially 2 arrays I'm trying to determine the average score for based upon the category groupings. 1. ($_post['category']), ($_post['score']) - with category being a text based array and score obviously being numbers based. How would I go about finding the average score for each category? I've tried various options to for mapping the two arrays and then trying to average the grades. I can get the total score average pretty easily, but finding a ways to do this by each category individually is tripping me up. I need to apply a weight to each category score, but that seems pretty easy once you get the above sorted. Thanks, Steve $_POST example: Array ( [0] => Assignment [1] => Assignment [2] => Assignment [3] => Assignment [4] => Assignment [5] => Assignment [6] => Exam [7] => Assignment [8] => Assignment [9] => Assignment [10] => Exam [11] => Exam [12] => Final Project ) Array ( [0] => 100 [1] => 100 [2] => 100 [3] => 98 [4] => 90 [5] => 92 [6] => 100 [7] => 100 [8] => 100 [9] => 100 [10] => 100 [11] => 92 [12] => 100 )
There are several ways to go about this, here's one: // create arrays $cat = array( "Assignment", "Assignment", "Assignment", "Assignment", "Assignment", "Assignment", "Exam", "Assignment", "Assignment", "Assignment", "Exam", "Exam", "Final Project"); $grade = array(100,100,100,98,90,92,100,100,100,100,100,92,100); // create $result: key = cat, values = sum, count, avg = 0 $result = array_fill_keys($cat, array('sum' => 0, 'count' => 0, 'avg' => 0)); $max = count($cat); // add grades to category in $result[cat][sum] for ($i = 0; $i < $max; $i++) $result[$cat[$i]]['sum'] += $grade[$i]; // count number of categories in $cat $num = array_count_values($cat); // fill $result[cat][count]... // then divide each cat's sum by each cat's count => $result[cat][avg] foreach ($result as $k => $v) { $result[$k]['count'] = $num[$k]; $result[$k]['avg'] = round($result[$k]['sum'] / $num[$k], 2); } Result: Array ( [Assignment] => Array ( [sum] => 880 [count] => 9 [avg] => 97.78 ) [Exam] => Array ( [sum] => 292 [count] => 3 [avg] => 97.33 ) [Final Project] => Array ( [sum] => 100 [count] => 1 [avg] => 100 ) ) see it working: http://codepad.viper-7.com/QQAaXD
Php, printing a 3d array into a table
Basically i need to sort some data into the top 5 best sales. I've managed to group the 3 arrays i've used using. $c = array_combine($PriceArray,$namesArray,$ProductArray); krsort($c); Price array being the total. (Bit of a silly name, i just realised) namesarray is the array of names and product array is the list of product codes I need to print it in a table like "|£3.45|Jelly Beans | 120|" so they have their own column, but at the moment it's printing it like | 3.45| array | array| and i use echo '<td>'.$ProductArray[$i].'</td>'.'<td>'.$year.'</td>'.'<td>'.array_keys($c,$c[$i]).'<td>'. $PriceArray[$i].'</td>'; to print it. Thanks in advance Array ( [0] => 77358.47 [1] => 111004.98 [2] => 227194.9 [3] => 84645.75 [4] => 29693.58 [5] => 198867.2 [6] => 110779.5 [7] => 210530.62 [8] => 102916.79 [9] => 186630.75 [10] => 140143.24 [11] => 48984.48 [12] => 74759.34 [13] => 204793.14 [14] => 82192.5 [15] => 167402.7 [16] => 58232.72 [17] => 216302.32 [18] => 26353.92 [19] => 149993.1 ) Array ( [0] => Jelly beans [1] => Banana milkshake powder [2] => Edam Cheese [3] => Hairnet [4] => Aubergine jam [5] => White bread [6] => Brown bread [7] => Purple bread [8] => Plain flour [9] => Striped flour [10] => Soft tissues [11] => Anti personnel mines [12] => Chicken fillets [13] => Beef cubes [14] => Marshmallows [15] => Fizzy carrot juice [16] => Low fat lard [17] => Suet dumpling mix [18] => Gravy powder [19] => Cherry pie filling ) Array ( [0] => 121 [1] => 122 [2] => 123 [3] => 124 [4] => 125 [5] => 126 [6] => 127 [7] => 128 [8] => 129 [9] => 130 [10] => 131 [11] => 132 [12] => 133 [13] => 134 [14] => 135 [15] => 136 [16] => 137 [17] => 138 [18] => 139 [19] => 140 ) Product Code Year Name Sales Total
Zip function blatantly stolen from: zip function from SO function zip() { $args = func_get_args(); $zipped = array(); $n = count($args); for ($i=0; $i<$n; ++$i) { reset($args[$i]); } while ($n) { $tmp = array(); for ($i=0; $i<$n; ++$i) { if (key($args[$i]) === null) { break 2; } $tmp[] = current($args[$i]); next($args[$i]); } $zipped[] = $tmp; } return $zipped; } function cmp($a, $b) { if($a[0] == $b[0]){ return 0; } return ($a[0] < $b[0]) ? -1 : 1; } $PriceArray = array( 4.56, 1.23, 7.89 ); $namesArray = array( 'ab', 'cd', 'ef' ); $ProductArray = array( '11', '22', '33' ); $c = zip($PriceArray, $namesArray, $ProductArray); usort($c, 'cmp'); foreach($c as $prices) { //$prices[0] == price //$prices[1] == name //$prices[2] == code echo "{$prices[0]}|{$prices[1]}|{$prices[2]}\n"; prints: 1.23|cd|22 4.56|ab|11 7.89|ef|33 I am using the zip-function that is available natively in Python to combine N-arrays and "zip" them together. So take index 0 of all given arrays, and make that a new array entry. Do that for all indices available. The cmp function takes two variables, in this case two arrays, where index-0 = price, 1 = name and 2 = code. You obviously want to sort by ascending by price thus we are comparing the price index. This results in a new/sorted array based on price. You can also substitude the usort($c, 'cmp'); call with the following: usort($c, function($a, $b){ if($a[0] == $b[0]){ return 0; } return ($a[0] < $b[0]) ? -1 : 1; }); However, this is only available in PHP version >= 5.3
Just put the keys and values into new arrays. $NewNamesArray = array_values($c); $NewPriceArray = array_keys($c)