# Simple PHP scrambler

#### mrCage

##### Member
Hi

As part of my new FMC website i wrote a PHP scrambler, so that i can generate scrambles automatically and insert to the database, one scramble for each week. I do not prefill the database with scrambles. I just generate new ones when the current last scramble is expired on accessing the site. Anyhow i just wanted to show the code for the scrambler - not the complete website

Code:
function makeScramble($length) { /*$faces = array('U','D,'F','B','R','L')
$taken = array(0,0,0,0,0,0,0);$numturns = array(1,1,1,1,1,1,1,2,2);
$axis = array(1,1,1,2,2,3,3);$modifiers = array('',','\'','2');
*/
$faces[1] = 'U';$faces[2] = 'D';
$faces[3] = 'F';$faces[4] = 'B';
$faces[5] = 'R';$faces[6] = 'L';
$taken[1] = 0;$taken[2] = 0;
$taken[3] = 0;$taken[4] = 0;
$taken[5] = 0;$taken[6] = 0;
$numturns[1] = 1;$numturns[2] = 1;
$numturns[3] = 1;$numturns[4] = 1;
$numturns[5] = 1;$numturns[6] = 1;
$numturns[7] = 2;$numturns[8] = 2;
$modifiers[1] = '';$modifiers[2] = '2';
$modifiers[3] = '\'';$axis[1] = 1;
$axis[2] = 1;$axis[3] = 2;
$axis[4] = 2;$axis[5] = 3;
$axis[6] = 3;$prevaxis = -1;
$scramble='';$totturns = 0;
do {
//select current axis to work on
do {
$curraxis = rand(1,3); } while ($curraxis == $prevaxis);$prevaxis = $curraxis; //update previous axis //select number of turns on this axis if ($totturns<($length-1)) {$num = $numturns[rand(1,8)]; } else {$num = 1;
}
for ($j=1;$j<=$num;$j++) {
do {
$faceindex=rand(1,6);$modifierindex=rand(1,3);
} while (($axis[$faceindex] != $curraxis) || ($taken[$faceindex] == 1));$taken[$faceindex] = 1;$turn = $faces[$faceindex].$modifiers[$modifierindex]." ";
$scramble =$scramble.$turn;$totturns++;
}
for ($j=1;$j<=6; $j++) {$taken[$j] = 0; } } while ($totturns<$length); return$scramble;
}

$mylength = 30;$myscramble = makeScramble($mylength); ... (applet and/or database code ??) ... ... Note that it does generate valid scrambles without sequences that can eb simplified - like U' D2 U. This is done through simple axis control. I first select a random axis and do either 1 or 2 turns on this axis (1 or 2 randomly). Then select a DIFFERENT axis and 1 or 2 turns again. If i already have length-1 turns in the scramble a single turn is generated for the last axis. This is also how the official .js WCA scrambler works. Feel free to use my scrambler for any website that may make use of it I know the code is not very elegant, but it works!! It should be easy to translate the code to other programming languages ... Also it is not hard to extend to bigger cubes. Note how i get bias to doing a single turn on same axis at a time, through the numturns array. This may be adjusted as needed. - Per Last edited: #### ShadenSmith ##### Member Very nice work. How long did this take you? #### tim ##### Member Code: do {$curraxis = rand(1,3);
} while ($curraxis ==$prevaxis);
Can't you write that in a different (much cleaner) way?

- Per

#### Kenneth

##### Not Alot
It would be nicer to write variable declarations explicitly like in pascal.
Or the other way around, function definitions, else it is a variable/constant.

Tim, how can that be hard to understand? That loop is the same in any high level language. Keep asking for a random until it is not equal to the last one you had.

#### mrCage

##### Member
It would be nicer to write variable declarations explicitly like in pascal.
Or the other way around, function definitions, else it is a variable/constant.

Tim, how can that be hard to understand? That loop is the same in any high level language. Keep asking for a random until it is not equal to the last one you had.
Hi

I have been teaching both pascal and java to students. Indeed one of the most difficult things for them is to get to grips with conditional looping. Where the loop is "looping" a not predefined number of times - like the typical for statement. While - do is a bit easier to understand than the do-while version. The latter is very similar to the pascal repeat - until construction.

To comment on Tim's suggestion further it is possible to "delete" prevaxis from the array temporarily. But coding this fully is a lot more lines of code than how i chose to do it. Yest another option is to simply go to next free if a random selction picks the same. There's almost always more than one way to skin a chicken

- Per

#### tim

##### Member
Tim, how can that be hard to understand? That loop is the same in any high level language. Keep asking for a random until it is not equal to the last one you had.
Indeed i do understand what's going on. It's fine to use a loop if you can't expect the results of your random function (e.g. floats).

But if you have just 3(!) values, it's not necessary (and looks indeed ugly).

Code:
array = (1,2,3)
array.delete(lastValue)
newValue = array[rand(array.length)]

#### Kenneth

##### Not Alot
A niter way to write the same loop is:

Code:
do {} while ($prevaxis == ($curraxis = rand(1,3)));
Emty loop, all is in the condition =)

#### mrCage

##### Member
A niter way to write the same loop is:

Code:
do {} while ($prevaxis == ($curraxis = rand(1,3)));
Emty loop, all is in the condition =)
Yes yes this is possible but i do not like to execute code as part of a condition evaluation. I'm quite a bit of a coding classicist i guess.

Another ugly coding construction is

Code:
while (true) {
..
if ( ...) break;
..
}
- Per

#### Stefan

##### Member
$curraxis = ($prevaxis + rand(1,2)) % 3;

Noobs.

#### mrCage

Hi Stefan

Yes that works since there is always just 1 taken axis in this case. One little catch though. If $prevaxis was 1 or 2 and the increment was 2 or 1 then the$curraxis would first evaluate to 3. Then mod it with 3 gives 0. The axes are in the range 1-3 not 0-2. So yes the fix is trivial, set up a new axis range like $axis = array(0,0,1,1,2,2). After making some code work i generally do no bother to improve it unless there would be a big benefit (in speed!) Feel free to check the speed difference on say 10 000 scrambles with this little tweak - Per #### mrCage ##### Member Hi Here is the final version of the scrambler: Code: [FONT=Courier New]function makeScramble($length)[/FONT]
[FONT=Courier New]{[/FONT]
[FONT=Courier New][COLOR=seagreen]//initialisation[/COLOR][/FONT]
[FONT=Courier New]$faces = array('U','D','F','B','R','L');[/FONT] [FONT=Courier New]$taken = array(0,0,0,0,0,0);[/FONT]
[FONT=Courier New]$numturns = array(1,1,1,1,1,1,2,2);[/FONT] [FONT=Courier New]$axis = array(0,0,1,1,2,2);[/FONT]
[FONT=Courier New]$modifiers = array('','2','\'');[/FONT] [FONT=Courier New]$curraxis = rand(0,2); [COLOR=seagreen]//small fix to allow a scramble to start with ANY axis[/COLOR][/FONT]
[FONT=Courier New]$scramble='';[/FONT] [FONT=Courier New]$totturns = 0;[/FONT]
[FONT=Courier New][COLOR=seagreen]//generate a scramble[/COLOR][/FONT]
[FONT=Courier New]do {[/FONT]
[FONT=Courier New][COLOR=seagreen]//select current axis to work on[/COLOR][/FONT]
[FONT=Courier New] $curraxis = ($curraxis + rand (1,2)) % 3; [COLOR=seagreen]//thx to Kenneth!![/COLOR][/FONT]
[FONT=Courier New] [COLOR=seagreen]//$prevaxis =$curraxis; //update previous axis[/COLOR][/FONT]
[FONT=Courier New] [COLOR=seagreen]//select number of turns on this axis[/COLOR][/FONT]
[FONT=Courier New] if ($totturns<($length-1)) {[/FONT]
[FONT=Courier New]  $num =$numturns[rand(0,7)];[/FONT]
[FONT=Courier New] } else {[/FONT]
[FONT=Courier New]  $num = 1;[/FONT] [FONT=Courier New] } [/FONT] [FONT=Courier New] [COLOR=seagreen]//generate the turns on this axis[/COLOR] [/FONT] [FONT=Courier New] for ($j=1; $j<=$num; $j++) {[/FONT] [FONT=Courier New] do {[/FONT] [FONT=Courier New]$faceindex=rand(0,5);[/FONT]
[FONT=Courier New]   $modifierindex=rand(0,2);[/FONT] [FONT=Courier New] } while (($axis[$faceindex] !=$curraxis) || ($taken[$faceindex] == 1));[/FONT]
[FONT=Courier New]  $taken[$faceindex] = 1;[/FONT]
[FONT=Courier New]  [COLOR=seagreen]//generate the corresponding turn and add it to scramble[/COLOR][/FONT]
[FONT=Courier New]  $turn =$faces[$faceindex].$modifiers[$modifierindex]." ";[/FONT] [FONT=Courier New]$scramble = $scramble.$turn;[/FONT]
[FONT=Courier New]  $totturns++;[/FONT] [FONT=Courier New] }[/FONT] [FONT=Courier New] [COLOR=seagreen]// free the faces[/COLOR][/FONT] [FONT=Courier New] for ($j=0; $j<=5;$j++) {[/FONT]
[FONT=Courier New]  $taken[$j] = 0;[/FONT]
[FONT=Courier New] }[/FONT]
[FONT=Courier New]} while ($totturns<$length);[/FONT]
[FONT=Courier New]return $scramble;[/FONT] [FONT=Courier New]}[/FONT] [FONT=Courier New]...[/FONT] [FONT=Courier New]$mylength=30;[/FONT]
[FONT=Courier New]$myscramble=makeScramble($mylength);[/FONT]
[FONT=Courier New]...[/FONT]
This is much neater code
I will soon post a PHP 4by and 5by scrambler, using r and R style turns only. lower case means turning the 2 OUTER layers.

- Per

Last edited:

#### Kenneth

##### Not Alot
//select current axis to work on
$curraxis = ($prevaxis + rand (1,2)) % 3;
$prevaxis =$curraxis; //update previous axis

$curraxis = ($curraxis + rand (1,2)) % 3;

You don't need to save the old value because you do not compare anymore

#### mrCage

##### Member
//select current axis to work on
$curraxis = ($prevaxis + rand (1,2)) % 3;
$prevaxis =$curraxis; //update previous axis

$curraxis = ($curraxis + rand (1,2)) % 3;

You don't need to save the old value because you do not compare anymore
Umm that's true. Stefan you are a noob

Getting rid of variables is a good thing ...

- Per

#### mrCage

##### Member
Hi

Yes your scrambler overcomes the "axis" problem. But i don not fully understand how that code works. This part:
Code:
($i^1) !=$turn
I'm probably just a bit bit slow today I know it's your axis trick somehow ...

- Per

#### Leo

##### Member
Bah I wish I understood all of this language and how to use it :/. Nice scrambler

All I know is the tiniest bit of html.

#### mrCage

##### Member
Hi

And here is the promised 4x4x4/5x5x5 scrambler:

Code:
<?php
function make45Scramble($length) {$faces = array('U','u','d','D','F','f','b','B','R','r','l','L');
$taken = array(0,0,0,0,0,0,0,0,0,0,0,0);$numturns = array(1,1,1,1,1,1,2,2,2,3);
$axis = array(0,0,0,0,1,1,1,1,2,2,2,2);$modifiers = array('','2','\'');
$curraxis = rand(0,2);$scramble='';
$totturns = 0; do { //select current axis to work on$curraxis = ($curraxis + rand(1,2)) % 3; //select number of turns on this axis$num = $numturns[rand(0,9)]; if ($num>($length-$totturns)) {$num=$length-$totturns;} for ($j=1; $j<=$num; $j++) { do {$faceindex=rand(0,11);
$modifierindex=rand(0,2); } while (($axis[$faceindex] !=$curraxis) || ($taken[$faceindex] == 1));
$taken[$faceindex] = 1;
$turn =$faces[$faceindex].$modifiers[$modifierindex]." ";$scramble = $scramble.$turn;
$totturns++; } for ($j=0; $j<=11;$j++) {
$taken[$j] = 0;
}
} while ($totturns<$length);
return $scramble; }$mylength=50;
$myscramble=make45Scramble($mylength);
echo "Test Mix = ".\$myscramble;
?>
Lowercase letters is double outer layer turns. Uppercase letters are the normal single outermost layer turns. Uu' may look strange since this produces a single inner layer turns. But this is intentional. since this notation has no tokens for the inner layer turns. m,e and s may easily be added if needed

- Per
Some things may look strange but are intentional.

#### tim

##### Member
Here's our Ruby (requires random access for arrays, which is implemented in Rails) version of it:

Code:
def cube_scramble(turns)
scramble = ''
variants = ['', "'", '2']
axis = rand turns.size
scramble_length.times do
axis = (axis + rand(turns.size - 1) + 1) % turns.size
scramble += (scramble.empty? ? '' : ' ') + turns[axis].rand + variants.rand
end
scramble
end

#3x3x3 & 2x2x2
cube_scramble [%w{R L}, %w{F B}, %w{D U}]
#4x4x4 & 5x5x5
cube_scramble [%w{R L}, %w{F B}, %w{D U}, %w{r l}, %w{f b}, %w{d u}]
Not the shortest, fastest or whatever scrambler, so i'm open for improvements .