Avatar of 4d47
0
0
Genius
0
0

4d47's solution

to Robot Name in the PHP Track

Instructions
Test suite
Solution

Manage robot factory settings.

When robots come off the factory floor, they have no name.

The first time you boot them up, a random name is generated in the format of two uppercase letters followed by three digits, such as RX837 or BC811.

Every once in a while we need to reset a robot to its factory settings, which means that their name gets wiped. The next time you ask, it will respond with a new random name.

The names must be random: they should not follow a predictable sequence. Random names means a risk of collisions. Your solution must ensure that every existing robot has a unique name.

Running the tests

  1. Go to the root of your PHP exercise directory, which is <EXERCISM_WORKSPACE>/php. To find the Exercism workspace run

     % exercism debug | grep Workspace
    
  2. Get PHPUnit if you don't have it already.

     % wget --no-check-certificate https://phar.phpunit.de/phpunit.phar
     % chmod +x phpunit.phar
    
  3. Execute the tests:

     % ./phpunit.phar robot-name/robot-name_test.php
    

Source

A debugging session with Paul Blackwell at gSchool. http://gschool.it

Submitting Incomplete Solutions

It's possible to submit an incomplete solution so you can see how others have completed the exercise.

robot-name_test.php

<?php

require_once "robot-name.php";

class RobotTest extends PHPUnit\Framework\TestCase
{
    /** @var Robot $robot */
    protected $robot = null;

    public function setUp()
    {
        $this->robot = new Robot();
    }

    public function testHasName()
    {
        $this->assertRegExp('/^[a-z]{2}\d{3}$/i', $this->robot->getName());
    }

    public function testNameSticks()
    {
        $this->markTestSkipped();
        $old = $this->robot->getName();

        $this->assertSame($this->robot->getName(), $old);
    }

    public function testDifferentRobotsHaveDifferentNames()
    {
        $this->markTestSkipped();
        $other_bot = new Robot();

        $this->assertNotSame($other_bot->getName(), $this->robot->getName());

        unset($other_bot);
    }

    public function testresetName()
    {
        $this->markTestSkipped();
        $name1 = $this->robot->getName();

        $this->robot->reset();

        $name2 = $this->robot->getName();

        $this->assertNotSame($name1, $name2);

        $this->assertRegExp('/\w{2}\d{3}/', $name2);
    }
  
    public function testNameArentRecycled()
    {
        $names = [];

        for ($i = 0; $i < 10000; $i++) {
            $name = $this->robot->getName();
            $this->assertArrayNotHasKey($name, $names, sprintf('Name %s reissued after Reset.', $name));
            $names[$name] = true;
            $this->robot->reset();
        }
    }

    // This test is optional.
    public function testNameUniquenessManyRobots()
    {
        $names = [];

        for ($i = 0; $i < 10000; $i++) {
            $name = (new Robot())->getName();
            $this->assertArrayNotHasKey($name, $names, sprintf('Name %s reissued after %d robots', $name, $i));
            $names[$name] = true;
        }
    }
}
<?php

class Robot
{
    protected $name;
    protected static $names = [];

    public function __construct()
    {
        $this->reset();
    }

    public function getName()
    {
        return $this->name;
    }

    public function reset()
    {
        unset(static::$names[$this->name]);
        do {
            $this->name = $this->pickName();
        } while (isset(static::$names[$this->name]));
        static::$names[$this->name] = true;
    }

    protected function pickName()
    {
        return static::pickLetter() . static::pickLetter()
             . static::pickNumber() . static::pickNumber() . static::pickNumber();
    }

    protected static function pickLetter()
    {
        return chr(rand(ord('A'), ord('Z')));
    }

    protected static function pickNumber()
    {
        return (string) rand(0, 9);
    }
}

What can you learn from this solution?

A huge amount can be learnt from reading other people’s code. This is why we wanted to give exercism users the option of making their solutions public.

Here are some questions to help you reflect on this solution and learn the most from it.

  • What compromises have been made?
  • Are there new concepts here that I could read more about to develop my understanding?