3v4l.org

run code in 300+ PHP versions simultaneously
<?php declare (strict_types=1); final class Position { private $row; private $column; public function __construct(int $row, int $column) { $this->row = $row; $this->column = $column; } public function is(Position $position) : bool { return $this->row === $position->row && $this->column === $position->column; } } final class Tile { private $position; private $clicked; public function __construct(Position $position) { $this->position = $position; $this->clicked = false; } public static function clicked(Position $position) : self { $tile = new self($position); $tile->clicked = true; return $tile; } public function position() : Position { return $this->position; } public function click() : self { if ($this->isClicked()) { throw new \RuntimeException('Tile can\'t be clicked twice'); } return self::clicked($this->position); } public function isClicked() : bool { return $this->clicked; } } final class Tiles { /** * @var Tile[] */ private $tiles; public function __construct(Tile ...$tiles) { $this->tiles = $tiles; } public function count() : int { return \count($this->tiles); } public function hasMoreThan(Position $position, int $expectedLimit) : bool { return $this->find( function(Tile $tile) use ($position) { return $tile->position()->is($position); } )->count() > $expectedLimit; } public function each(callable $callback) : void { array_map($callback, $this->tiles); } public function find(callable $callback) : Tiles { return new Tiles(...array_filter( $this->tiles, $callback )); } public function map(callable $callback) : array { return array_map($callback, $this->tiles); } public function has(Position $position) : bool { return (bool) $this->find( function(Tile $tile) use ($position) { return $tile->position()->is($position); } )->count(); } public function clickedCount() : int { return (int) array_reduce( $this->tiles, function(int $clicked, Tile $nextTile) { return $nextTile->isClicked() ? $clicked + 1 : $clicked; }, 0 ); } } final class Board { /** * @var Tiles */ private $tiles; public function __construct(Tiles $tiles) { $tiles->each(function(Tile $tile) use ($tiles) { if ($tiles->hasMoreThan($tile->position(), 1)) { throw new \RuntimeException('Board can have only tile at each position'); } }); $this->tiles = $tiles; } public function click(Position $position) : void { if (!$this->tiles->has($position)) { throw new \RuntimeException('Tile does not exists'); } $this->tiles = new Tiles(...$this->tiles->map(function(Tile $tile) use ($position) { return $tile->position()->is($position) ? $tile->click() : $tile; })); } public function score() : int { return $this->tiles->clickedCount(); } } $board = new Board(new Tiles( new Tile(new Position(0, 0)), new Tile(new Position(0, 1)) )); $board->click(new Position(0, 0)); $board->click(new Position(0, 1)); var_dump($board->score());
Output for 7.1.0 - 7.1.33, 7.2.0 - 7.2.33, 7.3.0 - 7.3.33, 7.4.0 - 7.4.32, 8.0.0 - 8.0.24, 8.1.0 - 8.1.11
int(2)
Output for 7.0.33
Fatal error: Uncaught TypeError: Return value of Tiles::each() must be an instance of void, none returned in /in/VOoEh:90 Stack trace: #0 /in/VOoEh(139): Tiles->each(Object(Closure)) #1 /in/VOoEh(165): Board->__construct(Object(Tiles)) #2 {main} thrown in /in/VOoEh on line 90
Process exited with code 255.
Output for 5.6.38 - 5.6.40
Warning: Unsupported declare 'strict_types' in /in/VOoEh on line 3 Parse error: syntax error, unexpected ':', expecting ';' or '{' in /in/VOoEh on line 16
Process exited with code 255.

preferences:
67.06 ms | 411 KiB | 5 Q