Created
November 2, 2014 11:58
-
-
Save CMCDragonkai/90250599fb0274265c3c to your computer and use it in GitHub Desktop.
PHP: Does the turtle cross a point that it has already visited? (Possibly useful in a snake games)
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 | |
/** | |
* Logo Turtle Challenge | |
* A turtle starts at (0,0). | |
* You have an array of movements, where each element represents the distance of a single move. | |
* Directions are cycled every four elements going through north, east, south, west. | |
* Find the move where the turtle crosses through a point that it has passed through before. | |
* This solution is somewhat space inefficient, and could become time inefficient if the distance range for a particular move is huge! | |
* There is probably a solution that allows you to persist only the corner coordinates and then using line equations to figure out if they intersect. | |
* The space inefficiency could be partially solved with a xrange generator. | |
* Right now it's kind of like O(n * (m+m)) where m is the average size of the distance range. | |
* However if you create a custom xrange generator, that allows us to lazily build out the $coordinates_to_check, then it would become O(n*m) where m is the average size of the distance range. | |
* You would still need keep the $coordinates array though! | |
* Could be further micro-optimised by only checking the coordinates on the fourth[3] movement. | |
*/ | |
function logo_turtle($movements) { | |
$coordinates = [0 => [0 => true]]; | |
$current_coordinate = [ | |
'x' => 0, | |
'y' => 0 | |
]; | |
$directions = ['n', 'e', 's', 'w']; | |
foreach($movements as $move => $distance){ | |
// cycle through the directions | |
$current_direction = array_shift($directions); | |
array_push($directions, $current_direction); | |
// if the distance is less than 1, then skip it, but we still cycle the direction! | |
if ($distance < 1) { | |
continue; | |
} | |
// clean slate | |
$coordinates_to_check = []; | |
// for each direction, acquire a list of coordinates derived from its traverse | |
// these coordinates will be used to check if turtle crosses its own previous path | |
switch($current_direction){ | |
case 'n': | |
$x_end = $current_coordinate['x']; | |
$y_end = $current_coordinate['y'] + $distance; | |
$start = $current_coordinate['y'] + 1; | |
foreach(range($start, $y_end) as $value){ | |
$coordinates_to_check[] = [ 'x' => $current_coordinate['x'], 'y' => $value]; | |
} | |
break; | |
case 'e': | |
$x_end = $current_coordinate['x'] + $distance; | |
$y_end = $current_coordinate['y']; | |
$start = $current_coordinate['x'] + 1; | |
foreach(range($start, $x_end) as $value){ | |
$coordinates_to_check[] = [ 'x' => $value, 'y' => $current_coordinate['y']]; | |
} | |
break; | |
case 's': | |
$x_end = $current_coordinate['x']; | |
$y_end = $current_coordinate['y'] - $distance; | |
$start = $current_coordinate['y'] - 1; | |
foreach(range($start, $y_end) as $value){ | |
$coordinates_to_check[] = [ 'x' => $current_coordinate['x'], 'y' => $value]; | |
} | |
break; | |
case 'w': | |
$x_end = $current_coordinate['x'] - $distance; | |
$y_end = $current_coordinate['y']; | |
$start = $current_coordinate['x'] - 1; | |
foreach(range($start, $x_end) as $value){ | |
$coordinates_to_check[] = [ 'x' => $value, 'y' => $current_coordinate['y']]; | |
} | |
break; | |
} | |
// if the traversal meets one of the existing coordinates, then the current move is an interception | |
foreach($coordinates_to_check as $xy){ | |
if( | |
isset( | |
$coordinates[ | |
$xy['x'] | |
][ | |
$xy['y'] | |
] | |
) | |
){ | |
return $move; | |
} | |
// add the point to the list of coordinates that has been traversed | |
$coordinates[$xy['x']][$xy['y']] = true; | |
} | |
// update the current coordinate for the next iteration | |
$current_coordinate = [ | |
'x' => $x_end, | |
'y' => $y_end | |
]; | |
} | |
return -1; | |
} | |
$moves = [1, 3, 2, 5, 4, 4, 6, 3, 2]; | |
$turtle_move = logo_turtle($moves); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment