Given n = 3 dogs and m = 3 pairs of enemies, a = [1, 2, 3] and b = [3, 3, 1], dog 1 is the enemy of dog 3, and dog 3 is the enemy of dogs 1 and 2. Because 3 is an enemy of both 1 and 2, it must be in its own container. dogs 1 and 2 can be together or separately. There are 4 possible groups: {1, 2} ,{1}, {2}, {3}. Note that the intervals are along the original line of dogs numbered consecutively from 1 to n, i.e. [1, 2, 3] in this case. The dogs cannot be reordered and dogs cannot be skipped, e.g. {2, 1} and {1, 3} are invalid.
So given the following:
case #1:
n = 5
m = 2
a = (1,2)
b = (3,5)
Result is: Total of 11 groups can be formed.
case #2
n = 8
m = 4
a = (2,3,4,3)
b = (8,5,6,4)
Result is: Total of 18 groups can be formed.
Here's my code:
function countSubstrings($n, $a, $b) {
$tokenArr = array();
$x = 1;
while ($x <= $n){
$tokenArr[] = $x;
$x++;
}
$first = 0;
$last = $n - 1;
$outArr = array();
$pointer = 0;
/* generate groups left to right */
for ($i = $first; $i <= $last; $i++) {
$outArr[$pointer][] = $tokenArr[$i];
$tokenString = $tokenArr[$i];
$pointer++;
for ($j = $i + 1; $j <= $last; $j++) {
$tokenString .= $tokenArr[$j];
$outArr[$pointer] = str_split($tokenString);
$pointer++;
}
}
/* find the enemeies */
$intersects = array();
for($k = 0; $k < count($outArr); $k++){
if (count(array_intersect($outArr[$k], $a)) > 1 || count(array_intersect($outArr[$k], $b)) > 1) {
$intersects[] = $outArr[$k];
}
}
/* remove first and last items which are basically equal to $a and $b */
$intersects = array_slice($intersects, 1, -1);
/* remove the enemeies from generated groups */
foreach ($outArr as $keya => $valuea) {
if (in_array($valuea, $intersects)) {
unset($outArr[$keya]);
}
}
return count($outArr);
}
So far my code works in case: #1 but fails on #2.
The intersect logic seems to be incorrect to me as we have to check if the relationship formed by [a , b], for example, [1,2] exists in $outArr or not. Current check of count(array_intersect($outArr[$k], $a)) > 1 does not care about that. It rather checks if any element in $outArr[$k] is present in $a or not.
So, change the current logic from:
/* find the enemeies */
$intersects = array();
for($k = 0; $k < count($outArr); $k++){
if (count(array_intersect($outArr[$k], $a)) > 1 || count(array_intersect($outArr[$k], $b)) > 1) {
$intersects[] = $outArr[$k];
}
}
/* remove first and last items which are basically equal to $a and $b */
$intersects = array_slice($intersects, 1, -1);
to
$intersects = array();
foreach($a as $index => $val1){
$val2 = $b[$index];
foreach($outArr as $current_group){
if(in_array($val1,$current_group) && in_array($val2,$current_group)){ // check if both exist as they are enemies
$intersects[] = $current_group;
}
}
}
Demo: https://3v4l.org/Q2rnP
In the above code, we:
loop through all elements of $a and simultaneously with $b with the help of $index in foreach.
Check if for the current group in $outArr, whether both $a[$index](a.k.a $val1) and $b[$index](a.k.a $val2) exist in the group or not.
If both exist in current group, we put them under intersect as they are enemies. Your rest of the logic is correct.
Efficient Solution:
We have to exploit this line:
A group is defined as an interval (x, y) such that all dogs in the range from x to y form a group.
This means that we need to look at subarrays(as you correctly judged) instead of subsequences.
Now, we loop from 1 to N and if we find a number which has an enemy on the left, we can only form the next groups from that number + 1 onwards. Anything before them can't be included anyway since we are looking at subarrays.
For example, let's assume 5 is an enemy of 3 in a line of 1 to 5 and no other enemies are present. So, group formations would look like below.
Representation:
1 2 3 4 5
-1 -1 5 -1 3
|___|
|___|___|
|___|___|___|
|___|
|___|___|
|___|
|___| // the connection/group (4,5) remains and breaks everything before 4 since 3 is an enemy of 5 and we are looking for subarrays. So everything before 4 is disconnected anyway.
So, our next starting animal/dog to look from is 4.
For each enemy/animal, we maintain the nearest enemy on the left if present. If present, we update the next animal to look from for groups as proved above. In the below code, $prev_start is the variable that maintains the next animal to look from.
In order to get nearest enemy on the left for each animal, we preprocess the enemy details as follows:
Preprocessing:
$enemies = array_combine(range(1,$n),array_fill(0,$n,-1)); // nothing tricky, just generates an array filled with sequential numbers as keys and sets it's value as -1
foreach($a as $index => $enemy_1){
$enemy_2 = $b[$index];
if($enemy_1 < $enemy_2){
$enemies[$enemy_2] = max($enemies[$enemy_2],$enemy_1);
}else if($enemy_2 < $enemy_1){
$enemies[$enemy_1] = max($enemies[$enemy_1],$enemy_2);
}
}
Computation:
$prev_start = 1;
$count = 0;
for($i=1;$i<=$n;++$i){
if($enemies[$i] !== -1){
$prev_start = max($enemies[$i] + 1,$prev_start);
}
$count += ($i - $prev_start + 1);
}
Since we preprocessed enemy details, we update $prev_start accordingly from where we have to start counting for groups again.
$count += ($i - $prev_start + 1); simply counts the number of groups(subarrays) to consider for counting.
Time complexity: O(m + n) where m is number of pairs and n is the number of dogs/animals.
Space complexity: O(n) where n is the number of dogs/animals.
Full Code:
<?php
function countSubarrays($n, $a, $b) {
$enemies = array_combine(range(1,$n),array_fill(0,$n,-1)); // nothing tricky, just generates an array filled with sequential numbers as keys and sets it's value as -1
foreach($a as $index => $enemy_1){
$enemy_2 = $b[$index];
if($enemy_1 < $enemy_2){
$enemies[$enemy_2] = max($enemies[$enemy_2],$enemy_1);
}else if($enemy_2 < $enemy_1){
$enemies[$enemy_1] = max($enemies[$enemy_1],$enemy_2);
}
}
$prev_start = 1;
$count = 0;
for($i=1;$i<=$n;++$i){
if($enemies[$i] !== -1){
$prev_start = max($enemies[$i] + 1,$prev_start);
}
$count += ($i - $prev_start + 1);
}
return $count;
}
Demo: https://3v4l.org/1W26C
I got this challenge to find the highest product of 4 consecutive numbers on a 20x20 matrix of integers.
The numbers are read line by line from a file separated by a space.
The products can be in horizontal, vertical and diagonal in both directions
My "solution" gives the wrong answer.
EDIT: I've updated the code to work without file input and added sample data; also fixed one of my mistakes that were pointed out in the comments
$data = [
[89,32,92,64,81,2,20,33,44,1,70,75,39,62,76,35,16,77,22,27],
[53,11,6,95,41,51,31,59,8,23,19,13,61,91,48,69,84,52,66,24],
[93,72,85,97,21,79,56,5,45,3,65,30,83,87,43,7,34,0,4,14],
[29,17,49,9,82,90,55,67,15,63,54,94,12,28,96,37,58,98,86,78],
[74,40,50,60,26,99,80,18,10,46,36,68,25,57,47,71,42,73,88,38],
[50,22,6,26,18,53,52,5,46,2,89,77,83,48,4,58,45,28,84,81],
[49,82,31,14,69,17,91,54,34,40,0,33,30,95,60,44,29,24,85,16],
[27,11,76,39,15,86,92,74,99,59,94,12,55,57,38,96,47,32,78,75],
[51,20,87,42,62,41,7,35,23,21,71,25,67,97,80,90,88,64,13,70],
[19,9,56,43,68,93,65,98,36,3,61,63,10,72,8,73,1,66,79,37],
[22,58,52,12,3,41,28,72,42,74,76,64,59,35,85,78,14,27,53,88],
[46,80,5,96,7,68,61,69,67,34,36,40,82,26,75,50,29,91,10,2],
[30,39,19,48,33,93,1,45,66,98,0,23,62,25,51,71,56,77,24,21],
[79,87,94,60,8,32,13,65,4,92,73,9,31,37,17,84,15,90,86,20],
[95,6,81,70,47,16,44,83,49,43,55,54,18,63,38,11,97,89,99,57],
[95,78,64,58,7,17,53,28,74,86,6,12,54,85,21,94,16,69,25,68],
[13,20,41,97,1,2,80,30,0,84,67,45,93,96,82,92,62,33,18,44],
[60,77,31,70,76,36,59,38,15,3,91,46,65,73,49,11,8,35,5,52],
[61,66,79,40,26,72,89,71,75,99,22,9,43,32,14,81,98,88,87,83],
[10,4,23,19,56,57,51,47,50,27,90,63,42,29,24,55,48,37,39,34]
];
$matrix = [];
//maximums in possible directions
$maxes = [0, 0, 0, 0];
//while ($line = trim(fgets(STDIN))) {
while ($line = current($data)) {
//the horizontal maxes can be calculated while loading
//$array = explode(" ", $line);
$array = $line;
$hMax = array_product(array_slice($array, 0, 4));
for ($i = 1; $i < (count($array)-4); $i++) {
$max = array_product(array_slice($array, $i, 4));
if($max > $hMax) {
$hMax = $max;
}
}
if ( $hMax > $maxes[0] ) {
$maxes[0] = $hMax;
}
$matrix[] = $array;
next($data);
}
// the last 3 rows can be skipped
for($i = 0; $i < (count($matrix)-4); $i++) {
for ($j = 0; $j < (count($matrix[$i])-1); $j++) {
$vMax = 1; // vertical
$dlMax = 1; // diagonal left
$drMax = 1; // diagonal rigth
for ($k = 0; $k < 5; $k++) {
$vMax *= $matrix[$i + $k][$j];
if ( $j < (count($matrix[$i]) - 4) ) {
$drMax *= $matrix[$i + $k][$j + $k];
}
if ( $j > 3 ) {
$dlMax *= $matrix[$i + $k][$j - $k];
}
}
if ( $maxes[1] < $vMax ) $maxes[1] = $vMax; // the index used to be 1 - my first mistake
if ( $maxes[2] < $dlMax ) $maxes[2] = $dlMax; // the index used to be 1 - my first mistake
if ( $maxes[3] < $drMax ) $maxes[3] = $drMax; // the index used to be 1 - my first mistake
}
}
sort($maxes);
echo end($maxes).PHP_EOL;
Where did my approach go wrong, and how can it be sped up?
Are there any math tricks that can be applied here (besides checking for zeros)?
EDIT: the solution that the code gives for the current data is 4912231320 is it correct?
I've found 2 major errors, and now the result is a plausible 67352832
I'm considering it solved for that reason, but if anyone comes up with some math trick that simplifies or makes it faster I'll give up the accepted answer.
The first mistake was
for ($k = 0; $k < 5; $k++) {
It should've been
for ($k = 0; $k < 4; $k++) {
since we are only counting 4 numbers at once, thats why the result was so large compared to 10^8
The second was
if ( $j > 3 ) {
which should've been
if ( $j > 2 ) {
which will now include one more diagonal possibility
We can consider the four directions a bottom- or right-most cell can be the last of in a sequence. If m[i][j][k][d] is the highest total for a sequence of length k coming from direction d, then:
m[i][j][1][d] = data[i][j] for all d
m[i][j][k]['E'] = data[i][j] * m[i][j - 1][k - 1]['E']
m[i][j][k]['NE'] = data[i][j] * m[i - 1][j - 1][k - 1]['NE']
m[i][j][k]['N'] = data[i][j] * m[i - 1][j][k - 1]['N']
m[i][j][k]['NW'] = data[i][j] * m[i - 1][j + 1][k - 1]['NW']
If we traverse north to south, east to west, the needed cells should have already been calculated, and, clearly, we're looking for
max(m[i][j][4][d])
for all i, j, d
I'm trying to build an algorithm for processing bracket sheet of competitions. I need to go through a range of numbers. For each number there will be the athlete name. Numbers are assigned to athletes randomly but the number's pairing must always stay the same. There are two groups odd and even, i.e. A and B.
The only problem that I can't find the proper algorithm to iterate numbers the exact way as follows:
Group A:
--------
1
17
9
25
------
5
21
13
29
------
3
19
11
27
------
7
23
15
31
Group B:
--------
2
18
10
26
------
6
22
14
30
------
4
20
12
28
------
8
24
16
32
Could someone please help with advice or example of how to get the output above?
EDIT 1:
The example above is the bracket sheet for 32 athletes! Same logic must be applied if you use a sheet for 4,8,16,64 or 128 athletes!
EDIT 2:
Let's make it more clear with examples of the sheet for 4 athletes and then the sheet for 16 athletes.
The sheet for 4 athletes:
Group A:
--------
1
3
Group B:
--------
2
4
The sheet for 16 athletes:
Group A:
--------
1
9
5
13
------
3
11
7
15
Group B:
--------
2
10
6
14
------
4
12
8
16
EDIT 3:
The last part, is that I'm planning to have an array with athlete name and its status in it.
By status I mean that, if the athlete has been a champion previously (strong), then he/she gets 1 for status, if the athlete's previous achievements are not known or minimal (weak), then the status is 0. It's done that way, so we could separate strongest athletes into different groups and make sure that they will not fight against each other in the first fight but rather meet each other closer to the semi-final or final.
Example of PHP array:
$participants = array(
array("John", 0),
array("Gagan", 0),
array("Mike Tyson", 1),
array("Gair", 0),
array("Gale", 0),
array("Roy Johnes", 1),
array("Galip", 0),
array("Gallagher", 0),
array("Garett", 0),
array("Nikolai Valuev", 1),
array("Garner", 0),
array("Gary", 0),
array("Gelar", 0),
array("Gershom", 0),
array("Gilby", 0),
array("Gilford", 0)
);
From this example we see that those, who have status 1 must be in different groups, i.e. A and B. But we have only two groups of numbers odd and even and in this example, there are 3 strong athletes. Thus two of them will be at the same group. The final result must be, that those two strong athletes, that got in the same group, must not meet at the very first fight (it means that they will not be on the same pair of numbers and as far away from each other as possible, so they wouldn't meet on the second fight as well).
Then randomly, I'm planning to rearrange the array and send athletes to the bracket sheet - every time, with different numbers, every time, those that have a flag 1 go to different groups and/or never meet at the first fight and every time, athletes' names assigned to the same pair of numbers.
Considering the number of participants is always a power of 2, this piece of code should give you the order you're expecting.
function getOrder($numberOfParticipants) {
$order = array(1, 2);
for($i = 2; $i < $numberOfParticipants; $i <<= 1) {
$nextOrder = array();
foreach($order as $number) {
$nextOrder[] = $number;
$nextOrder[] = $number + $i;
}
$order = $nextOrder;
}
return $order; // which is for instance [1, 17, 9, 25, and so on...] with 32 as argument
}
About the way it works, let's take a look at what happens when doubling the number of participants.
Participants | Order
2 | 1 2
4 | 1 3=1+2 2 4=2+2
8 | 1 5=1+4 3 7=3+4 2 6=2+4 4 8=4+4
... |
N | 1 X Y Z ...
2N | 1 1+N X X+N Y Y+N Z Z+N ...
The algorithm I used is the exact same logic. I start with an array containing only [1, 2] and $i is actually the size of this array. Then I'm computing the next line until I reach the one with the right number of participants.
On a side note: $i <<= 1 does the same than $i *= 2. You can read documentation about bitwise operators for further explanations.
About strong athletes, as you want to keep as much randomness as possible, here is a solution (probably not optimal but that's what I first thought):
Make two arrays, one with strongs and one with weaks
If there are no strongs or a single one, just shuffle the whole array and go to 8.
If there are more strongs than weaks (dunno if it can happen in your case but better be safe than sorry), shuffle the strongs and put the last ones with weaks so both arrays are the same size
Otherwise, fill up the strongs with null elements so the array size is a power of 2 then shuffle it
Shuffle the weaks
Prepare as many groups as they are elements in the strongs array and put in each group one of the strongs (or none if you have a null element) and complete with as many weaks as needed
Shuffle each group
Return the participants, ordered the same way than previous function resulting array
And the corresponding code:
function splitStrongsAndWeaks($participants) {
$strongs = array();
$weaks = array();
foreach($participants as $participant) {
if($participant != null && $participant[1] == 1)
$strongs[] = $participant;
else
$weaks[] = $participant;
}
return array($strongs, $weaks);
}
function insertNullValues($elements, $totalNeeded)
{
$strongsNumber = count($elements);
if($strongsNumber == $totalNeeded)
return $elements;
if($strongsNumber == 1)
{
if(mt_rand(0, 1))
array_unshift($elements, null);
else
$elements[] = null;
return $elements;
}
if($strongsNumber & 1)
$half = ($strongsNumber >> 1) + mt_rand(0, 1);
else
$half = $strongsNumber >> 1;
return array_merge(insertNullValues(array_splice($elements, 0, $half), $totalNeeded >> 1), insertNullValues($elements, $totalNeeded >> 1));
}
function shuffleParticipants($participants, $totalNeeded) {
list($strongs, $weaks) = splitStrongsAndWeaks($participants);
// If there are only weaks or a single strong, just shuffle them
if(count($strongs) < 2) {
shuffle($participants);
$participants = insertNullValues($participants, $totalNeeded);
}
else {
shuffle($strongs);
// If there are more strongs, we need to put some with the weaks
if(count($strongs) > $totalNeeded / 2) {
list($strongs, $strongsToWeaks) = array_chunk($strongs, $totalNeeded / 2);
$weaks = array_merge($weaks, $strongToWeaks);
$neededGroups = $totalNeeded / 2;
}
// Else we need to make sure the number of groups will be a power of 2
else {
$neededGroups = 1 << ceil(log(count($strongs), 2));
if(count($strongs) < $neededGroups)
$strongs = insertNullValues($strongs, $neededGroups);
}
shuffle($weaks);
// Computing needed non null values in each group
$neededByGroup = $totalNeeded / $neededGroups;
$neededNonNull = insertNullValues(array_fill(0, count($participants), 1), $totalNeeded);
$neededNonNull = array_chunk($neededNonNull, $neededByGroup);
$neededNonNull = array_map('array_sum', $neededNonNull);
// Creating groups, putting 0 or 1 strong in each
$participants = array();
foreach($strongs as $strong) {
$group = array();
if($strong != null)
$group[] = $strong;
$nonNull = array_shift($neededNonNull);
while(count($group) < $nonNull)
$group[] = array_shift($weaks);
while(count($group) < $neededByGroup)
$group[] = null;
// Shuffling again each group so you can get for instance 1 -> weak, 17 -> strong
shuffle($group);
$participants[] = $group;
}
// Flattening to get a 1-dimension array
$participants = call_user_func_array('array_merge', $participants);
}
// Returned array contains participants ordered the same way as getOrder()
// (eg. with 32 participants, first will have number 1, second number 17 and so on...)
return $participants;
}
If you want the resulting array to have as indexes the number in the bracket, you can simply do:
$order = getOrder(count($participants));
$participants = array_combine($order, shuffleParticipants($participants, count($order)));
Okay, I finally managed to convert my Tcl code to PHP! I changed some things too:
<?php
// Function generating order participants will be placed in array
function getBracket($L) {
// List will hold insert sequence
$list = array();
// Bracket will hold final order of participants
$bracket = array();
// The algorithm to generate the insert sequence
for ($n = 1; $n <= $L; $n += 1) {
// If 'perfect' number, just put it (Perfect no.s: 2, 4, 8, 16, 32, etc)
if (substr(log($n)/log(2), -2) == ".0") {
$list[] = $n;
// If odd number, stuff...
} elseif ($n % 2 == 1) {
$list[] = $list[($n-1)/2];
// Else even number, stuff...
} else {
$list[] = $list[$n/2-1]+$n/2;
}
}
// Insert participant order as per insert sequence
for ($i = 1; $i <= sizeof($list); $i += 1) {
$id = $i-1;
array_splice($bracket, $list[$id], 0, $i);
}
return $bracket;
}
// Find number of participants over 'perfect' number if any
function cleanList($L) {
for ($d = 1; $L > $d; $d += 1) {
$sq = $L-pow(2,$d);
if($sq == 0) {break;}
if($sq < 0) {
$d = pow(2,$d-1);
$diff = $L-$d;
break;
}
}
return $diff;
}
$participants = array(
array(0, "John", 2),
array(1, "Gagan", 1),
array(2, "Mike Tyson", 1),
array(3, "Gair", 1),
array(4, "Gale", 0),
array(5, "Roy Johnes", 0),
array(6, "Galip", 0),
array(7, "Gallagher", 0),
array(8, "Garett", 0),
array(9, "Nikolai Valuev", 0),
array(10, "Garner", 1),
array(11, "Gary", 0),
array(12, "Gelar", 0),
array(13, "Gershom", 1),
array(14, "Gilby", 0),
array(15, "Gilford", 1),
array(16, "Arianna", 0)
);
// Extract strength of participant
foreach ($participants as $array) {
$finorder[] = $array[2];
}
// Sort by strength, strongest first
array_multisort($finorder,SORT_DESC,$participants);
$order = array();
$outside = array();
// Remove participants above 'perfect' number
$remove = cleanList(sizeof($participants));
for ($r = 1; $r <= $remove; $r += 1) {
$removed = array_shift($participants);
$outside[] = $removed;
}
// Get corresponding bracket
$res = getBracket(sizeof($participants));
foreach ($res as $n) {
$order[] = $n;
}
// Align bracket results with participant list
array_multisort($order, $participants);
$participants = array_combine($res, $participants);
echo "The final arrangement of participants\n";
print_r($participants);
print_r($outside);
?>
Codepad demo
To get the logic for the order of insertion of elements, I used this pattern.
Also, since I'm not too familiar with PHP, there might be ways to make some things shorter, but oh well, as long as it works ^^
EDIT: Fixed an issue with first participant sorting and added new ticket numbers. For results without old ticket numbers, see here.
EDIT2: Managed to move keys into arrays; see here.
EDIT3: I thought that 'extra' participants should go outside the bracket. If you want null instead in the bracket, you can use this.
EDIT4: Somehow, PHP versions on codepad broke some stuff... fixing it below and removing initial index...:
<?php
// Function generating order participants will be placed in array
function getBracket($L) {
// List will hold insert sequence
$list = array();
// Bracket will hold final order of participants
$bracket = array();
// The algorithm to generate the insert sequence
for ($n = 1; $n <= $L; $n += 1) {
// If 'perfect' number, just put it (Perfect no.s: 2, 4, 8, 16, 32, etc)
if (int(log($n)/log(2)) || $n == 1) {
$list[] = $n;
// If odd number, stuff...
} elseif ($n % 2 == 1) {
$list[] = $list[($n-1)/2];
// Else even number, stuff...
} else {
$list[] = $list[$n/2-1]+$n/2;
}
}
// Insert participant order as per insert sequence
for ($i = 1; $i <= sizeof($list); $i += 1) {
$id = $list[$i-1]-1;
array_splice($bracket, $id, 0, $i);
}
return $bracket;
}
// Find number of participants over 'perfect' number if any
function cleanList($L) {
for ($d = 1; $L > $d; $d += 1) {
$diff = $L-pow(2,$d);
if($diff == 0) {break;}
if($diff < 0) {
$diff = pow(2,$d)-$L;
break;
}
}
return $diff;
}
$participants = array(
array("John", 2),
array("Gagan", 1),
array("Mike Tyson", 1),
array("Gair", 1),
array("Gale", 0),
array("Roy Johnes", 0),
array("Galip", 0),
array("Gallagher", 0),
array("Garett", 0),
array("Nikolai Valuev", 0),
array("Garner", 1),
);
// Extract strength of participant
foreach ($participants as $array) {
$finorder[] = $array[2];
}
// Sort by strength, strongest first
array_multisort($finorder,SORT_DESC,$participants);
$order = array();
// Add participants until 'perfect' number
$add = cleanList(sizeof($participants));
for ($r = 1; $r <= $add; $r += 1) {
$participants[] = null;
}
// Get corresponding bracket
$res = getBracket(sizeof($participants));
// Align bracket results with participant list
foreach ($res as $n) {
$order[] = $n;
}
array_multisort($order, $participants);
$participants = array_combine($res, $participants);
echo "The final arrangement of participants\n";
print_r($participants);
?>
ideone
viper-7
This sketchy code might be what you want:
<?php
class Pair
{
public $a;
public $b;
function __construct($a, $b) {
if(($a & 1) != ($b & 1))
throw new Exception('Invalid Pair');
$this->a = $a;
$this->b = $b;
}
}
class Competition
{
public $odd_group = array();
public $even_group = array();
function __construct($order) {
$n = 1 << $order;
$odd = array();
$even = array();
for($i = 0; $i < $n; $i += 4) {
$odd[] = $i + 1;
$odd[] = $i + 3;
$even[] = $i + 2;
$even[] = $i + 4;
}
shuffle($odd);
shuffle($even);
for($i = 0; $i < count($odd); $i += 2) {
$this->odd_group[] = new Pair($odd[$i], $odd[$i+1]);
$this->even_group[] = new Pair($even[$i], $even[$i+1]);
}
echo "Odd\n";
for($i = 0; $i < count($this->odd_group); ++$i) {
$pair = $this->odd_group[$i];
echo "{$pair->a} vs. {$pair->b}\n";
}
echo "Even\n";
for($i = 0; $i < count($this->even_group); ++$i) {
$pair = $this->even_group[$i];
echo "{$pair->a} vs. {$pair->b}\n";
}
}
}
new Competition(5);
?>