#!/usr/bin/perl # Program: rubix.cgi # Author: Rob Brown # Purpose: CGI to solve Rubik's Cube # DOB: 06/13/96 # $Id: rubix.cgi,v 1.23 2007/05/27 18:22:55 rob Exp $ # # Contributions by Neil Rashbrook # - Supplied entire source code for Cube 3D simulator java Applet # - Modifications to CGI to incorporate Applet # - Many Optimizations to CGI to make more efficient! # *** Thank You Neil! *** $notify='feedback@roobik.com'; # Log All Hits $year=(localtime(time))[5]+1900; open (LOG,">>rubix.$year.log"); ($refer)=split(/\?/,$ENV{'HTTP_REFERER'}); $date=`date`; chop $date; print LOG $date,":",$ENV{'REMOTE_ADDR'},":$refer\n"; close LOG; my $hits = 0; if (open (COUNT, "+; ($hits)=split; $hits++; seek (COUNT, 0, 0); print COUNT "$hits\n"; truncate(COUNT, tell COUNT); close COUNT; } else { $_ = `wc rubix.$year.log`; ($hits) = split; open (COUNT, ">rubix.$year.hits"); print COUNT "$hits\n"; close COUNT; } # Initialize Variables and Grab subs require "rubix.pl"; print "Content-type: text/html\n\n"; %GET = split(/[=&]/, $ENV{'QUERY_STRING'}); for ($k=0;$k<6;$k++) {$taken{$GET{"r11$k"}}=$k+1 if $GET{"r11$k"};} if (scalar(keys(%taken)) != 6) { foreach (@colors) {$taken{$_}=$GET{$_} if $GET{$_} ne '';} @taken = keys(%taken); &crash("Sorry, I can only fix cubes with (6) sides, not (", scalar(@taken),")") if scalar(@taken) != 6 && $GET{'function'}; if ($taken{$taken[0]} < 0) {for ($k=0;$k<6;$k++) {$taken{$taken[$k]}=6-$k;}} } $completed=1; for ($i=0;$i<3;$i++) {for($j=0;$j<3;$j++) {for($k=0;$k<6;$k++) { if ($GET{"r$i$j$k"}) { $r{"$i$j$k"}=$GET{"r$i$j$k"}; } elsif ($GET{"r$i$j$k"} eq "0") { $r{"$i$j$k"}=$GET{"add"}; } else {$completed=0;} }}} &play if $completed; &start if $GET{'function'} eq "start"; print < Robs Rubix Repair

Rob's Rubix Repair

Your Rubik's Cube will be back to normal soon

[$hits hits so far in $year]
You might want a KEY to help get you through this map of symbols.
Please check which colors you have on your cube: HEADER foreach (@colors) { print " "; } print "
$_
"; exit; sub start { ($GET{'add'}) = keys(%taken) unless $GET{'add'}; print " Rubix Repair

Enter All Cublets

Rubix Repair needs to know what your Rubik's Cube looks like in order to tell you how to fix it.
Grab a Crayon And fill in where this color appears on the cube
"; foreach $color (keys(%taken)) { print " "; } print "
$color
"; &showcube(); print " "; foreach (keys(%taken)) {print " ";} print "
If you do not see the 3D Cube Java Applet above, CLICK HERE TO DOWNLOAD JAVA 2 RUNTIME ENVIRONMENT (J2RE) PLUGIN SOFTWARE FREE for your browser. "; exit; } sub play { for ($i=0;$i<3;$i++) {for($j=0;$j<3;$j++) {for($k=0;$k<6;$k++) {$check{$r{"$i$j$k"}}++;}}} $completed=-1; foreach (keys(%taken)) { if ($check{$_} != 9) { print "ERROR: $check{$_} $_ found
"; $completed=0; } } &start if !$completed; print "Cube Stored

Cube Stored

NOW WE CAN HAVE FUN! Get a KEY if you can't speak Rubik
"; #print "
"; #&debug; #print "
"; if ($GET{function} eq "Solve") { $main=&Export; # print "[Main:$main]
\n"; if ($GET{'function'} eq "perform") { $GET{'codes'}=~tr/a-z/A-Z/; $GET{'codes'}=~tr/A-S//cd; $GET{'codes'}=&compact($GET{'codes'}); &DoToCube($GET{'codes'}); print "Debug Commands--
", &Human($GET{'codes'}),"
\n"; &Import($main); } if ($GET{'function'} eq "Solve") { require "solve.pl"; # &FixAll $shortmoves=0; $premoves=""; @log=(); $unchanged=$main; # print "[Main:$main]
\n"; $repeats=$GET{'ways'}; $maxpre=$GET{'prelen'}; $verbose=$GET{'verbose'}; $pause=$GET{'pause'}; $pause=0 unless length $pause; $rotation=$GET{'rotation'}; $rotation=0 unless length $rotation; # I want it the same "randomness" every time # srand(time|$$); srand($GET{srand}); while ($repeats-- && 1) { # print "DEBUG: Fixing...
\n"; $thisanswer=&FixAll(); if (!$verbose) { $thisanswer=~s/T//g; } # print "[$thisanswer<--$main]
\n"; # print "DEBUG: Successful
\n"; # &DoToCube($thisanswer,"main"); for($t=0;$t<6;$t++) { if (substr($main,$t*9,9) ne ($t+1)x9) { print " Congratulations, you found a bug!
PLEASE notify $notify
Please Supply Debugging Information...
Original Cube stamp: $unchanged
Tried premove codes: [$premoves]
Final Cube Resulted: $main
"; open (BUGS,">>rubix.BUGS"); print BUGS `date`; print BUGS "Original $unchanged\n"; print BUGS "Premoves $premoves\n"; print BUGS "Result $main\n"; print BUGS "-"x20,"\n"; close BUGS; &crash("THANK YOU FOR PLAYING"); } } $thisanswer=&compact($premoves.$thisanswer); if (length($thisanswer)<$shortmoves || !@log) {push(@log,join(":", (($shortmoves=length($thisanswer)), $GET{'ways'}-$repeats, $premoves)));} # print "[LOG(\"",join("\",\"",@log),"\")]
\n"; $main=$unchanged; # print "[Main:$main]
\n"; $i=int(rand($maxpre)); $premoves=""; while ($i--) {$premoves.=pack("c",int(rand(18))+65);} # print "DEBUG: [Premoves $premoves]
\n"; &DoToCube($premoves); } print "
    Solve Report"; foreach (@log) { ($no,$try)=split(/\:/); print "
  • Try $try - took $no moves to solve"; } print "
"; @log=reverse(@log); ($j,$j,$fanswer)=split(/\:/,$log[0]); # print "DEBUG: Fastest [Premoves $fanswer]
"; $main=$unchanged; &DoToCube($fanswer); $f=&FixAll(); if (!$verbose) { $f=~s/T//g; } $fanswer=&compact($fanswer.$f); # print "[Adding FixAll --> \"$fanswer\" from $f from $solution] (line ",__LINE__,")
\n"; $main=$unchanged; # print "[Main:$main]
\n"; print "Solving Cube ...
\n"; $chunk=$GET{'atatime'} || do { print "Ouch [$ENV{HTTP_USER_AGENT}] Browser bugs can't handle pull down!
\n"; 16; }; while ($fanswer) { my $chunk_moves = substr($fanswer, 0, $chunk, ""); $steps = &Steps($chunk_moves); print "(",length("$chunk_moves$fanswer")," moves left)\n"; print "

",&Human($chunk_moves),"

\n"; print "
"; &showcube("min"); &DoToCube($chunk_moves); &Import($main); } print "
\n"; } } $steps=''; if ($GET{function} eq "Solve") { print < If your cube really is fixed, send me a small donation if you want:
\$
If your cube is not fixed, then you did not follow the moves correctly. I'm sorry, but you'll need to START ALL OVER

Due to the large number of requests for my source code, I am just going to post it for everyone to download.
SOURCE CODE

Or tell me Complaints or Compliments now
Your email address:
SOLVED } else { &showcube("hidden"); print "
  • Want the Solution?
    • Just slap the SOLVE button to see the answer
    • If you ignore the stuff below, you'll still get your solution
  • Verbose explanations of each step?
    • I use seven (7) steps to solving the Cube.
    • Check this box to tell you when each step has been completed.
    • Check this box if you are interested to know which step you are currently on.
    • Check this box if you'd like to learn more how to solve the cube yourself.
    • If you do not care which step you are on, do not check this box.
    • Each explanation will count as a \"move\" even though nothing moves.
    • Warning: For optimization purposes, some moves are performed to satisfy the demands of overlapping Steps. This makes it so there is never a definite boundry between Steps. In this case, they would be approximated.
  • Rotation speed
    • This configures how fast each move is executed.
  • Pause in between each move.
    • This configures how long to wait in between each move.
"; for ($k=0;$k<6;$k++) {print "";} print "
  • Show only commands at a time
    • If you have tons of memory or a very fast computer or you are just a wimp and you don't mind flipping though miles of pages, then set this low.
    • Warning: It could take many megabytes to display all the intermediate progressions if set too low.
    • If you feel brave or want to see the ENTIRE solution in one shot and don't like scrolling too much to see the answer, (or if your computer can't handle large documents), then set this all the way up.
    • Note: If you are using Microsoft IE, the java Applet might stop after one move, in which case you must set this to ONE.
  • Try different ways to solve
    • (This option effects the most factors)
    • As you may know, there are a bazillion ways to solve your cube
    • Some ways are more moves than other ways
    • If you don't care how many moves it takes to fix, then set low (1) to see the brute force solution (FAST)
    • If you want a closer to minimal solution, then set higher
    • Setting to 50 almost guarantees a solution under 100 moves
    • Setting to 1 almost guarantees a solution over 100 moves
    • Warning: It takes about 50 milliseconds (on average) to determine each solution. So don't set this too high or else it might take a while to load.
    • The shortest solution of all the tries will be used (of course)
  • Prepend Sequence upto moves.
    • This is the only Artificial Intelligence of this program
    • This program is written in Perl so there is no random involved in finding the solution
    • But a random bunch of moves can be done before attempting to find the solution
    • This actually saves moves in the long run (on a random cube) but can never hurt, since only the shortest solution (including the moves done at the beginning) is what you will use to solve the cube
    • Since most humans can not solve a random cube in less than two seconds, this program can try many possibilities and save more time for the slow human (you).
  • Seed with value of for Randomization.
    • Theoretically it should not matter the number you choose.
    • This is mostly for debugging.
    • It may increase or decrease the number of moves you need to perform to solve your cube depending on how lucky you are.
    • You are free to try different numbers if you wish.

    Don't use the pow button please, it's for my debugging.
    (And I certainly found MANY so far)
    Debug Codes to Perform:
    Please help me find more bugs...
    $notify "; } exit; } sub showcube { ($opt)=@_; print "
    "; print " "; foreach (keys(%taken)) {$k=6-$taken{$_}; print " ";} print " $steps "; $k=0; foreach (@table) { print "$_"; for ($i=0;$i<3;$i++) { print ""; for ($j=0;$j<3;$j++) { if ($opt eq "min") { print "\n\n"; } elsif($opt eq "hidden") { print "\n\n"; } else { print ""; } } print ""; } print "
       \n
    \n"; $k++; } print "
    "; } sub crash {print @_; exit;}