Skip to content
Advertisement

2 dimensional associative array sorting with conditional statements in PHP

I’m having trouble figuring out how to solve this question, it’s from a free online test website. Here’s the link: https://www.testdome.com/questions/php/league-table/19939?questionIds=7278,19939&generatorId=30&type=fromtest&testDifficulty=Hard

But to be clearer, I’m writing the question and my answer as well. The starting answer is there in the link written above.

Question:

The LeagueTable class tracks the score of each player in a league. After each game, the player records their score with the recordResult function.

The player’s rank in the league is calculated using the following logic:

The player with the highest score is ranked first (rank 1). The player with the lowest score is ranked last. If two players are tied on score, then the player who has played the fewest games is ranked higher. If two players are tied on score and number of games played, then the player who was first in the list of players is ranked higher. Implement the playerRank function that returns the player at the given rank.

For example:

$table = new LeagueTable(array('Mike', 'Chris', 'Arnold'));
$table->recordResult('Mike', 2);
$table->recordResult('Mike', 3);
$table->recordResult('Arnold', 5);
$table->recordResult('Chris', 5);
echo $table->playerRank(1);

All players have the same score. However, Arnold and Chris have played fewer games than Mike, and as Chris is before Arnold in the list of players, he is ranked first. Therefore, the code above should display “Chris”.

My code:

<?php

class LeagueTable
{
    public function __construct($players)
    {
        $this->standings = array();
        foreach($players as $index => $p)
        {
            $this->standings[$p] = array
            (
                'index' => $index,
                'games_played' => 0, 
                'score' => 0
            );
        }
    }

    public function recordResult($player, $score)
    {
        $this->standings[$player]['games_played']++;
        $this->standings[$player]['score'] += $score;
    }

    public function playerRank($rank)
    {
        // I'm not sure what to do in here, not even sure where to place the conditional statements
        // but here's me trying to figure it out which I'm 90% sure I'm doing it wrong, 
        // since I'm using too many foreach function and arrays. Most probably not even close
        // to the correct answer.

        $comparison = $result = $this->standings;
        $player_names = array();

        foreach($this->standings as $name => $records)
        {
            foreach($comparison as $name_compare => $records_compare)
            {     
                if($this->standings[$name]['score'] > $comparison[$name_compare]['score'])
                {
                    $result[$name]['index'] = $this->standings[$name]['index'];
                }
                else if($this->standings[$name]['score'] == $comparison[$name_compare]['score']
                      && $this->standings[$name]['games_played'] < $comparison[$name_compare]['games_played'])
                {
                    $result[$name]['index'] = $this->standings[$name]['index'];
                }
                else if($this->standings[$name]['score'] == $comparison[$name_compare]['score']
                        && $this->standings[$name]['games_played'] == $comparison[$name_compare]['games_played'])
                {
                    $result[$name]['index'] = $this->standings[$name]['index'];
                }

                // This is where I'm confused, although there are conditional statemens there
                // but the code inside each "if" and "else if" is the same.

            }
        }

        foreach($result as $name => $records)
        {
            array_push($player_names,$name);
        }

        return $player_names[$rank-1]; //This should return "Chris" based on the record result, but it's not
    }
}

$table = new LeagueTable(array('Mike', 'Chris', 'Arnold'));
$table->recordResult('Mike', 2);
$table->recordResult('Mike', 6);
$table->recordResult('Arnold', 5);
$table->recordResult('Chris', 5);
echo $table->playerRank(1);

Can anybody helps me solve this question please?

Advertisement

Answer

Using usort in your case

usort($this->standings, function($a, $b) {
  // Compare scores
  $r = $b['score'] - $a['score'];
  // If two players are tied on score, 
  // then the player who has played the fewest games is ranked higher
  if(! $r) {
    $r = $a['games_played'] - $b['games_played'];
  }
  // If two players are tied on score and number of games played, 
  // then the player who was first in the list of players is ranked higher
  if(! $r) {
    $r = $a['index'] - $b['index'];
  }
  return $r;        
});

// You can watch result of sorting
print_r($this->standings);
User contributions licensed under: CC BY-SA
7 People found this is helpful
Advertisement