3x3x3 simulator in 745 bytes of javascript

Superbump.

Just looked at this, and improved the 15-puzzle sim from the original down to 414 bytes. http://codepen.io/molarmanful/pen/OVEYEv

- No need for charCodeAt: strings can be parsed like arrays with [].
- Never use brackets with any loops/conditionals in general unless you REALLY need to.
- Sometimes, conditionals can be replaced with && or ||.
- window.onkeydown should be written as onkeydown.
- Use e.which instead e.keyCode.
- In for loops, use -- instead of ++.

Just some of the stuff I did. There's probably more that I did and more that can be done.

it says 'undefined' after some moves
 
Okay, I deleted my previous post because I finished redoing the code. But OH MY GOD! I got the 15 puzzle sim down to 372 bytes!

Demo here: http://codepen.io/molarmanful/pen/OVEYEv

I got some inspiration from the 219-byte game of Tron and used their key event handling. Did the customary golfing to minimize repetition, unnecessary code, and stuff like that. Also, I fixed the undefined error and made the puzzle scramble onload and onclick.

Code:
a=document.getElementById('a');a[w="innerHTML"]='1234\n5678\n9ABC\nDEF ';h=" ";function r(f,g){a[w]=a[w][s='substring'](0,f)+g+a[w][s](f+1)}onkeyup=d=function(e){f=(x=a[w]).indexOf(h);q=e?e.which&3:0|Math.random()*4;y=f+[-5,1,5,-1][q];if((q==2&&f<14)||(!q&&f>4))r(f,x[y]),r(y,h);if(q%2){g=x.charAt(y);if(g!="\n")r(f,g),r(y,h)}},onclick=onload=function(){for(i=99;i--;)d()}
 
Last edited:
279 bytes :D http://codepen.io/anon/pen/LVBRbX

Code:
a=document.getElementById('a');a[w="innerHTML"]='1234\n5678\n9ABC\nDEF ';r=(f,g)=>a[w]=a[w].slice(0,f)+g+a[w].slice(f+1);onkeyup=d=e=>{f=(x=a[w]).search(" ");if((z=x[y=f+[-5,1,5,-1][e?e.which&3:0|Math.random()*4]])&&z!='\n')r(f,z),r(y," ")},onclick=onload=e=>{for(i=1e4;i--;)d()}

Changes:
- Removed a lot of the complicated logic with q and f and g to check if a move is valid, and simply replaced it with a check for whether x[y] is not undefined and not \n (that is: if(x[y]&&x[y]!='\n'))
- Used z for x[y] and inlined the definition of y
- Got rid of variable q now, since we only use it once
- Got rid of variable h to save 2 bytes
- slice instead of substring, and got rid of variable s
- Changed scramble length to 1e4 (=10000) instead of 99 - it loses a byte but provides scrambles which are much closer to random state
- search instead of indexOf
- (arguments)=>{function body} syntax



EDIT: I updated an old script from this topic: http://jsfiddle.net/pq6VK/9/ The javascript is only 217 (!!) bytes.
Code:
h=[...' 123\n5674\n9AB8\nDEFC'];y=0;onkeyup=e=>d(e.keyCode%5);d=q=>{if(q==6)for(i=1e4;i--;d(0|Math.random()*5));m=h[y],h[y]=h[f=h[w=y+[-5,,1,5,-1][q]]&&h[w]!='\n'?w:y],h[y=f]=m;document.body.innerHTML=h.join("")};d(6)

Tricks include:
- the new function syntax as above
- the valid-move logic as above
- [...string] instead of string.split("")
- starting from a non-solved state (it doesn't matter, we immediately scramble anyway) to save a character on y
- making the entire body a <pre> tag using CSS so I can just use document.body.innerHTML :p
 
Last edited:
I decided to keep with the ES5 syntax for all y'all non-FF users:

Code:
a=document.getElementById('a');a[w="innerHTML"]='1234\n5678\n9ABC\nDEF ';function r(f,g){a[w]=a[w].slice(0,f)+g+a[w].slice(f+1)}onkeyup=d=function(e){f=(x=a[w]).search(" ");if((z=x[y=f+[-5,1,5,-1][e?e.which&3:0|Math.random()*4]])&&z!='\n')r(f,z),r(y," ")},onclick=function(e){for(i=1e4;i--;)d()}

295 bytes, which is still a big improvement over 372. And we're sub-300, so thanks qqwref!

One thing I like about the code is the [-5,1,5,-1][e?e.which&3:0 part, which I find pretty cool. I'm using it for sure in other projects when possible.
 
The other one is a working 15 puzzle sim too :) Should still be pretty short (240 bytes by my count) even with ES5 syntax:
Code:
h=' 123\n5674\n9AB8\nDEFC'.split("");y=0;onkeyup=function(e){d(e.keyCode%5)};d=function(q){if(q==6)for(i=1e4;i--;d(0|Math.random()*5));m=h[y],h[y]=h[f=h[w=y+[-5,,1,5,-1][q]]&&h[w]!='\n'?w:y],h[y=f]=m;document.body.innerHTML=h.join("")};d(6)

I'm kinda thinking of trying the 3x3x3 sim challenge too... hmmm
EDIT: lol, never mind, I forgot how crazy small it got XD Might still be interesting to see what you can get with a reasonable view and control scheme though...
 
OH MY GOD! I got the 15 puzzle sim down to 372 bytes!

I don't understand the excitement. If I'm not mistaken, [post=906615]we were at least down to 313[/post], including random-state scrambling (that's just the latest posted version, maybe earlier ones were even shorter). Does yours have more/better functionality?
 
Last edited:
EDIT: I updated an old script from this topic: http://jsfiddle.net/pq6VK/9/ The javascript is only 217 (!!) bytes.
Code:
h=[...' 123\n5674\n9AB8\nDEFC'];y=0;onkeyup=e=>d(e.keyCode%5);d=q=>{if(q==6)for(i=1e4;i--;d(0|Math.random()*5));m=h[y],h[y]=h[f=h[w=y+[-5,,1,5,-1][q]]&&h[w]!='\n'?w:y],h[y=f]=m;document.body.innerHTML=h.join("")};d(6)

I'm not set up to test it myself, but q==6 should be equivalent to q>5, right?

And maybe d(1e4) instead of d(6) and use that to get rid of the if?
 
Last edited:
I don't understand the excitement. If I'm not mistaken, [post=906615]we were at least down to 313[/post], including random-state scrambling (that's just the latest posted version, maybe earlier ones were even shorter). Does yours have more/better functionality?
I didn't read the previous posts, just thought, " this could be better" and edited the code.


ES5 code, with my edits (224 bytes):
Code:
h=' 123\n5674\n9AB8\nDEFC'.split("");y=0;onkeyup=function(e){d(e.which%5)};function d(q){if(q>5)for(i=1e4;i--;d(0|Math.random()*5));m=h[y],h[y]=h[f=h[w=y+[-5,,1,5,-1][q]]&&h[w]!='\n'?w:y],h[y=f]=m;a.innerHTML=h.join("")}d(6)

- Keep pre tag with ID a and call it using a.innerHTML (actually works for some reason).
- Change keyCode to which.
- Change d=function to function d so that we can eliminate the semicolon right after the closing bracket.
- Change q==6 to q>5, as Stefan suggested.

I'm working on improving the variable swap inside function d so we can eliminate variable m.
 
Last edited:
- Change 0|Math.random()*5 to new Date%5. This isn't as great, but it works.
I don't think this is valid. The date just doesn't move fast enough to be used as a random number inside such a tight loop, so you will get a lot of UUUU... moves and it won't be a decent scramble anymore.

Also - and this is a problem with my 217 too - I noticed the script now only provides scrambles when you load the scrambler, which means you can't press a key (e.g. v) to do it anymore. Oh well.

209 bytes ES5 (http://jsfiddle.net/pq6VK/14/):
Code:
h=' 123\n5674\n9AB8\nDEFC'.split("");y=0;onkeyup=function(e){d(e.which)};function d(q){m=h[y],h[y]=h[f=h[w=y+[-5,1,5,-1][q&3]]&&h[w]!='\n'?w:y],h[y=f]=m;a.innerHTML=h.join("")}for(i=1e4;i--;)d(Math.random()*4)
I moved the for loop outside of d, so we don't need to check if(q>5) anymore. And switched back to modulo 4 (and saved two characters by using q&3 inside d, which means we don't have to floor the random number).

(ES6: 187 (http://jsfiddle.net/pq6VK/17/))
Code:
h=[...' 123\n5674\n9AB8\nDEFC'];y=0;onkeyup=e=>d(e.which);d=q=>{m=h[y],h[y]=h[f=h[w=y+[-5,1,5,-1][q&3]]&&h[w]!='\n'?w:y],h[y=f]=m,a.innerHTML=h.join("")};for(i=1e4;i--;)d(Math.random()*4)
 
I noticed the script now only provides scrambles when you load the scrambler, which means you can't press a key (e.g. v) to do it anymore.

What about the F5 key? :D

Save one byte with h[w]>'\n' instead of h[w]!='\n'.

Edit: 179, by replacing &&h[w]!= with > and using the loop for onkeyup=e=>d(e.which) to save a semicolon.

Code:
h=[...' 123\n5674\n9AB8\nDEFC'];y=0;d=q=>{m=h[y],h[y]=h[f=h[w=y+[-5,1,5,-1][q&3]]>'\n'?w:y],h[y=f]=m,a.innerHTML=h.join("")};for(i=1e4;i--;onkeyup=e=>d(e.which))d(Math.random()*4)
 
Last edited:
Ah, nice :) If we're doing that, we can also change >'\n' to >' ' for 178 (since y is the space, the other piece is always 0-9A-F):
Code:
h=[...' 123\n5674\n9AB8\nDEFC'];y=0;d=q=>{m=h[y],h[y]=h[f=h[w=y+[-5,1,5,-1][q&3]]>' '?w:y],h[y=f]=m,a.innerHTML=h.join("")};for(i=1e4;i--;onkeyup=e=>d(e.which))d(Math.random()*4)
 
Ah, nice :) If we're doing that, we can also change >'\n' to >' ' for 178 (since y is the space, the other piece is always 0-9A-F)

Haha, I only considered >=' '. That's what I get for not looking at the big picture :-)

Edit: Lol. 173.

Code:
h=[...' 123\n5674\n9AB8\nDEFC'];y=0;d=q=>{h[y]=h[f=h[w=y+[-5,1,5,-1][q&3]]>' '?w:y],h[y=f]=' ',a.innerHTML=h.join("")};for(i=1e4;i--;onkeyup=e=>d(e.which))d(Math.random()*4)
 
Huh, my edits to the previous post didn't save! I saw that the date trick didn't work right after I posted and tried to edit.

ES5 code (down to 196):
Code:
onkeyup=function(e){d(e.which)};function d(q){h[y]=h[f=h[w=y+[-5,1,5,-1][q&3]=]=>' '?w:y],h[y=f]=' ',a.innerHTML=h.join("")}for(h=' 123\n5674\n9AB8\nDEFC'.split(""),y=0,i=1e4;i--;)d(Math.random()*4)

- I guess Stefan figured out how to eliminate m, so kudos to him.
- Put variable initialization in for loop, which did nothing -- but I'll keep it there anyway :P .

I think we need to shorten that string defined in variable h. No idea how to do that (or if it's even possible). Anyone have a clue?
 
Back
Top