Rubik's Cube Scrambles
C,129
f(){int i,n,m,r,s,t;for(i=26;i--;i<25&&printf("%c%c","URFDLB"[s%6],"'2"[r%3])){for(n=m,t=1;t;t=m*n==9)m=(r=rand()%15)/3+1;s+=m;}}
The inner loop generates a value of m
in the range 1..5
which when added to s
and taken modulo 6, ensures that no two consecutive moves are on the same side of the cube. The old value of m
is stored in n
and the test m*n==9
ensures that the value m
=3 is never generated twice in a row (so opposite faces cannot be picked twice in a row; note the order of faces in the string.)
The least significant part of r
is used to decide which suffix ('
, 2
or null) to use, taking advantage of the null character at the end of "'2"
.
The outer loop runs 26 times. The first time, U
can never be picked, so printf
is suppressed for the first iteration.
Ungolfed code in test program
The ungolfed code puts a space between each move for clarity (the golfed code does not, in order to save one byte.) Additionally the golfed code saves a semicolon by relocating the printf
within the for
bracket.
f(){
int i,n,m,r,s,t;
for(i=26;i--;){
for(n=m,t=1;t;t=m*n==9)m=(r=rand()%15)/3+1;
s+=m;
i<25&&printf("%c%c ","URFDLB"[s%6],"'2"[r%3]);
}
}
main(){
int j;
srand(time(0));
for(j=0;j<5;j++)f(), puts("");
}
Typical output
U' B D2 B' R' L F' D2 B D2 B2 R' B2 U D2 F' R U R' L B' L R2 B2 F'
U B U B F L2 D2 B' U' L B L R' D B U' D R D' B' F2 D' B D R
L D F2 B2 R' U F B' D2 L U R' L' U2 F' R F D U2 B L' B' U L2 F'
R2 B' F2 R2 L2 F' U2 L U' B' F R' D' F2 D F' L2 U2 R' D' B2 D F R2 L'
U2 F2 B2 D' F D F R L2 U' B D2 L' R D R F2 R' F2 U2 D R' D2 L F2
CJam, 47 45 bytes
This solution uses an approach that's different from any other posted so far. It takes advantage of CJam's concise list operations to generate the available move list and select one at random each iteraton. Modifiers are simply generated independently.
Try it online.
{BA^2/6,_B-?A:B-mr0=:A"UDRLFB"=3mr[L2'']=}25*
Explanation
{ "Loop...";
BA^2/ "If the two previous moves were not from the same group, ...";
6, "... then produce the available move list [0 1 2 3 4 5], ...";
_B- "... else produce the available move list [0 1 2 3 4 5] with
the second previous move removed";
?
A:B "Save the previous move as the second previous move";
- "Remove the previous move from the available move list";
mr0= "Randomly select an available move";
:A "Save this move as the previous move";
"UDRLFB"= "Map this move to its character (implicitly printed)";
3mr[L2'']= "Randomly select a modifier (implicitly printed)";
}25* "... 25 times";
Pyth, 65 66
I've never really golfed in Pyth, maybe written a program or two. This is basically @steveverrill's solution translated to Pyth. Improvement suggestions are welcome.
Update: added 1 byte to make scrambles also start with U
. Maybe the C solution is relying on undefined behavior to make it work...
=YO6V25JZK1WK=GO15=Z/+3G3=Kq9*ZJ)~YZpd+@"URFDLB"%Y6?@"'2"%G3>2%G3k
I believe this should be done with less assignments, but that would require me to modify the algorithm a lot. (Well, might try.)
Here's an explanation based on the C code:
=YO6 s = random.choice(range(6))
V25 for i in range(25):
JZ n = m
K1 t = 1
WK while t:
=GO15 r = random.choice(range(15))
=Z/+3G3 m = (r + 3) / 3
=Kq9*ZJ t = 9 == m * n
)
~YZ s += m
pd print(..., end = " ")
+ ... + ...
@"URFDLB"%Y6 "URFDLB"[s % 6]
?@"'2"%G3>2%G3k "'2"[G % 3] if 2 > G % 3 else ""