<?php
$solution = new PuzzleSolver($argv[1], $argv[2]);
$solution->solvePuzzle();
$solution->saveOutput();
/*
* PuzzleSolver class.
*
* Will draw lines between points defined by '#' character.
*/
class PuzzleSolver
{
const searchChar = '#';
const lineChar = '*';
public $puzzle = array();
public $solvedPuzzle = array();
public $output;
private $linePoints = array();
/**
* Constructs a PuzzleSolver object.
*
* @param string $input
* The input file in .txt format containing the puzzle.
* @param string $output optional
* The output file to save the solved puzzle.
*
* @throws ErrorException
* If either the input file is not provided or the puzzle is empty.
*/
function __construct($input, $output = null) {
if (!isset($input))
throw new ErrorException("Input puzzle must be defined.");
$this->puzzle = file_get_contents($input);
$this->puzzle = explode("\n", $this->puzzle);
$this->output = $output;
if (!$this->puzzle)
throw new ErrorException("Puzzle is empty; I need a challenge!");
}
/**
* Main puzzle solving function, finds each point which will be connected.
*/
public function solvePuzzle() {
foreach ($this->puzzle as $index => $row) {
$i = 0;
while ($i <= strlen($row)) {
$foundChar = strpos($row, $this::searchChar, $i);
if ($foundChar === FALSE) {
break;
} else {
array_push($this->linePoints, array('row' => $index, 'col' => $foundChar));
$i = $foundChar + 1;
}
}
}
$this->solvedPuzzle = $this->puzzle;
$this->connectPoints();
}
/**
* Takes the line points found by solvePuzzle() and connects them.
*/
private function connectPoints() {
foreach ($this->linePoints as $point) {
if (isset($previousPoint)) {
if ($previousPoint['row'] != $point['row']) {
$this->draw($previousPoint, $point);
$pointCorner = ($previousPoint['col'] > $point['col']) ? $previousPoint['col'] + 1 : $previousPoint['col'] - 1;
$previousPoint = array('row' => $point['row'], 'col' => $pointCorner);
}
$this->draw($previousPoint, $point);
}
$previousPoint = $point;
}
}
/**
* Draw a line between two points using the global lineChar variable.
* Each point is expected to be an associative array with a row and col key.
*
* @param Array $start
* An associative array containing the start point.
* @param Array $end
* An associative array containing the end point.
*/
private function draw(Array $start, Array $end) {
if ($start['col'] == $end['col'] && $start['row'] == $end['row'])
return;
if ($start['row'] == $end['row']) {
$this->solvedPuzzle[$start['row']] = $this->line($this->solvedPuzzle[$start['row']], $start['col'], $end['col']);
} else {
foreach ($this->puzzle as $index => $row) {
if ($index > $start['row'] && $index < $end['row']) {
$this->solvedPuzzle[$index] = $this->line($row, $start['col']);
}
}
}
}
/**
* Responsible for the character replacement in the line draw.
*
* @param string $text
* The full text of the line being drawn in.
* @param integer $start
* The character position of the start of the line.
* @param integer $end optional
* The character position of the end of the line.
*
* @return string
* The resulting string after the line is drawn.
*/
private function line($text, $start, $end = null) {
if (isset($end) && $start > $end) list($start, $end) = array($end, $start);
$start = $start + isset($end);
$length = (!isset($end)) ? 1 : abs($start - $end);
return substr($text, 0, $start) . str_repeat($this::lineChar, $length) . substr($text, $start+$length);
}
/**
* Saves the puzzle results to a file.
*/
public function saveOutput() {
if (!$this->output) {
$this->printOutput();
} else {
file_put_contents($this->output, implode($this->solvedPuzzle, "\n"));
}
}
/**
* Prints the puzzle results to the screen.
*/
public function printOutput() {
print implode($this->solvedPuzzle, "\n");
}
}
Warning: Undefined array key 1 in /in/T8RJv on line 3
Warning: Undefined array key 2 in /in/T8RJv on line 3
Fatal error: Uncaught ErrorException: Input puzzle must be defined. in /in/T8RJv:36
Stack trace:
#0 /in/T8RJv(3): PuzzleSolver->__construct(NULL, NULL)
#1 {main}
thrown in /in/T8RJv on line 36
Process exited with code 255.
Notice: Undefined offset: 1 in /in/T8RJv on line 3
Notice: Undefined offset: 2 in /in/T8RJv on line 3
Fatal error: Uncaught ErrorException: Input puzzle must be defined. in /in/T8RJv:36
Stack trace:
#0 /in/T8RJv(3): PuzzleSolver->__construct(NULL, NULL)
#1 {main}
thrown in /in/T8RJv on line 36
Process exited with code 255.
Output for 7.3.32 - 7.3.33
Fatal error: Uncaught ErrorException: Input puzzle must be defined. in /in/T8RJv:36
Stack trace:
#0 /in/T8RJv(3): PuzzleSolver->__construct(NULL, NULL)
#1 {main}
thrown in /in/T8RJv on line 36
Process exited with code 255.
Notice: Undefined offset: 1 in /in/T8RJv on line 3
Notice: Undefined offset: 2 in /in/T8RJv on line 3
Fatal error: Uncaught exception 'ErrorException' with message 'Input puzzle must be defined.' in /in/T8RJv:36
Stack trace:
#0 /in/T8RJv(3): PuzzleSolver->__construct(NULL, NULL)
#1 {main}
thrown in /in/T8RJv on line 36
Process exited with code 255.
Output for 5.1.0 - 5.1.6, 5.2.0 - 5.2.17
Parse error: syntax error, unexpected T_PAAMAYIM_NEKUDOTAYIM in /in/T8RJv on line 54
Process exited with code 255.
Output for 5.0.0 - 5.0.5
Parse error: parse error, unexpected T_PAAMAYIM_NEKUDOTAYIM in /in/T8RJv on line 54
Process exited with code 255.
Output for 4.4.2 - 4.4.9
Parse error: syntax error, unexpected T_CONST, expecting T_OLD_FUNCTION or T_FUNCTION or T_VAR or '}' in /in/T8RJv on line 14
Process exited with code 255.
Parse error: parse error, unexpected T_CONST, expecting T_OLD_FUNCTION or T_FUNCTION or T_VAR or '}' in /in/T8RJv on line 14
Process exited with code 255.
Output for 4.3.2 - 4.3.4
Parse error: parse error, expecting `T_OLD_FUNCTION' or `T_FUNCTION' or `T_VAR' or `'}'' in /in/T8RJv on line 14
Process exited with code 255.