I was actually pleasantly surprised by the followups that I received to my “Programming Puzzle” query the other day.
It’s a simple problem, but it does take a little bit of thinking.
My original answer that I did was:
function calculateDraftRoundAndTeamNum($numTeams,$draftPosition,&$round,&$teamNumber) { $round = ceil(($draftPosition / $numTeams)); if($round % 2) { $teamNumber = ($draftPosition % $numTeams); if($teamNumber == 0) $teamNumber = $numTeams; } else { $relativePosition = ( $draftPosition % $numTeams); if($relativePosition == 0) $teamNumber = 1; else { $teamNumber = ($numTeams+1-$relativePosition); } }}
Basically, reverse the index into one’s array by determining which round you were in, handling the edge cases of a “0” remainder from using the MODulus operator to be the last team or the first team. Like most of my emails, my answer is a little verbose I think.
Which is why I really liked Charles Brabec’s Perl-based answer. By kicking up the number of teams internal within the logic, you obviate having to test for the edge cases. Nice.
He also did a Postscript answer. I told him he was just showing off :-). But it’s really interesting, and interesting to remember that Postscript is actually a programming language.
Charles also provided a test case with his code, which is important to help verify the results. One of the folks that submitted a PHP example would have benefited by running through their function through a test suite. It looked good until you got around the picks that rolled back around.
Professor Jeff Joines did the following in Matlab:
function [rnd, teamindex]=jeff(numteam,draftpos)rnd=ceil(draftpos/numteam);re = draftpos-(rnd-1)*numteam;if mod(rnd,2) == 0 teamindex = numteam+1-re;else teamindex = re;endend
Getting around the edge case check by not using a modulus to compute the relative position.
Doug Goodall did the following in Python
def draft(draftPosition, draftOrder): numberOfTeams = len(draftOrder) currentTeam = "" draftRound = ( (draftPosition - 1) / numberOfTeams) + 1 if draftRound % 2: pick = draftPosition - ( (draftRound - 1) * numberOfTeams) else: pick = numberOfTeams - (draftPosition - ( (draftRound - 1) * numberOfTeams) ) + 1 for team in draftOrder: if team[1] == pick: currentTeam = team[0] break return [str(draftRound), currentTeam]
Doug also calculated the pick position like Jeff did.
One interesting difference between Python and PHP shows up in the round calculation, PHP returns a float value with division and Python does an integer division.
Billy Beaudoin mixed his languages and provided a PHP example that would work only in Perl. It was unique because it raised -1 to the power of the round within an array reference, basically:
(Remainder - 1) * (-1)^Round)
The subscripts are off — but it takes advantage of a neat feature in Perl, negative array indexes index back from the end of the array.
Billy also found the gmp_div_qr() function — providing quotient and remainder in one fell swoop.
Troy Hurteau also did php:
$round = ceil($position / $totalTeams);$order = $position % $totalTeams;if($order == 0) $order = $totalTeams;//if the round is oddif($round % 2 != 0) $teamNumber = $position - (($round - 1) * $totalTeams);//if the round is evenelse $teamNumber = ($round * $totalTeams) + 1 - $position;
one thing Troy did (not shown) was provide lots of error checking for the number of teams against the provided team array, and checking for silly values like 0 teams (which the rest of us really forgot to do).
While I would have loved more responses, having so many different code examples was great.