Skip to content

Instantly share code, notes, and snippets.

@Nessworthy

Nessworthy/8.php Secret

Created December 8, 2016 10:42
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save Nessworthy/c793508b3b7383da34bdc70d534d3a3d to your computer and use it in GitHub Desktop.
Save Nessworthy/c793508b3b7383da34bdc70d534d3a3d to your computer and use it in GitHub Desktop.
<?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