-
-
Save Nessworthy/c793508b3b7383da34bdc70d534d3a3d to your computer and use it in GitHub Desktop.
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 | |
namespace Program; | |
class StringChunker | |
{ | |
private $original; | |
public function __construct(string $data) | |
{ | |
$this->original = $data; | |
} | |
public function iterate() : \Generator | |
{ | |
$split = "\n"; | |
$token = strtok($this->original, $split); | |
while ($token) { | |
$token = trim($token); | |
yield $token; | |
$token = strtok($split); | |
} | |
} | |
} | |
class Coordinates | |
{ | |
private $x; | |
private $y; | |
public function __construct(int $x, int $y) | |
{ | |
$this->x = $x; | |
$this->y = $y; | |
} | |
public function x() : int | |
{ | |
return $this->x; | |
} | |
public function y() : int | |
{ | |
return $this->y; | |
} | |
public function toString() : string | |
{ | |
return $this->x . ',' . $this->y; | |
} | |
} | |
interface Canvas | |
{ | |
const FILL = '#'; | |
const EMPTY = ' '; | |
public function set(Coordinates $coords, $state = Canvas::FILL); | |
public function get(Coordinates $coords); | |
public function move(Coordinates $from, Coordinates $to); | |
public function fill(Coordinates $from, Coordinates $to, $state = Canvas::FILL); | |
public function cycleRow(int $y); | |
public function cycleCol(int $x); | |
public function render(); | |
public function on(): int; | |
} | |
class AsciiCanvas implements Canvas | |
{ | |
private $grid = []; | |
private $width = 0; | |
private $height = 0; | |
public function __construct(int $width, int $height) | |
{ | |
$this->width = $width; | |
$this->height = $height; | |
$this->setupGrid(); | |
} | |
private function setupGrid() | |
{ | |
for ($iterator = 0; $iterator <= $this->width - 1; $iterator += 1) { | |
$this->grid[$iterator] = array_fill(0, $this->height, Canvas::EMPTY); | |
} | |
} | |
public function set(Coordinates $coords, $state = Canvas::FILL) | |
{ | |
$x = $coords->x(); | |
$y = $coords->y(); | |
if (!array_key_exists($x, $this->grid)) { | |
throw new \OutOfBoundsException('X Coordinate ' . $coords->x() . ' is out of range.'); | |
} | |
if (!array_key_exists($y, $this->grid[$x])) { | |
throw new \OutOfBoundsException('Y Coordinate ' . $coords->y() . ' is out of range.'); | |
} | |
$this->grid[$x][$y] = $state; | |
} | |
public function get(Coordinates $coords) | |
{ | |
return $this->grid[$coords->x()][$coords->y()]; | |
} | |
public function move(Coordinates $from, Coordinates $to) | |
{ | |
$fromState = $this->get($from); | |
$this->set($from, Canvas::EMPTY); | |
$this->set($to, $fromState); | |
} | |
public function fill(Coordinates $from, Coordinates $to, $state = Canvas::FILL) | |
{ | |
$fromX = $from->x(); | |
$fromY = $from->y(); | |
$toX = $to->x(); | |
$toY = $to->y(); | |
for ($x = $fromX; $x <= $this->width - 1 && $x <= $toX; $x += 1) { | |
for ($y = $fromY; $y <= $this->height - 1 && $y <= $toY; $y += 1) { | |
$this->set(new Coordinates($x, $y), $state); | |
} | |
} | |
} | |
public function cycleCol(int $x) | |
{ | |
$last = $this->get(new Coordinates($x, $this->height - 1)); | |
for ($y = $this->height - 2; $y >= 0; $y -= 1) { | |
$this->move(new Coordinates($x, $y), new Coordinates($x, $y + 1)); | |
} | |
$this->set(new Coordinates($x, 0), $last); | |
} | |
public function cycleRow(int $y) | |
{ | |
$last = $this->get(new Coordinates($this->width - 1, $y)); | |
for ($x = $this->width - 2; $x >= 0; $x -= 1) { | |
$this->move(new Coordinates($x, $y), new Coordinates($x + 1, $y)); | |
} | |
$this->set(new Coordinates(0, $y), $last); | |
} | |
public function render() | |
{ | |
$output = ''; | |
for ($col = 0; $col <= $this->height - 1; $col += 1) { | |
for ($row = 0; $row <= $this->width - 1; $row += 1) { | |
$output .= $this->grid[$row][$col]; | |
} | |
$output .= "\n"; | |
} | |
return $output; | |
} | |
public function on(): int | |
{ | |
$total = 0; | |
for ($col = 0; $col <= $this->height - 1; $col += 1) { | |
for ($row = 0; $row <= $this->width - 1; $row += 1) { | |
if ($this->grid[$row][$col] === Canvas::FILL) { | |
$total += 1; | |
} | |
} | |
} | |
return $total; | |
} | |
} | |
interface CanvasInstruction | |
{ | |
public function execute(Canvas $canvas); | |
} | |
class InstructionFactory | |
{ | |
public function create(string $string): CanvasInstruction | |
{ | |
$args = explode(' ', $string); | |
$command = array_shift($args); | |
switch ($command) { | |
case 'rect': | |
$dimensions = explode('x', array_shift($args)); | |
return new RectCanvasInstruction((int) $dimensions[0], (int) $dimensions[1]); | |
case 'rotate': | |
$orientation = array_shift($args); | |
$position = (int) substr(array_shift($args), 2); | |
array_shift($args); | |
$amount = (int) array_shift($args); | |
return new RotateCanvasInstruction($orientation, $position, $amount); | |
break; | |
} | |
throw new \InvalidArgumentException('Command not recognised: ' . $string); | |
} | |
} | |
class RectCanvasInstruction implements CanvasInstruction | |
{ | |
private $width; | |
private $height; | |
public function __construct(int $width, int $height) | |
{ | |
$this->width = $width; | |
$this->height = $height; | |
} | |
public function execute(Canvas $canvas) | |
{ | |
$canvas->fill(new Coordinates(0, 0), new Coordinates($this->width - 1, $this->height - 1)); | |
} | |
} | |
class RotateCanvasInstruction implements CanvasInstruction | |
{ | |
const COLUMN = 'column'; | |
const ROW = 'row'; | |
private $orientation; | |
private $position; | |
private $amount; | |
public function __construct(string $orientation, int $position, int $amount) | |
{ | |
$this->orientation = $orientation; | |
$this->amount = $amount; | |
$this->position = $position; | |
} | |
public function execute(Canvas $canvas) | |
{ | |
switch ($this->orientation) { | |
case self::COLUMN: | |
for ($i = 0; $i < $this->amount; $i += 1) { | |
$canvas->cycleCol($this->position); | |
} | |
break; | |
case self::ROW: | |
for ($i = 0; $i < $this->amount; $i += 1) { | |
$canvas->cycleRow($this->position); | |
} | |
break; | |
} | |
} | |
} | |
$stdIn = file_get_contents('8.txt'); | |
$data = new StringChunker($stdIn); | |
$generator = $data->iterate(); | |
$instructionFactory = new InstructionFactory(); | |
echo "\n"; | |
$canvas = new AsciiCanvas(50, 6); | |
foreach ($generator as $instruction) { | |
$action = $instructionFactory->create($instruction); | |
$action->execute($canvas); | |
} | |
echo $canvas->render(); | |
echo "\n"; | |
echo $canvas->on() . ' pixels on.'; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment