Created
January 31, 2013 19:56
-
-
Save parap/4685877 to your computer and use it in GitHub Desktop.
Test task for Olexander Bondarenko
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
/** | |
* @task Write a php class Network. | |
* The constructor should take a positive integer value indicating the number of elements in the set. | |
* Passing in an invalid value should throw InvalidArgumentException. | |
* | |
* The class should also provide two public methods, connect and query. | |
* | |
* The first method, connect will take two integers indicating the elements to connect. | |
* This method should throw InvalidArgumentException or OutOfBoundsException as appropriate. | |
* | |
* The second method, query will also take two integers and should also throw InvalidArgumentException | |
* or OutOfBoundsException as appropriate. | |
* It should return true if the elements are connected, directly or indirectly, and false if the elements are not connected. | |
* | |
* The class can have as many private or protected members as needed for a good implementation. | |
* Also note that the exceptions mentioned are SPL exceptions and you should not define them. | |
*/ | |
interface NetworkInterface | |
{ | |
public function __construct($total); | |
public function connect($firstElement, $secondElement); | |
public function query($firstElement, $secondElement); | |
} | |
abstract class NetworkAbstract implements NetworkInterface | |
{ | |
protected $groups = array(); | |
protected $total; | |
abstract public function __construct($total); | |
abstract public function connect($firstElement, $secondElement); | |
abstract public function query($firstElement, $secondElement); | |
} | |
abstract class ConnectedElementsGroupAbstract | |
{ | |
protected $elements; | |
abstract public function __construct(Pair $pair); | |
/** | |
* @param Pair $pair | |
* @returns void | |
*/ | |
abstract public function add(Pair $pair); | |
/** | |
* @param Pair $pair | |
* @returns boolean | |
*/ | |
abstract public function contains(Pair $pair); | |
} | |
class ConnectedElementsGroup extends ConnectedElementsGroupAbstract | |
{ | |
public function __construct(Pair $pair) | |
{ | |
$this->elements[] = $pair->getElements()[0]; | |
$this->elements[] = $pair->getElements()[1]; | |
} | |
public function add(Pair $pair) | |
{ | |
foreach ($this->elements as $element) { | |
if ($pair->has($element)) { | |
$this->elements[] = $pair->other($element); | |
break; | |
} | |
} | |
} | |
public function hasElement($input) | |
{ | |
foreach ($this->elements as $element) { | |
if ($input == $element) { | |
return true; | |
} | |
} | |
return false; | |
} | |
public function contains(Pair $pair) | |
{ | |
foreach ($this->elements as $element) { | |
if ($pair->has($element)) { | |
return true; | |
} | |
} | |
return false; | |
} | |
} | |
class Pair | |
{ | |
private $firstElement; | |
private $secondElement; | |
public function __construct($firstElement, $secondElement) | |
{ | |
$this->firstElement = $firstElement; | |
$this->secondElement = $secondElement; | |
} | |
public function has($element) | |
{ | |
return $this->firstElement == $element || $this->secondElement == $element; | |
} | |
public function other($element) | |
{ | |
if ($this->firstElement == $element) { | |
return $this->secondElement; | |
} | |
if ($this->secondElement == $element) { | |
return $this->firstElement; | |
} | |
throw new InvalidArgumentException("Wrong $element passed. Bug in Pair->other()"); | |
} | |
public function getElements() | |
{ | |
return array($this->firstElement, $this->secondElement); | |
} | |
} | |
class Verifier | |
{ | |
public static function verify($max, $firstElement, $secondElement) | |
{ | |
$firstElement = (int)$firstElement; | |
$secondElement = (int)$secondElement; | |
if ($firstElement !== (int)$firstElement) { | |
throw new InvalidArgumentException("$firstElement parameter must be integer"); | |
} | |
if ($secondElement !== (int)$secondElement) { | |
throw new InvalidArgumentException("$secondElement parameter must be integer"); | |
} | |
if (0 >= $firstElement) { | |
throw new InvalidArgumentException("$firstElement parameter must be positive"); | |
} | |
if ($max < $firstElement) { | |
throw new InvalidArgumentException("$firstElement parameter must be below or equal $max"); | |
} | |
if (0 >= $secondElement) { | |
throw new InvalidArgumentException("$secondElement parameter must be positive"); | |
} | |
if ($max < $secondElement) { | |
throw new InvalidArgumentException("$secondElement parameter must be below or equal $max"); | |
} | |
} | |
public static function checkPositive($max) | |
{ | |
if (0 >= (int)$max) { | |
throw new InvalidArgumentException('Total must be positive'); | |
} | |
} | |
} | |
class Network extends NetworkAbstract | |
{ | |
public function __construct($total) | |
{ | |
Verifier::checkPositive($total); | |
$this->total = (int)$total; | |
} | |
/** | |
* @param Pair $pair | |
* | |
* @brief Check all groups, if they contain any element from the pair. If yes, add whole pair to this group | |
* @brief Otherwise, create new group with this pair | |
* | |
* @return void | |
*/ | |
public function connect($firstElement, $secondElement) | |
{ | |
Verifier::verify($this->total, $firstElement, $secondElement); | |
$pair = new Pair($firstElement, $secondElement); | |
foreach ($this->groups as $group) { | |
if ($group->contains($pair)) { | |
$group->add($pair); | |
return; | |
} | |
} | |
$this->groups[] = new ConnectedElementsGroup($pair); | |
} | |
/** | |
* @param $firstElement | |
* @param $secondElement | |
* | |
* @brief check all groups, if they contain first element of the pair | |
* @brief check all groups, if they contain second element of the pair | |
* @brief if both 1. and 2. are true, return true. Otherwise return false | |
* | |
* @return bool | |
*/ | |
public function query($firstElement, $secondElement) | |
{ | |
Verifier::verify($this->total, $firstElement, $secondElement); | |
$pair = new Pair($firstElement, $secondElement); | |
$elements = $pair->getElements(); | |
$results = array(false, false); | |
if (empty($this->groups)) { | |
return false; | |
} | |
foreach ($this->groups as $group) { | |
if ($group->hasElement($elements[0])) { | |
$results[0] = true; | |
} | |
if ($group->hasElement($elements[1])) { | |
$results[1] = true; | |
} | |
} | |
return $results[0] && $results[1]; | |
} | |
} | |
// DEBUG | |
$x = new Network(10); | |
$x->connect(1, 4); | |
$x->connect(4, 7); | |
$x->connect(1, 4); | |
var_dump($x->query(1, 7)); | |
//var_dump($x->query(-50, 7)); | |
var_dump($x->query(1, 10)); | |
$x->connect(10, 7); | |
var_dump($x->query(1, 10)); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment