Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- <?php
- /**
- * FFXIII-2 Hands Of Time Solver v0.1b (and probably the only version!)
- * Author: Nuno Melo (c) 2012
- * Final Fantasy and all related stuff is a trademark of Square-Enix and all that stuff.
- *
- * Example usage:
- * try {
- * //ex: new Puzzle(1,4,2,5,2)
- * $puzzle = new Puzzle([Pass the clock numbers as arguments from the top-center position, in a clockwise direction]);
- * $solution = $puzzle->solve();
- * foreach ($res->getValues() as $node)
- * echo $node . " ";
- * } catch (Exception $ex){
- * echo $lang[$ex->getMessage()];
- * }
- *
- * Exceptions:
- * I went with using the top-class Exception, and a string is passed to identify the error. Let's keep it simple.
- * IP -> Too many, or too little nodes.
- * NS -> No solutions were found.
- * IN -> Numbers are out of range.
- * ES -> Empty stack (if you try to pop() in an empty Path object)
- */
- //Constants
- define('MAX_NODES', 13);
- define('MIN_NODES', 5);
- //text responses
- $lang = array(
- "IP" => "Nodes out of bounds. 5-13 nodes tops!",
- "ES" => "Stack is empty.",
- "NS" => "No solutions.",
- "IN" => "Invalid numbers. Must be in the [1, 9] E N, range"
- );
- /**
- * Represents a full puzzle
- */
- class Puzzle {
- private $nodeCount;
- private $move = array();
- private $state = array();
- private $found = FALSE;
- function __construct() {
- $this->nodeCount = func_num_args();
- if($this->nodeCount >= MIN_NODES && $this->nodeCount <= MAX_NODES){
- //initialize state and move
- for($i = 0, $tmp = func_get_args() ; $i < $this->nodeCount ; $this->state[$i] = TRUE, $this->move[$i] = $tmp[$i], $i++)
- if($tmp[$i] < 1 || $tmp[$i] > 9 || !is_int($tmp[$i])) throw new Exception('IN');
- } else throw new Exception('IP');
- }
- /**
- * This calls the recursive function.. Starts with the first node, and visits every node until it finds a solution
- */
- public function solve(){
- for($i = 0, $tmp ; !$this->found && $i < $this->nodeCount ; $i++)
- $tmp = $this->solveRec($this->state, $i, $this->nodeCount, new Path());
- if($tmp != null) return $tmp;
- else throw new Exception('NS');
- }
- /**
- * Recursive bruteforce function
- */
- private function solveRec($state, $node, $left, $path){
- //check if a solution has been found or if this node hasn't been visited
- if($this->found == TRUE || $state[$node] == FALSE) return null;
- $left--;
- $path->push($node);
- $state[$node] = FALSE;
- //checks if this is the final node (All other nodes have been visited)
- if($left == 0){
- $this->found = TRUE;
- return $path;
- }
- //if not, keep on moving through this node's path if possible
- $links = $this->getNodes($node, $this->move[$node]);
- //is it worth going to the connected nodes?
- if(!$state[$links['left']] && !$state[$links['right']]) return NULL;
- $leftRes = $this->solveRec($state, $links['left'], $left, clone $path);
- $rightRes = $this->solveRec($state, $links['right'], $left, clone $path);
- if($leftRes != NULL) return $leftRes;
- else if($rightRes != NULL) return $rightRes;
- else return null;
- }
- /**
- * This simply calculates the left and right nodes of a given node using its offset (value).
- */
- private function getNodes($node, $value){
- $left = ($node-$value < 0) ? $this->nodeCount-(abs($node-$value) % $this->nodeCount) : $node-$value;
- return array("left" => $left, "right" => ($node+$value) % $this->nodeCount);
- }
- }
- /**
- * Represents a path through the clock, it's similar to a stack (but we're breaking some rules here :) )
- */
- class Path {
- private $top = -1;
- private $values = array();
- public function push($value){
- $this->top++;
- $this->values[$this->top] = $value;
- }
- public function pop(){
- if($this->top < 0) throw new Exception('ES');
- $tmp = $this->values[$this->top];
- $this->top--;
- return $tmp;
- }
- public function isEmpty(){ return $this->top < 0; }
- public function getValues(){ return $this->values; }
- }
- ?>
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement