# Simple PHP scrambler

#### Johannes91

##### Member
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:
Code:
scramble = []
...
scramble.push(turns[axis].rand + variants.rand)
...
scramble.join(" ")

FWIW, here's a Haskell scrambler I wrote a while ago:
Code:
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

##### Member
Code:
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

##### Member
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:
Code:
scramble = []
...
scramble.push(turns[axis].rand + variants.rand)
...
scramble.join(" ")
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"?)

Last edited:

#### mrCage

##### Member
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

##### Member
Here's a simpler (but much less general) Haskell scrambler:
Code:
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): Code: 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'
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>

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.

Last edited:

#### mrCage

##### Member
Here's a simpler (but much less general) Haskell scrambler:
Code:
module SimpleScrambler where

import Data.List
import System.Random

getScramble :: Int -> IO String
getScramble n = liftM concat $mapM showFace =<< getFaces n where showFace x = return . ("UFRLBD" !! x :) =<< pick [" ", "' ", "2 "] getFaces :: Int -> IO [Int] getFaces = rec [] where rec acc 0 = return acc rec acc n = do z <- pick zs rec (z:acc) (n-1) where zs = case acc of (x:y:_) | x + y == 5 -> delete y$ delete x [0..5]
(x:_)                -> delete x [0..5]
[]                   -> [0..5]

pick :: [a] -> IO a
pick xs = liftM (xs !!) $randomRIO (0, length xs - 1) And a 136-byte Perl scrambler (could certainly be shortened, but I have other things to think about now): Code: perl -le 'for(0..24){do{$a=int rand 6}until$a-$a[-1]and$a+$a[-1]-5||$a-$a[-2];[email protected],$a}print join" ",map{qw<U F R L B D>[$_].(v39,2)[rand 3]}@a'
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>

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

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

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.
Tell me one PROCEDURAL common language that does not have loops and variables.
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.

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

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

##### Member
I could prevent linking to pictures, files etc on the site.
How? (This is a sincere question, I'm interested and don't know.)
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

##### Member
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

Code:
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

Last edited:

#### Johannes91

Code:
$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: 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. Code: 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)) Last edited: #### badmephisto ##### Member 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 Code: 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. Last edited: #### Johannes91 ##### Member 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. 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. 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. Code: 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 ##### Member 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 ##### Member 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 ##### Member So.... idk php at all, can someone post this for html? #### JBCM627 ##### Member 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 ##### Member 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: <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>
<body>

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

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

Last edited:

#### mrCage

##### Member
Hi

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

- Per

#### ezh

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

PHP:
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(' ');
}