# Simple PHP scrambler



## mrCage (Mar 12, 2008)

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 


```
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


----------



## ShadenSmith (Mar 12, 2008)

Very nice work. How long did this take you?


----------



## tim (Mar 12, 2008)

```
do {
    $curraxis = rand(1,3);
} while ($curraxis == $prevaxis);
```
Can't you write that in a different (much cleaner) way?
I'm not good at PHP, but i think you could use an array - prefilled with all numbers - and subtract $prevaxis from the array. And then let PHP give you a random element out of this list.

Anyway, nice work .

btw. the dollar sign before every variable looks so ugly and is completely unnecassary...


----------



## mrCage (Mar 13, 2008)

Hi 

After trying to do it in some other way, this code took me about 2 hrs including debugging. The arrays may be initialised much more beautifully - i know. To avoid move redundancy i need to use some kind of loop, it's unavoidable. Exactly how to do that is up to the coder to find out. There's many things in the code that are not "beautiful". But it works fast, and that's the most important thing for me  My code is inspired by Jaap's javscript scrambler 

One last thing - the dollar sign ($) is necessary if php is gonna treat it as a variable/constant. Or else it will think it is a function. And yes, the dollars is one thing i do not like in php It would be nicer to write variable declarations explicitly like in pascal.

- Per


----------



## Kenneth (Mar 13, 2008)

mrCage said:


> 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 (Mar 13, 2008)

Kenneth said:


> mrCage said:
> 
> 
> > It would be nicer to write variable declarations explicitly like in pascal.
> ...


 
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 (Mar 13, 2008)

Kenneth said:


> 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).

What about (pseudocode):

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


----------



## Kenneth (Mar 13, 2008)

A niter way to write the same loop is:


```
do {} while ($prevaxis == ($curraxis = rand(1,3)));
```

Emty loop, all is in the condition =)


----------



## mrCage (Mar 13, 2008)

Kenneth said:


> A niter way to write the same loop is:
> 
> 
> ```
> ...


 
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


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


----------



## Stefan (Mar 13, 2008)

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

Noobs.


----------



## mrCage (Mar 13, 2008)

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 (Mar 14, 2008)

Hi 

Here is the final version of the scrambler:


```
[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


----------



## tim (Mar 14, 2008)

StefanPochmann said:


> $curraxis = ($prevaxis + rand(1,2)) % 3;
> 
> Noobs.



Damn, i feel so stupid... :/


----------



## Kenneth (Mar 14, 2008)

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

Like this instead:

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

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


----------



## mrCage (Mar 14, 2008)

Kenneth said:


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


 
Umm that's true. Stefan you are a noob

Getting rid of variables is a good thing ...

- Per


----------



## Stefan (Mar 14, 2008)

Bah. I only looked at the discussed part. And my scrambler is much shorter.


----------



## mrCage (Mar 16, 2008)

Hi 

Yes your scrambler overcomes the "axis" problem. But i don not fully understand how that code works. This part:

```
($i^1) != $turn
```
 
I'm probably just a bit bit slow today I know it's your axis trick somehow ...

- Per


----------



## Leo (Mar 16, 2008)

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 (Mar 20, 2008)

Hi 

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


```
<?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 (Apr 3, 2008)

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


```
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 .


----------



## Johannes91 (Apr 3, 2008)

I don't know much Ruby, but one thing stands out: I think it would make sense to pass scramble_length as a parameter. And at least in Python it's more efficient (and IMO more elegant) to use an array and join it once instead of repeatedly concatenating strings:

```
scramble = []
...
scramble.push(turns[axis].rand + variants.rand)
...
scramble.join(" ")
```


FWIW, here's a Haskell scrambler I wrote a while ago:

```
getScramble :: Int -> IO FlatAlg
getScramble = liftM fromJust . getGeneralScramble (map (flip (,) [1,2,3]) [U,D,F,B,R,L])

getGeneralScramble :: [(Face,[Int])] -> Int -> IO (Maybe FlatAlg)
getGeneralScramble xs n = do maybeFaces <- getRandomFaces (map fst $ filter (not . null . snd) xs) n
                             case maybeFaces of
                                Nothing    -> return Nothing
                                Just faces -> do suffixes <- mapM (liftM (Suffix . fromJust) . pick . fromJust . flip lookup xs) faces
                                                 return $ Just $ FlatAlg $ zipWith FaceMove faces suffixes

getRandomFaces :: [Face] -> Int -> IO (Maybe [Face])
getRandomFaces fcs = flip rec []
                   where rec :: Int -> [Face] -> IO (Maybe [Face])
                         rec 0 acc = return $ Just acc
                         rec n acc = do maybeFace <- pick (filter p fcs)
                                        case maybeFace of
                                           Nothing -> return Nothing
                                           Just x  -> rec (n-1) (x:acc)
                                   where p = case acc of
                                                []     -> const True
                                                (x:[]) -> (/= x)
                                                (x:y:_) | isSameSliceFace x y -> not . isSameSliceFace x
                                                        | otherwise           -> (/= x)

pick :: [a] -> IO (Maybe a)
pick [] = return Nothing
pick xs = liftM (Just . (xs !!)) $ randomRIO (0, length xs - 1)
```


----------



## joey (Apr 3, 2008)

```
def cube_scramble1(turns,scramble_length = 25)
    variants = ['', "'", '2']
    axis = rand turns.size
    (0..scramble_length).map do
      axis = (axis + rand(turns.size - 1) + 1) % turns.size
      turns[axis].rand + variants.rand
    end.join(" ")
end
```

I havn't tested that (too lazy), but I'm pretty sure it should work.


----------



## tim (Apr 3, 2008)

Johannes91 said:


> I don't know much Ruby, but one thing stands out: I think it would make sense to pass scramble_length as a parameter. And at least in Python it's more efficient (and IMO more elegant) to use an array and join it once instead of repeatedly concatenating strings:
> 
> ```
> scramble = []
> ...



Thanks, Johannes. In Ruby you can join an array in the same way, too. I don't know, why i didn't think about that. I'll change that immediately.
And for the scramble_length: Actually the method is part of the puzzle model, so the scramble_length is alway given (from the database), if you call the method. (I should've removed it for this post)

/edit: and thanks to joey, your method works and i use it from now on . (argh, how could i forget "map"?)


----------



## mrCage (Apr 16, 2008)

Hi 

It's nice to see other scramblers written in other languages. However for the new FMC site my only options are really like this: PHP, Perl, Javascript, COM object. Javascript is not a real option as it has to be done serverside, and i do not have time to get into ajax or similar technologies. As the site is hosted on a linux server the COM alternative is also not possible - i have no way to set up a virtual OS or anything like that. Perl is a good alternative, but for portabliity i just use plain PHP, not using PEAR or PECL or anything like that. ONE scramble is generated pr week (rollover) so speed is not really an issue The most important thing is to make valid (non-simplifiable) scrambles. Also, code that is very clear is better than tricky very compact scramblers. Easier to maintain, expand, port the code for future use. I believe that how i coded it can be ported easily to virtually any language (procedural ones at least).

- Per


----------



## Johannes91 (Apr 16, 2008)

Here's a simpler (but much less general) Haskell scrambler:

```
module SimpleScrambler where

import System.Random (randomRIO)
import Data.List ((\\))

getScramble :: Int -> IO String
getScramble n = fmap unwords $ mapM showFace =<< getFaces n
    where showFace x = fmap ("UFRLBD" !! x :) $ pick ["", "'", "2"]

getFaces :: Int -> IO [Int]
getFaces = go [] where
    go acc 0 = return acc
    go acc n = pick zs >>= \z -> go (z : acc) (n - 1)
        where zs = case acc of
                      (x:y:_) | x + y == 5 -> [0..5] \\ [x,y]
                      (x:_)                -> [0..5] \\ [x]
                      (_)                  -> [0..5] \\ []

pick :: [a] -> IO a
pick xs = fmap (xs !!) $ randomRIO (0, length xs - 1)
```

And a 127-byte Perl scrambler (could certainly be shortened, but I have other things to think about now):

```
perl -le 'for(0..24){$a=int rand 6 until$a-$a[0]&&$a+$a[0]-5|$a-$a[1];@a=($a,@a)}print join" ",map{(U,F,R,L,B,D)[$_].(v39,2)[rand 3]}@a'
```



mrCage said:


> Javascript is not a real option as it has to be done serverside, and i do not have time to get into *ajax* or similar technologies.


<nitpick>
Ajax basically lets client-side JavaScript make requests to server-side programs. It doesn't have much to do with server-side JavaScript.
</nitpick>



mrCage said:


> I believe that how i coded it can be ported easily to virtually any language (procedural ones at least).


That's a very important distinction to make. Not all languages have such things as loops and variables.


----------



## mrCage (Apr 16, 2008)

Johannes91 said:


> Here's a simpler (but much less general) Haskell scrambler:
> 
> ```
> module SimpleScrambler where
> ...


 
Tell me one PROCEDURAL common language that does not have loops and variables. I can think of some non-procedural ones. I never said server side javascript. I said i ignored javascript because i do not have time to get into ajax and similar.

It is best sometimes to just read between the lines.

And btw, i do not have ANY intention to switch to random position scrambling for FMC. The FMC site does not intend to follow WCA ragulations at all times. It will remain independent in the foreseeable future.

Any site is welcome to link to the fmc site (how could i prevent it anyway??). I could prevent linking to pictures, files etc on the site. But there is virtually non such useful content to "rip", and thus steal bandwidth 

-PKF


----------



## Johannes91 (Apr 16, 2008)

Why did you quote the whole long post when you were only replying to a couple of specific parts?



mrCage said:


> Johannes91 said:
> 
> 
> > mrCage said:
> ...


I just pointed out that saying _virtually any language_ would've been extremely naïve. You added the word _procedural_, but just as a sidenote, assuming almost all languages are procedural. I can think of several language familys/paradigms in which it would be easier to write a scrambler from scratch than to adapt an imperative/procedural one.



mrCage said:


> I never said server side javascript. I said i ignored javascript because i do not have time to get into ajax and similar.


But you did say that the scrambler needs to be server-side. And I said that Ajax wouldn't help, so not having time to get into Ajax shouldn't be a reason to ignore JavaScript...



mrCage said:


> I could prevent linking to pictures, files etc on the site.


How? (This is a sincere question, I'm interested and don't know.)


----------



## mrCage (Apr 29, 2008)

Johannes91 said:


> mrCage said:
> 
> 
> > I could prevent linking to pictures, files etc on the site.
> ...


 
I meant hot linking to be more specific. It is a standard feature of most hosting control panels. How it works is quite trivial. Only local requests are allowed. I'm not sure if this is an Apache only feature, but i have only seen that on linux/apache hosting (i think). Sorry for late reply - my forum reading is a bit random 

-Per


----------



## badmephisto (Jul 11, 2008)

and finally a python version  :
edit: I just wish so much I could get rid of the variable 'a' in the loop! I cant think of anything simple


```
from random import randrange
def scramble(length=25):
    turns=['U','D','F','B','R','L']
    vars = ["'", "2", ""]
    out=[]
    while len(out) != length:
        a=turns[randrange(0,len(turns)-1)]
        if len(out)==0 or out[len(out)-1] != a: out.append(a)
    return " ".join(map(lambda x: x+vars[randrange(0,len(vars)-1)], out))
```

*edit:* actually thats wrong, sigh! but easy fix


----------



## Johannes91 (Jul 11, 2008)

```
$ python
>>> [paste badmephisto's code here]
>>> scramble(25)
"D2 B2 F2 R2 [b]B2 F' B' F2[/b] D2 U2 R2 D' U' B2 F2 D' F2 D2 U2 R' F' U2 B2 U2 B'"
```

Edit:


badmephisto said:


> edit: I just wish so much I could get rid of the variable 'a' in the loop! I cant think of anything simple



Here's one way to get rid of it (it's still not a proper scrambler). Just add a random turn, if it's bad, remove it.

```
from random import randrange
def scramble(length=25):
    turns = "UDFBRL"
    vars = ["'", "2", ""]
    out = []
    while len(out) < length:
        out.append(turns[randrange(0, len(turns) - 1)])
        if len(out) > 1 and out[-1] == out[-2]: out.pop()
    return " ".join(map(lambda x: x + vars[randrange(0, len(vars) - 1)], out))
```


----------



## badmephisto (Jul 11, 2008)

yes i know. but the whole point was that i wanted to have a single line in that while loop 

Anyway I forgot about that little glitch, i think this will do it. But now it doesnt look that elegant 
In addition I can forget trying to make that a single line while-loop without going over like 200 characters 


```
from random import randrange
def scramble(length=25):
    turns=['U','F','R','D','B','L']
    vars = ["'", "2", ""]
    out=[]
    while len(out) != length:
        a=turns[randrange(0,len(turns)-1)]
        if len(out)==0 or (out[-1] != a and out[-1] != turns[(turns.index(a)+3)%len(turns)]): out.append(a)
    return " ".join(map(lambda x: x+vars[randrange(0,len(vars)-1)], out))
```

basically re-arranged turns list s.t. parallel faces are 3 spaces apart, and then add 3 and mod for the additional check.


----------



## Johannes91 (Jul 11, 2008)

badmephisto said:


> Anyway I forgot about that little glitch, i think this will do it.


Now it rejects R L R, but also R L, which should be fine. How I fixed it: If out is [..., _a_, _b_, _c_], reject _c_ if _b_ = _c_. Otherwise check if _b_ and _c_ are opposite each other, if they are, accept _c_ iff it's not equal to _a_.



badmephisto said:


> But now it doesnt look that elegant


One change that IMO makes it a bit more elegant is to put _a_ to the out array instead of _turns[a]_, and change them just before returning.



badmephisto said:


> basically re-arranged turns list s.t. parallel faces are 3 spaces apart, and then add 3 and mod for the additional check.


Another way is to use [U,F,R,L,B,D] ordering and check if the sum equals 5.


```
from random import randrange
def scramble(length=25):
    turns = "UFRLBD"
    vars = ["'", "2", ""]
    out = []
    while len(out) < length:
        a = randrange(0, len(turns) - 1)
        if len(out) == 0 or a != out[-1] and (len(out) == 1 or a + out[-1] != 5 or a != out[-2]): out.append(a)
    return " ".join(map(lambda x: turns[x]+vars[randrange(0,len(vars)-1)], out))
```

That's quite a mess, but works. Would probably be better to split the conditional in several elifs.


----------



## JBCM627 (Jul 11, 2008)

Hey... any help condensing this: http://www.thewonderidiot.net/timer/scramble.html would be great too, or improving efficiency as it can be slower for larger cubes...

Note the scramble procedure, which will generate more evenly distributed moves than the WCA scrambler...


----------



## badmephisto (Jul 11, 2008)

you are right Johannes. I jumped into coding way too fast without thinking about all the subtleties involved. I like the solution with sum equaling to 5, its an interesting way to get that check done.


----------



## TheCubers (Jul 18, 2008)

So.... idk php at all, can someone post this for html?


----------



## JBCM627 (Jul 18, 2008)

HTML is not a programming language, so you can't write a scrambler with it. The one I posted is in javascript, which you can put in an html file if you wish.


----------



## TheCubers (Jul 18, 2008)

JBCM627 said:


> HTML is not a programming language, so you can't write a scrambler with it. The one I posted is in javascript, which you can put in an html file if you wish.



Just Read Over it again and realized 


```
<html>
<head>
<script type="text/javascript">
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 ??)
...
...
</script>
</head>
<body>

<input type="button" onclick="makeScramble($length)" value="Display Scramble" />

</body>
</html>
```
is what i have, doesn't seem to work


----------



## mrCage (Jul 18, 2008)

Hi 

You cannot convert php serverside code into javascript that easily. But the steps should work the same nevertheless 

- Per


----------



## JBCM627 (Jul 18, 2008)

Yeah the one I was referring to is what I posted... the one at http://www.thewonderidiot.net/timer/scramble.html. I can make this into a shorter 3x3-only version if you wish...


----------



## ezh (Jul 19, 2008)

Since we're all sharing our scramble generators, here's mine, written in JavaScript:


```
function scramble(length) {
    var scramble=[], face=Math.floor(5*Math.random()), sameAxis;
    while(scramble.length < length) {
        var faceDiff = sameAxis ? (Math.random()>.5 ? 4 : 1) + Math.floor(2*Math.random()) : Math.floor(4*Math.random())+1;
        sameAxis = faceDiff == 3;
        face += faceDiff;
        scramble.push('URFDLB'.charAt(face%6) + (1>3*Math.random() ? '' : (Math.random()>.5 ? '2' : "'")));
    }
    return scramble.join(' ');
}
```


----------

