# My python one-liner scramble generator

#### qqwref

##### Member
Your code seems to make every other move an R or L turn, and the rest are never R or L turns. This does avoid canceling moves but it also provides far less possibilities than a normal scramble. The other scramblers in the thread were made to use all of the moves equally but also avoid cancellations - it's a little trickier, but see if you can make one that does that.

#### qq280833822

##### Member
1429-characters random-state 2x2 scrambler, and 1798-characters random-state pyraminx scrambler

Code:
var get2x2optscramble=function(){function o(a,c,b,d,e){if(0!=b){if(j[a]>b||k[c]>b)return!1;var h,g,f,i;for(i=0;3>i;i++)if(i!=d){h=a;g=c;for(f=0;3>f;f++)if(h=m[h][i],g=n[g][i],o(h,g,b-1,i,e))return e.push("URF".charAt(i)+" 2'".charAt(f)),!0}}else return 0==a&&0==c}function p(){p=function(){};var a,c,b,d,e;for(a=0;5040>a;a++){j[a]=-1;m[a]=[];for(c=0;3>c;c++)m[a][c]=q(a,c)}for(a=j[0]=0;7>a;a++)for(c=0;5040>c;c++)if(j[c]==a)for(b=0;3>b;b++){d=c;for(e=0;3>e;e++)d=m[d][b],0>j[d]&&(j[d]=a+1)}for(a=0;729>a;a++){k[a]=-1;n[a]=[];for(c=0;3>c;c++)n[a][c]=r(a,c)}for(a=k[0]=0;6>a;a++)for(c=0;729>c;c++)if(k[c]==a)for(b=0;3>b;b++){d=c;for(e=0;3>e;e++)d=n[d][b],0>k[d]&&(k[d]=a+1)}}function q(a,c){var b,d,e,h=a,g=[];for(b=1;7>=b;b++){d=h%b;h=(h-d)/b;for(e=b-1;e>=d;e--)g[e+1]=g[e];g[d]=7-b}0==c?l(g,1,3,2):1==c?l(g,4,5,1):2==c&&l(g,2,6,4);for(b=h=0;7>b;b++){for(e=d=0;7>e&&!(g[e]==b);e++)g[e]>b&&d++;h=h*(7-b)+d}return h}function r(a,c){var b,d,e,h=0,g=a,f=[];for(b=0;5>=b;b++)e=~~(g/3),d=g-3*e,g=e,f[b]=d,h-=d,0>h&&(h+=3);f[6]=h;0==c?l(f,1,3,2):1==c?(l(f,4,5,1),f[0]+=2,f[1]++,f[5]+=2,f[4]++):2==c&&(l(f,2,6,4),f[2]+=2,f[0]++,f[4]+=2,f[6]++);g=0;for(b=5;0<=b;b--)g=3*g+f[b]%3;return g}function l(a,c,b,d){var e=a[0];a[0]=a[c];a[c]=a[b];a[b]=a[d];a[d]=e}var j=[],k=[],m=[],n=[];return function(a){p();var c=~~(5040*Math.random()),b=~~(729*Math.random()),d=[];if(0!=c||0!=b)for(;99>a&&!o(c,b,a,-1,d);a++);return d.reverse().join(" ")}}();

//1429 chars

var getpyraoptscramble=(function(){function r(){function l(a,c){for(var e=[],j=5517840,f=0,b=0;5>b;b++){var h=k[5-b],d=~~(a/h),a=a-d*h,f=f^d,d=d<<2;e[b]=j>>d&15;h=(1<<d)-1;j=(j&h)+(j>>4&~h)}0==(f&1)?e[5]=j:(e[5]=e[4],e[4]=j);0==c&&g(e,0,3,1);1==c&&g(e,1,5,2);2==c&&g(e,0,2,4);3==c&&g(e,3,4,5);a=0;j=5517840;for(b=0;4>b;b++)d=e[b]<<2,a*=6-b,a+=j>>d&15,j-=1118480<<d;return a}function i(a,c){var e,d,f;d=0;var b=[],h=a;for(e=0;4>=e;e++)b[e]=h&1,h>>=1,d^=b[e];b[5]=d;for(e=6;9>=e;e++)f=~~(h/3),d=h-3*f,h=f,b[e]=d;0==c&&(b[6]++,3==b[6]&&(b[6]=0),g(b,0,3,1),b[1]^=1,b[3]^=1);1==c&&(b[7]++,3==b[7]&&(b[7]=0),g(b,1,5,2),b[2]^=1,b[5]^=1);2==c&&(b[8]++,3==b[8]&&(b[8]=0),g(b,0,2,4),b[0]^=1,b[2]^=1);3==c&&(b[9]++,3==b[9]&&(b[9]=0),g(b,3,4,5),b[3]^=1,b[4]^=1);h=0;for(e=9;6<=e;e--)h=3*h+b[e];for(e=4;0<=e;e--)h=2*h+b[e];return h}function g(a,c,d,f){var g=a[c];a[c]=a[d];a[d]=a[f];a[f]=g}r=function(){};var k=[1,1,1,3,12,60,360],m,a,f,d,c;for(a=0;360>a;a++){n[a]=-1;p[a]=[];for(c=0;4>c;c++)p[a][c]=l(a,c)}for(d=n[0]=0;5>d;d++)for(a=0;360>a;a++)if(n[a]==d)for(c=0;4>c;c++){f=a;for(m=0;2>m;m++)f=p[f][c],-1==n[f]&&(n[f]=d+1)}for(a=0;2592>a;a++){o[a]=-1;q[a]=[];for(c=0;4>c;c++)q[a][c]=i(a,c)}for(d=o[0]=0;5>=d;d++)for(a=0;2592>a;a++)if(o[a]==d)for(c=0;4>c;c++){f=a;for(m=0;2>m;m++)f=q[f][c],-1==o[f]&&(o[f]=d+1)}}function s(l,i,g,k,m){if(0==g)return 0==l&&0==i;if(n[l]>g||o[i]>g)return!1;for(var a=0;4>a;a++)if(a!=k)for(var f=l,d=i,c=0;2>c;c++)if(f=p[f][a],d=q[d][a],s(f,d,g-1,a,m))return m.push("ULRB".charAt(a)+["","'"][c]),!0;return!1}var n=[],o=[],p=[],q=[];return function(l){r();var i=~~(360*Math.random()),g=~~(2592*Math.random()),k=[];if(0!=i||0!=g)for(;99>l&&!s(i,g,l,-1,k);l++);k=k.reverse().join(" ")+" ";for(g=0;4>g;g++)i=~~(3*Math.random()),2>i&&(k+="lrbu".charAt(g)+["","'"][i]+" ");return k}})();

1798 chars

#### onionhoney

##### Member
Code:
for(int i=25,a,b=6,c;i;){do c=rand()%6;while(!(c-b&&(c+b!=5||c-a)));cout<<"UFLRBD"[i--,a=b,b=c]<<"'2 "[rand()%3];}
My first try with C++. 114 chars.

EDIT: tried in vain to modify the 102-char solution by saving a rand()....end up getting one more..
Code:
for(int c=0,b=6,j=25,m;j;m%6-c|c+b-5&&b-m%6&&cout<<"URFBLD"[j--,c=b,b=m%6]<<" 2'"[m/6%3]<<" ")m=rand();

Last edited:

#### qqwref

##### Member
Hey all, here's a scrambler in K Yeah, a bit silly, but under 100 characters. Can probably be optimized a ton.

Code:
,/("FRUDLB"@25#({,/1_'(0,&((x=q)|(:':t)&t:5=x+q: :':x))_x:0,x}/99?6)),'25?(" ";"' ";"2 ")
Edit: Typical output:
"U R F2 B' R2 U' D2 L2 U' L B' L2 U2 B' F U' L2 R D' B' D2 F U' R2 L' "
And you can get K from kx.com, they have a Q console and from there you can press \ to switch between Q and K. K is a lot less verbose but is missing several useful functions.

Last edited:

#### Baian Liu

##### Member
Even shorter for TI-83/84.

Code:
:ClrHome
:0→E
:7→D
:For(A,1,6
:For(B,2,14,3
:E→F
:D→E
:While D=E or D+E=7 and D=F
:randInt(1,6→D
:End
:Output(A,B,sub("URFBLD",D,1)+sub(" '2",randInt(1,3),1
:End
:End

#### qqwref

##### Member
Much better K scrambler:

Code:
,/("FRUDLB"@{#&(=':x),2_&':5=+':x}{25?6}/2#2),'25?" ","'2",'" "
Only 63 characters, by my count. I think that's pretty solid.
(I had one that was 61 before until I realized it didn't allow sequences starting with 5.)

Explanation of what it does:
Let's first dissect this weird-looking function: {#&(=':x),2_&':5=+':x}. The curly braces signify a function, and it's implied that the argument is x, so we don't need to declare it. The expression f':x for a function f basically returns the list you get from applying f to each adjacent pair of elements of x. So +':x gives us a list of sums of two adjacent elements. 5=+':x gives us a list of bits, with a 1 set in every position where the sum of two adjacent elements is equal to 5. &':5=+':x gives us another list of bits, but this time there is a 1 only when there were two sums-to-5 in a row (which in this case represents sequences like LRL or UDU). The 2_ removes the first two elements from that so we don't get problems with sequences that start with 5 or 5 0. So that part gives us a 1 for each LRL-type sequence. The part to the left of the comma, =':x, gives us another list of bits, with a 1 for each repeated number (so, a sequence like RR). The comma joins those two sequences together; and then the #& at the left returns the number of 1s we have. So this whole function ends up giving us the number of bad sequences in our potential scramble.

In the middle we have {stuff}{25?6}/2#2. 2#2 makes a list of two 2's so we have (2 2) there. So what does this thing do? Well, f g/ x (with f and g functions) applies g to x repeatedly until f of the result is zero. Now 25?6 generates a list of 25 random integers from 0 to 5, so we are generating lists of 25 random integers until they pass the first function (i.e. the result is 0). We needed that 2#2 so the function would start off giving a 1; otherwise the expression would immediately terminate. Notice that a list passes the first function if it has zero mistakes - that is, the list of faces to move is valid. So great - now we have generated a random list of 25 faces until it was valid for making a scramble out of. The list will look something like this: 0 3 2 5 3 0 3 5 ...

The rest is more straightforward. Let's call the part we looked at so far X; then we have ,/("FRUDLB"@X),'25?" ","'2",'" ". The "FRUDLB"@X just indexes our list into the string "FRUDLB" so now we have a list of 25 letters, such as "FDUBDFDB...". The " ","'2",'" " at the far right generates a list of the 3 possible suffixes (" ", "' ", and "2 ") and the 25? chooses 25 random suffixes, just like the previous use of it. Finally, the ,' joins each move letter up with one of the suffixes, and the ,/ at the beginning takes the whole list of strings and joins it together into one. Pretty tricky, but it makes sense if you analyze it.

Last edited:

#### Escher

##### Babby
Explanation of what it does:
Let's first dissect this weird-looking function: {#&(=':x),2_&':5=+':x}. The curly braces signify a function, and it's implied that the argument is x, so we don't need to declare it. The expression f':x for a function f basically returns the list you get from applying f to each adjacent pair of elements of x. So +':x gives us a list of sums of two adjacent elements. 5=+':x gives us a list of bits, with a 1 set in every position where the sum of two adjacent elements is equal to 5. &':5=+':x gives us another list of bits, but this time there is a 1 only when there were two sums-to-5 in a row (which in this case represents sequences like LRL or UDU). The 2_ removes the first two elements from that so we don't get problems with sequences that start with 5 or 5 0. So that part gives us a 1 for each LRL-type sequence. The part to the left of the comma, =':x, gives us another list of bits, with a 1 for each repeated number (so, a sequence like RR). The comma joins those two sequences together; and then the #& at the left returns the number of 1s we have. So this whole function ends up giving us the number of bad sequences in our potential scramble.

In the middle we have {stuff}{25?6}/2#2. 2#2 makes a list of two 2's so we have (2 2) there. So what does this thing do? Well, f g/ x (with f and g functions) applies g to x repeatedly until f of the result is zero. Now 25?6 generates a list of 25 random integers from 0 to 5, so we are generating lists of 25 random integers until they pass the first function (i.e. the result is 0). We needed that 2#2 so the function would start off giving a 1; otherwise the expression would immediately terminate. Notice that a list passes the first function if it has zero mistakes - that is, the list of faces to move is valid. So great - now we have generated a random list of 25 faces until it was valid for making a scramble out of. The list will look something like this: 0 3 2 5 3 0 3 5 ...

The rest is more straightforward. Let's call the part we looked at so far X; then we have ,/("FRUDLB"@X),'25?" ","'2",'" ". The "FRUDLB"@X just indexes our list into the string "FRUDLB" so now we have a list of 25 letters, such as "FDUBDFDB...". The " ","'2",'" " at the far right generates a list of the 3 possible suffixes (" ", "' ", and "2 ") and the 25? chooses 25 random suffixes, just like the previous use of it. Finally, the ,' joins each move letter up with one of the suffixes, and the ,/ at the beginning takes the whole list of strings and joins it together into one. Pretty tricky, but it makes sense if you analyze it.
I think this applies to you, too.

o_________________________o

#### Stefan

##### Member
Your explanation is about 41 times as long as the program. Can't decide whether that's good or bad.

#### qqwref

##### Member
Here's a 2x2 random-state scrambler in Q (a more verbose version of K, as above), in 593 characters:
Code:
system"S ",string 6h$.z.T e:{m:enlist();x:enlist x;do[y;t:asc each raze each(3*(til 3)except/:(first each m)div 3)+'/:\:til 3;x:raze ({y x/z}./:({x:[email protected]\:0 5 1 3 4 6 2;x[1]:(x[1]+0 2 1 0 0 1 2)mod 3;x};{[email protected]\:1 2 3 0 4 5 6};{x:[email protected]\:4 0 2 3 5 1 6;x[1]:(x[1]+2 1 0 0 1 2 0)mod 3;x})cross 1+til 3)[t]@\:'x;m:raze t,\:'m];(m;x)} w:{a:e[(til 7;7#0);ceiling y%2];b:e[x;floor y%2];$[(s:(raze a[1]~/:\:b 1)?1b)=(c:count b 0)*count a 0;0N;" "sv ("RUF"cross("";"2";"'"))(reverse b[0;s mod c]),2 1 0 5 4 3 8 7 [email protected][0;s div c]]}
scramble:{i:0;s:0N;h:(-7?7;k,(neg sum k:6?3)mod 3);while[0N~s;i+:1;s:w[h;i]];s}
I'm obviously not gonna explain this in full detail, but the general gist is that we get a random position and then try 1, 2, ... moves until we find a solution. We look for solutions of n moves by generating all positions ceiling(n/2) moves away from solved and all positions floor(n/2) moves away from our position, and then matching every pair of elements and seeing if we get any successes. This isn't the fastest possible way to do this but it seems fast enough.

Sample output:
q)scramble[]
"U2 F2 U F2 U R2 U2 F R'"

In K: 513 characters :3
Code:
."\\S ",$6h$.z.T
e:{m:,();x:,x;do[y;t:.q.asc',/'(3*(!3).q.except/:(*:'m)div 3)+'/:\:!3;x:,/({y x/z}./:,/({x:[email protected]\:.:'"0513462";x[1]:(x[1]+.:'"0210012").q.mod'3;x};{[email protected]\:.:'"1230456"};{x:[email protected]\:.:'"4023516";x[1]:(x[1]+.:'"2100120").q.mod'3;x}),/:\:1+!3)[t]@\:'x;m:,/t,\:'m];(m;x)}
w:{a:e[(!7;7#0);-_-y%2];b:e[x;_y%2];$[(s:(,/a[1]~/:\:b 1)?1b)=(c:#b 0)*#a 0;0N;" "/:(,/"RUF",/:\:("";"2";"'"))(|b[0;s .q.mod'c]),.:'"210543876"@a[0;s div c]]} scramble:{i:0;s:0N;h:(-7?7;k,(-+/k:6?3).q.mod'3);while[0N~s;i+:1;s:w[h;i]];s} Last edited: #### qqwref ##### Member 506 characters It's only 479 if you don't count the random seed part (which I didn't count in my 3x3 scrambler in K). Code: system"S ",string 6h$.z.T
e:{m:,:[-1];x:,:[x];do[y;t:!:[9]except/:(3**:'[m]div 3)+'/:\:til 3;x:raze({y x/z}./:({x:[email protected]\:0 5 1 3 4 6 2;x[1]:(x[1]+7#0 2 1 0)mod 3;x};{[email protected]\:1 2 3 0 4 5 6};{x:[email protected]\:4 0 2 3 5 1 6;x[1]:(x[1]+7#2 1 0 0)mod 3;x})cross 1 2 3)[t]@\:'x;m:,/[t,\:'m]];(m;x)}
w:{a:e[(til 7;7#0);o:_:[y%2]];b:e[x;y-o];\$[()~s:*:[a[1]inter b 1];0N;" "sv("RUF"cross("";"2";"'"))1_-1_|:[b[0]b[1]?s],2 1 0 5 4 3 8 7 [email protected][0]a[1]?s]}
scramble:{i:0;s:0N;h:(-7?7;k,(neg sum k:6?3)mod 3);while[0N~s;i+:1;s:w[h;i]];s}
Cool thing: this is actually significantly faster than the previous one, and the biggest reason is using "a[1]inter b 1" instead of "(raze a[1]~/:\:b 1)?1b". The old one would take about 10 seconds for particularly hard scrambles, but this one can do 100 scrambles in about 10 seconds.

#### Baian Liu

##### Member
python: 138
Code:
from random import randint as r;a=b=8
for x in range(25):
c=b;b=a
while (a==b)+(a+b-5)*(a==c):a=r(0,5)
print("URFBLD"[a]+" '2"[r(0,2)])
A "one-liner":
Code:
from random import randint as r;d=[r(0,5) for x in range(50)];print(''.join(["URFBLD"[[d[y] for y in range(2,50) if 1-((d[y]==d[y-1])+(d[y]+d[y-1]-4)*(d[y]==d[y-2]))][z]]+" '2"[r(0,2)] for z in range(2,27)]))

Last edited:

#### JF1zl3

##### Member
Dayum, nice. I don't know much about Python, actually virtually nothing, but it looks extremely condensed.
I think I can pick up on certain things about the code that make sense to me though, so it isn't foreign language or anything, it just seems super cool how little code is required lol.

#### JustinJ

##### Premium Member
Bump because I think this is a cool thread and I think I have a kind of cute Ruby (2.0) solution

Code:
p (1..1.0/0).lazy.map{(1..25).map{"UDLRFB"[rand 6]}.join}.find{|s|!(/(.)\1|(UDU|DUD|LRL|RLR|FBF|BFB)/=~s)}.each_char.map{|c|c+["","'","2"].sample}.join" "
Neated up a bit with explanations:

Code:
p (1..1.0/0).lazy # infinite lazy enumerator
.map { (1..25).map { "UDLRFB"[rand 6] }.join } # make each element a list of faces
.find { |s| !(/(.)\1|(UDU|DUD|LRL|RLR|FBF|BFB)/ =~ s) } # find one that doesn't duplicate moves or RLR etc
.each_char.map { |c| c + ["","'","2"].sample } # suffixes
.join " "
Not the shortest at 154 chars, I'd like to see some improvements on it though!

I also didn't see any other functional-ish solutions, although I might have missed some. I'd like to see some functional attempts by others.

I think it might be similar to this one, but I'm not familiar enough with Perl to tell.

#### Stefan

##### Member
I think it might be similar to this one, but I'm not familiar enough with Perl to tell.
It's somewhat similar, but it appends one move at a time and chops it off if it causes a violation, repeat until 25 moves are built. Those like yours started with Michael's request [post=485880]two posts later[/post].

#### JustinJ

##### Premium Member
It's somewhat similar, but it appends one move at a time and chops it off if it causes a violation, repeat until 25 moves are built. Those like yours started with Michael's request [post=485880]two posts later[/post].
Ah neat, not sure how I missed those.

#### Stefan

##### Member
not sure how I missed those.
Probably you didn't think someone other than me could be that brilliant.

#### keemy

##### Member
133
Code:
import random as l;r=l.randint;a=b=8
for x in"a"*25:
c=b;b=a;
while(a==b)+(a+b==5)*(a==c):a=r(0,5)
print"URFBLD"[a]+" '2"[r(0,2)],
Last python post had an error, this fixes it and reduces count by 5. Sorry for huge bump though.

#### Carrot

##### Member
javascript(110):
Code:
for(c=b=j=25;j;c+b-5|c-m&&b-m?document.write("URFBLD"[j--,c=b,b=m]+" 2'"[0|r()*3]+" "):r=Math.random)m=0|r()*6
instead of initialising Math.random in r before the for loop, you could just move it to the c-part of a?b:c as it was unused anyway and we are not using the random function before that.

Python(128):
Code:
import random as l;r=l.randrange;a=2
for c in"a"*25:
b=a
while(a==b)+(a+b==5)*(a==c):a=r(6)
print"URFBLD"[a]+" '2"[r(3)],;c=b
just moved a bit around in Keemy's code.

ohhh, hooray I bumped the thread :3

#### ajayd

##### Member
So code that does strange stuff like U2 U2 isn't allowed(and strange spacing)?

If not:
Code:
from random import randint as r;m,l="UDLRFB"," '2";print " ".join(m[r(0,5)]+l[r(0,2)]for i in range(25))
[\code]
106 characters

Last edited:

#### Carrot

##### Member
So code that does strange stuff like U2 U2 isn't allowed(and strange spacing)?

If not:
Code:
from random import randint as r;m,l="UDLRFB"," '2";print " ".join(m[r(0,5)]+l[r(0,2)]for i in range(25))
[\code]
106 characters[/QUOTE]

you need:
fair distribution of moves
no moves on the same face after each other
no moves of the opposite face of the previous move but only if the past two were also opposite face turns

Similar threads