3v4l.org

run code in 300+ PHP versions simultaneously
<?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"); } }

preferences:
30.44 ms | 402 KiB | 5 Q