• Welcome to the Speedsolving.com, home of the web's largest puzzle community!
    You are currently viewing our forum as a guest which gives you limited access to join discussions and access our other features.

    Registration is fast, simple and absolutely free so please, join our community of 40,000+ people from around the world today!

    If you are already a member, simply login to hide this message and begin participating in the community!

My python one-liner scramble generator

qqwref

Member
Joined
Dec 18, 2007
Messages
7,834
Location
a <script> tag near you
WCA
2006GOTT01
YouTube
Visit Channel
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
Joined
May 28, 2008
Messages
206
Location
China
WCA
2008CHEN27
1429-characters random-state 2x2 scrambler, and 1798-characters random-state pyraminx scrambler :p

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
Joined
Jun 29, 2009
Messages
328
Location
Shanghai, China, China
WCA
2008SUNZ01
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. :p

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
Joined
Dec 18, 2007
Messages
7,834
Location
a <script> tag near you
WCA
2006GOTT01
YouTube
Visit Channel
Hey all, here's a scrambler in K :p 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
Joined
Feb 12, 2010
Messages
120
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
Joined
Dec 18, 2007
Messages
7,834
Location
a <script> tag near you
WCA
2006GOTT01
YouTube
Visit Channel
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
Joined
Jul 23, 2008
Messages
3,374
WCA
2008KINN01
YouTube
Visit Channel
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
 

qqwref

Member
Joined
Dec 18, 2007
Messages
7,834
Location
a <script> tag near you
WCA
2006GOTT01
YouTube
Visit Channel
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:x@\:0 5 1 3 4 6 2;x[1]:(x[1]+0 2 1 0 0 1 2)mod 3;x};{x@\:1 2 3 0 4 5 6};{x:x@\: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 6@a[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:x@\:.:'"0513462";x[1]:(x[1]+.:'"0210012").q.mod'3;x};{x@\:.:'"1230456"};{x:x@\:.:'"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
Joined
Dec 18, 2007
Messages
7,834
Location
a <script> tag near you
WCA
2006GOTT01
YouTube
Visit Channel
506 characters :p 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:x@\:0 5 1 3 4 6 2;x[1]:(x[1]+7#0 2 1 0)mod 3;x};{x@\:1 2 3 0 4 5 6};{x:x@\: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 6@a[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
Joined
Feb 12, 2010
Messages
120
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
Joined
Feb 13, 2013
Messages
349
Location
St. Charles, MO
WCA
2013REUS01
YouTube
Visit Channel
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
Joined
Oct 15, 2008
Messages
635
Location
Waterloo, Ontario, Canada
WCA
2008JAFF01
Bump because I think this is a cool thread and I think I have a kind of cute Ruby (2.0) solution :D

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.
 

keemy

Member
Joined
Dec 29, 2007
Messages
151
WCA
2006CORR01
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
Joined
Feb 9, 2009
Messages
1,910
WCA
2008ANDE02
YouTube
Visit Channel
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
Joined
Aug 16, 2012
Messages
117
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
Joined
Feb 9, 2009
Messages
1,910
WCA
2008ANDE02
YouTube
Visit Channel
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
 
Top