Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- <?php
- $colors = array(
- 1 => 'R',
- 2 => 'O',
- 4 => 'Y',
- 8 => 'G',
- 16 => 'B',
- 32 => 'P',
- false => 'X',
- );
- $used_towers = array_fill(0, 6, 0);
- $cube = array(
- array(1,3,4,5,2,0),
- array(2,5,1,4,1,3), // note 'special' base at (2, 1) here
- array(0,1,3,2,5,4),
- array(5,4,0,3,0,2), // note 'special' base at (2, 3) here
- array(4,2,5,0,3,1),
- array(3,0,2,1,4,5),
- );
- $solution = array_fill(0, 6, array_fill(0, 6, false));
- function solve_color($color) {
- global $solution, $used_towers, $colors, $cube;
- $orig = $solution;
- $failed = array( );
- $i = 0;
- $j = -1;
- while ($i <= 5) {
- // if we already have a piece in this space (via pre-reqs)
- // just skip it
- if (in_array($color, $orig[$i])) {
- $i++;
- $j = -1;
- continue;
- }
- if ( ! isset($failed[$i])) {
- $failed[$i] = array( );
- }
- do {
- $j++;
- $size = $cube[$i][$j];
- // we've already tried this one, try the next space
- } while (in_array($size, $failed[$i]) && (5 > $j));
- // try putting a piece in the ith row in the last + 1 col
- if (test_color(($i * 6) + $j, $solution, $used_towers, $color, $size) && ! in_array($size, $failed[$i])) {
- $solution[$i][$j] = $color;
- $used_towers[$size] |= $color;
- $i++;
- $j = -1;
- continue;
- }
- // something failed, go back a row and try a new piece
- if (5 <= $j) {
- // backtrack until we find a row that didn't already have a piece in it
- do {
- $i--;
- } while (in_array($color, $orig[$i]));
- // find out what piece was used here
- foreach ($solution[$i] as $j => $col) {
- if ($color == $col) {
- $size = $cube[$i][$j];
- $failed[$i][] = $size;
- $used_towers[$size] ^= $color;
- }
- }
- $solution[$i] = $orig[$i];
- $j = -1;
- continue;
- }
- }
- return $solution;
- }
- function solve_color_by_pieces($color, $solution, $used_towers, $continue_colors = false, $top = false) {
- global $colors, $cube;
- $orig = $solution;
- $sols = array( );
- while (32 >= $color) {
- $size = 0;
- while (6 >= count(filter_color($used_towers, $color)) && (5 >= $size)) {
- if ($color & $used_towers[$size]) {
- $size++;
- continue;
- }
- // find ALL possible solutions for this size
- for ($pos = 0; $pos < 36; ++$pos) {
- if ($size != $cube[floor($pos / 6)][$pos % 6]) {
- continue;
- }
- if ( ! test_color($pos, $solution, $used_towers, $color, $size)) {
- continue;
- }
- // add to this solution path and continue...
- $solution[floor($pos / 6)][$pos % 6] = $color;
- $used_towers[$size] |= $color;
- $return = ((6 > count(filter_color($used_towers, $color))) ? solve_color_by_pieces($color, $solution, $used_towers, $continue_colors) : array('SOLUTION' => $solution));
- if ($return) {
- $sols[] = $return;
- }
- // remove this solution and continue searching this level
- $solution[floor($pos / 6)][$pos % 6] = false;
- $used_towers[$size] ^= $color;
- }
- break;
- }
- if ($top) {
- unset($sols);
- $sols = array( );
- }
- if ($continue_colors) {
- $color << 1;
- }
- else {
- break;
- }
- }
- return $sols;
- }
- // solve for yellow given the initial piece constraint
- $color = 4;
- $solution[1][2] = $color;
- $size = $cube[1][2];
- $used_towers[$size] |= $color;
- echo solve_color_by_pieces($color, $solution, $used_towers);
- // helper functions
- function test_color($pos, $solution, $used_towers, $color, $size) {
- if (36 <= $pos) {
- return false;
- }
- // check if piece exists in solution at this location
- if (false !== $solution[floor($pos / 6)][$pos % 6]) {
- return false;
- }
- // check if tower of this size and color has already been used
- if ($color & $used_towers[$size]) {
- return false;
- }
- // check if tower has already been used in row or column:
- for ($i = 0; $i < 6; ++$i) {
- if ($color == $solution[floor($pos / 6)][$i]) {
- return false;
- }
- if ($color == $solution[$i][$pos % 6]) {
- return false;
- }
- }
- // special conditions for the two special towers
- if (array(1, 2) == (array(floor($pos / 6), $pos % 6)) && (4 != $color)) {
- return false;
- }
- if (array(3, 2) == (array(floor($pos / 6), $pos % 6)) && (2 != $color)) {
- return false;
- }
- return true;
- }
- function filter_color($used, $color) {
- foreach ($used as & $row) {
- $row = (bool) ($color & $row);
- }
- unset($row);
- return array_filter($used);
- }
- function find_sols($sols, $color) {
- foreach ($sols as $key => $sol) {
- if ('SOLUTION' === $key) {
- foreach ($sol as $i => $row) {
- foreach ($row as $j => $piece) {
- if ($color == $piece) {
- echo '$solution['.$i.']['.$j.'] = ';
- }
- }
- }
- echo "<br>\n";
- }
- elseif (is_array($sol)) {
- find_sols($sol, $color);
- }
- }
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement