- Feature Articles
- CodeSOD
- Error'd
- Forums
-
Other Articles
- Random Article
- Other Series
- Alex's Soapbox
- Announcements
- Best of…
- Best of Email
- Best of the Sidebar
- Bring Your Own Code
- Coded Smorgasbord
- Mandatory Fun Day
- Off Topic
- Representative Line
- News Roundup
- Editor's Soapbox
- Software on the Rocks
- Souvenir Potpourri
- Sponsor Post
- Tales from the Interview
- The Daily WTF: Live
- Virtudyne
Admin
private static int[] moves = new int[] { { 1, 3 }, { 0, 2, 4 }, { 1, 5 }, { 0, 4, 6 }, { 1, 3, 5, 7 }, { 2, 4, 8}, { 3, 7 }, { 4, 6, 8 }, { 5, 7 } };
private static int[] solve(int[] board) {
Random rand=new Random();
}
Admin
In pseudocode:
Admin
Thus many problems have no efficient solution.
Admin
I have to wonder why this kind of programming "problem" is still included in computer programming courses. I looked through the course descriptions for a local university (University of Hawaii) recently and it mentions that students will learn sorting and linked-list algorithms. What the hell ? At what job would you ever have to do that? How about using real-world, practical examples in class so students get a feel for what programming is really like? Aaarrrggghh!
Admin
Dr. Ian Parberry assigned this to a LARC student back in the 1993-1995 timeframe, he wrote the DOS program "GifPuz" which solved an NxN version of this on-screen. Dr. Parberry claimed that the algorithm was provably within 7x of the optimal solution.
It worked by solving first for the upper-left corner, then the 2nd from left on the top row, then the 3rd from left, etc., until it solved the top row. Then the rows and column indices were switched and the solver solved the left-most column. Now it had a (N-1)x(N-1) square to solve. It continued this way until it was 2x2 and then rotated the last few squares into place.
It was deterministic and always worked.
Admin
Here’s a solution in Scheme:
Admin
Ugly, slow, Python 3k solution:
Admin
You know, in looking at this I had an interesting idea for the hardest one:
Why not use a variant of Dijkstra's Algorithm, by representing moves as edges and states as vertices?
Admin
Admin
Admin
Weighing in at .5Kb, in non-golfed, idiomatic Perl:
Admin
[quote user="ysth"][quote user="EngleBart"] [quote user="Go Figure"][quote user="Buzzard"]I should send the requirements to our Indian outsourcing team... Those fuckers write ( read cut 'n paste ) beautiful solutions and get it right first time!!!!!!!!!!!![/quote] Another racist pig scared for his pathetic job[/quote]To be fair, s/he was not speaking of generic Indians, but specifically of an Indian outsourcing team s/he has experience with. So you can't necessarily conclude racism.[/quote]
If there hadn't been racism, there wouldn't have been any need to mention that the team was Indian.
Admin
Eh, I'm missing some subtle sarcasm here. Yes? Please?
Aside from the fact that there are plenty of jobs where you might have to understand and even implement that sort of code -- not everyone has enough space to have libraries to fall back on.
And ignoring that fact that questions like that form the backbone of many technical interviews.
The basic fact is that software engineers should understand how all the basics work even if they never need to use them.
Next you'll be saying that people shouldn't worry about memory allocation and cleaning up afterwards because it can all be done for you ...
Admin
No, he thought 'used' is written 'just', used as some people think 'should've' is written 'should of'.
Admin
I have found an elegant solution which solves this problem in less than polynomial time but this box is too small to write it down.
Admin
An dirty, yet surprisingly fast VBScript implementation
input="1,X,2,5,6,3,4,7,8" Dim board(3,3)
init() print()
tries=0 done=False
While Not done 'Find Empty Square - 'X' For i=1 To 3 For j=1 To 3 If board(i,j)="X" Then open=i&","&j WScript.Echo "Open Spot= "& open End If Next Next
mover=getNeighbor() WScript.Echo "Move Spot= " & mover
swap() print()
If board(1,1)="1" And board(1,2)="2" And board(1,3)="3" And board(2,1)="4" And board(2,2)="5" And board(2,3)="6" And board(3,1)="7" And board(3,2)="8" Then WScript.Echo "Solution Found in " &tries+1& " moves" done=True print() End If
tries=tries+1 If tries >= 1000 Then WScript.Echo "No Solution Found, Exiting" done=True End If Wend
Function swap() a1=Left(open,1) a2=Right(open,1) b1=Left(mover,1) b2=Right(mover,1) 'WScript.Echo a1,a2,b1,b2 temp1=board(a1,a2) temp2=board(b1,b2) board(a1,a2)=temp2 board(b1,b2)=temp1 End Function
Function init() count=1 For i=1 To 3 For j=1 To 3 temp=Mid(input,count,1) board(i,j)=temp count=count+2 Next Next End Function
Function print() WScript.Echo "======" WScript.Echo board(1,1) &"|"& board(1,2) &"|"& board(1,3) WScript.Echo "======" WScript.Echo board(2,1) &"|"& board(2,2) &"|"& board(2,3) WScript.Echo "======" WScript.Echo board(3,1) &"|"& board(3,2) &"|"& board(3,3) WScript.Echo "======" end Function
Function getNeighbor() Randomize n=Rnd() * 1000 Select Case open Case "1,1" If board(1,2) <> "2" then getNeighbor="1,2" Else getNeighbor="2,1" End If
End Select End Function
Admin
One would expect that with such name you would use C64 BASIC. So no CLS, but PRINT "shift+home" to clear screen and semicolon instead of comma in the INPUT line.
Admin
Hey, could someone post a solution to this problem in Ada? I'm working on a special project to write games for legacy systems. Oh, and it needs to be thread-safe and multi-user because the specs call for collaborative games. Is there an Erlang mod for Ada?
:)
Admin
A compact Python solution below. Input is a list of 8 integers and a '_'. The program will go into an infinite loop if the solution is unsolvable for any reason (e.g. being in an unsolvable configuration or having an invalid set of components in the input)
import random def s(b): def w(m):b[m[0]],b[m[1]]=b[m[1]],b[m[0]] while b!=[1,2,3,4,5,6,7,8,'_']:w([[0,1],[1,2],[3,4],[4,5],[6,7],[7,8],[0,3],[1,4],[2,5],[3,6],[4,7],[5,8]][random.randint(0,11)]) return b
The above solution takes up 219 bytes. (Bytes of Python source code, not binary)
Addendum (2009-09-04 14:02): Also, to visualize the above (although this will probably cause the script to take forever to converge), use:
import random def s(b): def w(m):b[m[0]],b[m[1]]=b[m[1]],b[m[0]] while b!=[1,2,3,4,5,6,7,8,'_']: print('',b[0:3],'\n',b[3:6],'\n',b[6:9],'\n') w([[0,1],[1,2],[3,4],[4,5],[6,7],[7,8],[0,3],[1,4],[2,5],[3,6],[4,7],[5,8]][random.randint(0,11)]) return b
Addendum (2009-09-04 14:04): Now, with whitespace!
Addendum (2009-09-04 14:27): Whee, under 200 bytes (194):
Admin
It's not NP-complete, since it's not a decision problem. Maybe you mean NP-hard.
Admin
C++ solution to the 'Difficult' problem using Dijkstra's Algorithm
Admin
Whoops, my solution will claim that there's no solution if the start and end states are the same since path.len would be 0. Insert a check to compare them in main() where appropriate. Also, remove the parameters to main() - they're an accidental leftover from the original use of this code (finding paths on graphs of weighted edges between string vertices).
Admin
I was pretty sure you were wrong about all starting solutions being OK. So I checked with Wikipedia: "A simple parity argument shows that half of the starting positions for the n-puzzle are impossible to resolve, no matter how many moves are made. This is done by considering a function of the tile configuration that is invariant under any valid move, and then using this to partition the space of all possible labeled states into two equivalence classes of reachable and unreachable states." (http://en.wikipedia.org/wiki/Fifteen_puzzle)
However, if you allow the final order to be either the normal left-to-right or right to left, I think the other starting positions all go that way.
Admin
http://cplus.about.com/od/programmingchallenges/a/challenge16.htm
Programming Challenge 16 was to solve 1000 Puzzles (4x4) You'll find 2 solutions at the bottom of the page...
My A* Program didn't do much for me, so i skipped it...
Admin
Scala. You can specify an arbitrary end position, too. Finds a shortest path.
Admin
Frankly, I'd far rather hire somebody who thinks this way (algorithms, Dijkstra, representation) than somebody who churns out an insta-solution in lingo-of-choice.
Sadly, that's not the way the powers that be hire, these days. If indeed it ever was.
Admin
This sort of crap is designed for supercilious interviewers who already know the two or three best answers, and get warm fuzzy feelings when you (the interviewer) get them slightly wrong. Many college professors also fall into this category.
Your mistaken lemma, however, is to assume, simply because a college student will never need to write their own sort or linked-list algorithm, that the exercise will not help them learn what programming is "really like."
Whatever that is.
I'd posit that, if you've not gone through the pain of writing your own quicksort in language of choice (and the particular algorithm in question is irrelevant and amenable to substitution), then you're gonna be a thoroughly useless pain in the ass when you program "as it is really like."
Think of it (loosely) as Civil Engineering. Nobody who builds a bridge really needs to know what a catenary is, because there are tools to solve that problem for you.
On the other hand, it would be quite nice to know when the program gets it wrong.
Admin
Admin
Actually, half of all the combinations are impossible to solve. Here's a short "proof" of why (we learnt this is undegrad Algebra course):
Start with your random configuration, and move the empty box, "9", to the bottom right - it's original location. This is always possible, and it just simplifies the proof.
First note that every move you make is a "transpose" - where you swap the position of "9" and some other number. So a possible configuration is simply a sequence of transpositions.
Now, since in the final and starting configuration, "9" is in the same place, this means we must have an EVEN number of "transposition". Because every time we move "9" up, we must eventually move "9" down again and vice verse.
Now for the maths. With out starting configuration, we calculate the "permutation" that generates this configuration from the original one. This basically means we look at the function which maps the original numbers to the new numbers.
And a permutation can be either odd or even. An even permutation basically can be decomposed to an even number of tranpositions. Hence, we have the requirement that the permutation of the random configuration must be even for the 9 box to be possible.
Hope that made sense :)
something like that...
Admin
Admin
Since Hertzfeld's program probably won't run on modern Macs, and certainly touch anything Microsoft, I decided to spend some of my weekend writing a Windows version of his game.
I went for 4x4, as the original did, but I don't have a 128k to find out what happens when you win. Also, the PE file format is sadly limiting, so the result is an enormous 1184 bytes, but it's 753 compressed!
http://erato.co.uk/Puzzle.zip
Have fun!
Admin
FYI: The original story about the Puzzle desk accessory is found here:
http://www.folklore.org/StoryView.py?project=Macintosh&story=Puzzle.txt
About desk accessories in general: http://www.folklore.org/StoryView.py?project=Macintosh&story=Desk_Ornaments.txt&topic=User%20Interface
The history about that is quite fun to read.
Admin
I used perl to hack the code for generating all possible solutions. Basically work backwards from the solution:
Admin
Hmmm it did not like my second half of the solution (I kept getting spam messages)... Basically make a html page with all of the solutions cached. Then the javascript just looks up the solution and draws it on the page. It was especially wtf'ed as :
Admin
It's look that's it couldn't be solved as random, in a short period of time, somebody have a similar behaviour ? Or perhaps I WTF ^^, see code in C#:
Admin
A bruteforce solution in JavaScript. I know it doesn't meet the specification - it doesn't exactly accept input, instead it randomizes the puzzle itself... I just wanted to make certain that the input is solveable.
Admin
Wait a minute. Everyone knows the puzzle application that shipped with the mac had fifteen pieces on a 4x4 grid. What gives? I mean, anonymization is one thing, but it's not like this is exactly a detail you can change. I can see the point of changing it for the problem (since the 4x4 version has unsolvable starting positions), but you also changed it in the description of the real puzzle desk accessory.
Admin
Would you say that is a plethora of WTFs?
Three Amigos dance
Admin
175 bytes of Python. I expect it's a one-liner in APL variants. Usage example:
Admin
Pope, you will die like dogs... :) I vote for a lurch or a stun... but then have we agreed on what the plural actually is? WTFs or WsTF?
Admin
Down to 164 bytes.
Admin
You remember correctly, in a way. I'd have to dig it out but this is a basic, classic CIS-101 type of problem (where did YOU go to school?) in Topology, and it's easily demonstrated that any configuration shows a kind of "handedness" -- "even or odd" at any point, and it is impossible by simple movement to change the handedness of a configuration. Any even handed config cannot become an odd handed config (and vice-versa) without removing a piece from the system to change the config's handedness directly. Simple sliding movements won't transpose that.
Admin
Hey!!
Hey!!
No fair corrupting the data pool!!
You can't ASK the question and then get a valid answer. Observational interaction kicks in and skews the result.
And, as proof that computers don't have AI yet ("Skynet")... here is what would be a proper solution to the puzzle, were the computer to have true AI:
/* Solves the puzzle in the fastest possible time *
#include <stdio.h>
#include <stdlib.h>
int main(char argc, char**argv){
}
Admin
Java Solution (depth first)
http://pastebin.be/20950
Admin
How do you know he's not racially Indian himself?
He should be scared, everyday we are getting undercut and outsourced, maybe you would have the same opinion if it happened to you?
Marxist twat.
Admin
HTML/Javascript. Firefox only. Zoom in to 10x for a larger puzzle.
<a rel="nofollow" href="data:text/html,<title>Sliders</title><style>%23r{border:inset 2px;height:108;width:108;float:left;padding:1;position:relative;cursor:inherit}.s{border:outset 2px;background:buttonface;text-align:center;line-height:30px;height:30;width:30;float:left;margin:1}</style><body onload="with(m=String.prototype){m.b=substring;m.i=indexOf;m.M=match;m.r=replace;m.s=split}with(m=Array.prototype){m.c=concat;m.j=join;m.p=push}(m=Event.prototype).p=m.preventDefault;D=document;B=D.body;E=function(e){return D.getElementById(e)};M=Math;Ma=M.abs;Mf=M.floor;Mr=M.random;MR=M.round;W=window;pI=parseInt;T=true;F=!T;sT=setTimeout;u=typeof a;ab='absolute';im='image/png';na='not-allowed';co='cover';=function(e){return D.createElement(e)};J=function(){try{l=[0,0,0,0,0,0,0,0,i=0%5D;while(T)l[MR(((s=E('s'+i)).offsetTop3+s.offsetLeft)/36)%5D=++i}catch(e){}};K=function(s){if(typeof d!=u)return F;if(s instanceof Event)s=this;if(typeof s!='object'||!(s instanceof HTMLDivElement))s=E('s'+s);J();l=l.j('');j=l.i(0);k=l.i(s.id.b(1)1+1);x=k%253;y=Mf(k/3);X=j%253;Y=Mf(j/3);if(Ma(X-x)+Ma(Y-y)>1){s.style.cursor=na;return F}m=U%3Fna:(X-x>0%3F'e':X-x<0%3F'w':Y-y>0%3F's':'n')+'-resize';if((s=s.style).cursor!=m)s.cursor=m;return T};A=function(){B.onmousemove=B.onmouseup=B.style.cursor='';if(typeof d==u)return;if(Ma(d.offsetLeft-X)+Ma(d.offsetTop-Y)!=36){s.left=X-1;s.top=Y-1}else O.value+=(O.value.i('\n')<0%3F'\n':' ')+(d.id.b(1)1+1);d=void(0);G()};G=function(){J();for(j=x=0;j<l.length-1;++j)if(l[j%5D!=j+1){++x;for(k=j+1;k<l.length;++k)if(l[k%5D==j+1){m=l[j%5D;l[j%5D=l[k%5D;l[k%5D=m;k=l.length}}J();j=l.j('').i(0);y=j%253+(j-j%253)/3;n=x==0%3F'green':((x+y)%252>0)%3F'red':'yellow';if((s=b.style).borderColor!=n)s.borderColor=n;return n!='red'};Q=function(j){if(typeof j=='string')j=j.s(/[ ,%5D+/);if(typeof j!=u&&j.length==1)j=j[0%5D.s('');for(k=0;typeof j==u||k<j.length;++k){s=E('s'+(typeof j==u%3Fk:j[k%5D-1));if(s!=null){(s=s.style).left=k%25336+1;s.top=(k-k%253)12+1}else if(typeof j==u)j=[%5D}J();O.value=l.j('')+(G()%3F'':'\nUnsolveable')};S=function(){a=arguments;J();if(typeof U==u||!U){O.value=l.j('');U=T;z=[%5D;o=[%5D;for(n=D.forms[j=0%5D.elements;j<n.length;++j)n[j%5D.disabled=n[j%5D.type.i('x')<0}m=T;for(j=0;j<l.length;m=!l[++j%5D||l[j%5D==j+1);if(m)O.value+=(O.value.M(/[\n%5D$/)==null%3F'\n':'')+'Done in '+z.length+' moves';if(m||a.length&&a[0%5D==F){U=F;for(n=D.forms[j=0%5D.elements;j<n.length;n[j++%5D.disabled='');G();return}if(o.length+z.length==0)if(a.length)o=a[0%5D;else return H(l.j(''),S);if(o.length){z.p(n=o.shift());O.value+=(O.value.M(/[\n %5D$/)==null%3F' ':'')+n;I(n-1,S)}else G()};H=function(){a=arguments;if(a.length==2){L=a[N=0%5D;V=[[[%5D,a[0%5D%5D%5D;P={};C=a[1%5D}f=new Date();while(V.length&&(new Date())-f<100){m=V.shift();if(typeof P[m[1%5D%5D==u){++N;P[m[1%5D%5D=T;j=m[1%5D.i(n=0);l=m[1%5D.s('');for(k=T;n<l.lengthk;++n)k=l[n%5D==0||l[n%5D==n+1;if(k){O.value=L+'\n';V=[%5D;C(m[0%5D);return}else{if(j>2)V.p([m[0%5D.c(l[j-3%5D),m[1%5D.r(l[j%5D,l[j-3%5D).r(l[j-3%5D,l[j%5D)%5D);if(j<6)V.p([m[0%5D.c(l[j+3%5D),m[1%5D.r(l[j+3%5D,l[j%5D).r(l[j%5D,l[j+3%5D)%5D);if(j%253>0)V.p([m[0%5D.c(l[j-1%5D),m[1%5D.r(l[j%5D,l[j-1%5D).r(l[j-1%5D,l[j%5D)%5D);if(j%253<2)V.p([m[0%5D.c(l[j+1%5D),m[1%5D.r(l[j+1%5D,l[j%5D).r(l[j%5D,l[j+1%5D)%5D)}}}O.value=L+((V.length>0&&sT(H,1)||C(F))%3F'\nTrying solutions of '+V[0%5D[0%5D.length+' moves':'\nNo solution exists.')+'\nPermutations: '+N};I=function(n,k){if(typeof d==u||!d){K(n);d=E('s'+n);C=k;p=X-x;q=Y-y;r=pI((Z=d.style).left)+36p;t=pI(Z.top)+36q}if(pI(Z.left)!=r||pI(Z.top)!=t){Z.left=pI(Z.left)+p;Z.top=pI(Z.top)+q;sT(I,10)}else{d=void(0);sT(C,10)}};O=D.forms[j=0%5D.output;U=F;b=E('r');for(s=D.getElementsByClassName('s');j<s.length;++j){s[j%5D.onmousemove=K;s[j%5D.onmousedown=function(e){if(typeof d!=u||K(this)==F)return F;d=this;B.style.cursor=d.style.cursor='none';x=e.clientX(X-x);X=d.offsetLeft;y=e.clientY(Y-y);Y=d.offsetTop;B.onmousemove=function(e){if(e.buttons<1||typeof d==u)return A();j=x!=0%3Fe.clientX-Ma(x):0;k=y!=0%3Fe.clientY-Ma(y):0;if(Ma(j=jx>0)>36)j=Ma(j)/j36;if(Ma(k=ky>0)>36)k=Ma(k)/k36;(s=d.style).left=X+j-1;s.top=Y+k-1;if(Ma(j)+Ma(k)>=36)A()};B.onmouseup=A;J();if(O.value.i('D')>0)O.value=l.j('');return false};s[j%5D.style.position=ab;s[j%5D.id='s'+j}Q()"ondragover="if((e=event).dataTransfer.types.contains('Files'))e.p()"ondrop="if(!((j=(f=(e=event).dataTransfer).types).contains('application/x-moz-file')||j.contains('text/uri-list')))return;i=('img');if((k=f.files).length){g=k[0%5D;if(!g.type.M(/image./))return;e.p();R=new FileReader();R.onload=(function(i){return function(e){i.src=e.target.result;i.onload=function(e){i=e.target;if(i.height<i.width)i.width=i.naturalWidth/i.naturalHeight(i.height=440);else i.height=i.naturalHeight/i.naturalWidth(i.width=440);c=('canvas');c.width=M.min(w=i.width,h=i.height);c.height=M.min(w,h);x=c.getContext('2d');x.drawImage(i,w>h%3F(h-w)/2:0,h>w%3F(w-h)/2:0,w,h);n=('canvas');n.width=n.height=120;for(j=0;j<8;++j){n.getContext('2d').putImageData(x.getImageData(16+j%253144,16+(j-j%253)48,120,120),0,0);x.clearRect(8+j%253144,8+(j-j%253)48,136,136);s=E('s'+j);(k=s.style).backgroundImage='url('+n.toDataURL(im)+')';k.backgroundSize=co;k.backgroundPosition=s.innerHTML=''}(k=b.style).backgroundImage='url('+c.toDataURL(im)+')';k.backgroundSize=co;k.backgroundPosition='';sT(G,1)}}})(i);R.readAsDataURL(g)}else{e.p();i.src=f.getData('text/uri-list');i.onload=function(e){i=e.target;(s=b.style).backgroundImage='url('+i.src+')';s.backgroundSize=co;v=w=j=0;if(i.width>i.height){v=MR(55-55/i.heighti.width);i.width=(i.height=110)/i.naturalHeighti.naturalWidth}else{w=MR(55-55/i.widthi.height);i.height=(i.width=110)/i.naturalWidthi.naturalHeight}for(console.log(s.backgroundPosition=v+'px '+w+'px');j<8;++j){s=E('s'+j);(k=s.style).backgroundImage='url('+i.src+')';console.log(k.backgroundSize=i.width+'px '+i.height+'px');console.log(k.backgroundPosition=v-4-j%25336+'px '+(w-4-(j-j%253)12)+'px');s.innerHTML='';if(E('h'+j)==null){m=_('div');(k=m.style).background='white';k.position=ab;k.display='block';k.height=k.width=34;k.left=2+j%25336;k.top=2+(j-j%253)12;k.zIndex=0;m.id='h'+j;(n=s.parentNode).insertBefore(m,n.firstChild)}}};if(i.complete){i.onload({target:i});i.onload=null}}">
<form><input type=button value=Scramble onclick="l=[%5D;n=[0,1,2,3,4,5,6,7,8%5D;while(n.length>0)l.p(n.splice(Mf(Mr()*n.length),1)[0%5D);Q(l);while(!G()){j=Mf(Mr()*9);k=Mf(Mr()*8);m=l[j%5D;l[j%5D=l[k+=k>j%5D;l[k%5D=m;Q(l)}"> <input type=button value=Set... onclick="J();Q(prompt('Enter %23s (the solved state is 123456780)',l.j('')))"> <input type=button value=Solve onclick=S()>
<textarea name=output rows=7 style=width:100%25 readonly>" target="blank" title="data:text/html,<title>Sliders</title><style>%23r{border:inset 2px;height:108;width:108;float:left;padding:1;position:relative;cursor:inherit}.s{border:outset 2px;background:buttonface;text-align:center;line-height:30px;height:30;width:30;float:left;margin:1}</style><body onload="with(m=String.prototype){m.b=substring;m.i=indexOf;m.M=match;m.r=replace;m.s=split}with(m=Array.prototype){m.c=concat;m.j=join;m.p=push}(m=Event.prototype).p=m.preventDefault;D=document;B=D.body;E=function(e){return D.getElementById(e)};M=Math;Ma=M.abs;Mf=M.floor;Mr=M.random;MR=M.round;W=window;pI=parseInt;T=true;F=!T;sT=setTimeout;u=typeof a;ab='absolute';im='image/png';na='not-allowed';co='cover';=function(e){return D.createElement(e)};J=function(){try{l=[0,0,0,0,0,0,0,0,i=0%5D;while(T)l[MR(((s=E('s'+i)).offsetTop3+s.offsetLeft)/36)%5D=++i}catch(e){}};K=function(s){if(typeof d!=u)return F;if(s instanceof Event)s=this;if(typeof s!='object'||!(s instanceof HTMLDivElement))s=E('s'+s);J();l=l.j('');j=l.i(0);k=l.i(s.id.b(1)1+1);x=k%253;y=Mf(k/3);X=j%253;Y=Mf(j/3);if(Ma(X-x)+Ma(Y-y)>1){s.style.cursor=na;return F}m=U%3Fna:(X-x>0%3F'e':X-x<0%3F'w':Y-y>0%3F's':'n')+'-resize';if((s=s.style).cursor!=m)s.cursor=m;return T};A=function(){B.onmousemove=B.onmouseup=B.style.cursor='';if(typeof d==u)return;if(Ma(d.offsetLeft-X)+Ma(d.offsetTop-Y)!=36){s.left=X-1;s.top=Y-1}else O.value+=(O.value.i('\n')<0%3F'\n':' ')+(d.id.b(1)1+1);d=void(0);G()};G=function(){J();for(j=x=0;j<l.length-1;++j)if(l[j%5D!=j+1){++x;for(k=j+1;k<l.length;++k)if(l[k%5D==j+1){m=l[j%5D;l[j%5D=l[k%5D;l[k%5D=m;k=l.length}}J();j=l.j('').i(0);y=j%253+(j-j%253)/3;n=x==0%3F'green':((x+y)%252>0)%3F'red':'yellow';if((s=b.style).borderColor!=n)s.borderColor=n;return n!='red'};Q=function(j){if(typeof j=='string')j=j.s(/[ ,%5D+/);if(typeof j!=u&&j.length==1)j=j[0%5D.s('');for(k=0;typeof j==u||k<j.length;++k){s=E('s'+(typeof j==u%3Fk:j[k%5D-1));if(s!=null){(s=s.style).left=k%25336+1;s.top=(k-k%253)12+1}else if(typeof j==u)j=[%5D}J();O.value=l.j('')+(G()%3F'':'\nUnsolveable')};S=function(){a=arguments;J();if(typeof U==u||!U){O.value=l.j('');U=T;z=[%5D;o=[%5D;for(n=D.forms[j=0%5D.elements;j<n.length;++j)n[j%5D.disabled=n[j%5D.type.i('x')<0}m=T;for(j=0;j<l.length;m=!l[++j%5D||l[j%5D==j+1);if(m)O.value+=(O.value.M(/[\n%5D$/)==null%3F'\n':'')+'Done in '+z.length+' moves';if(m||a.length&&a[0%5D==F){U=F;for(n=D.forms[j=0%5D.elements;j<n.length;n[j++%5D.disabled='');G();return}if(o.length+z.length==0)if(a.length)o=a[0%5D;else return H(l.j(''),S);if(o.length){z.p(n=o.shift());O.value+=(O.value.M(/[\n %5D$/)==null%3F' ':'')+n;I(n-1,S)}else G()};H=function(){a=arguments;if(a.length==2){L=a[N=0%5D;V=[[[%5D,a[0%5D%5D%5D;P={};C=a[1%5D}f=new Date();while(V.length&&(new Date())-f<100){m=V.shift();if(typeof P[m[1%5D%5D==u){++N;P[m[1%5D%5D=T;j=m[1%5D.i(n=0);l=m[1%5D.s('');for(k=T;n<l.lengthk;++n)k=l[n%5D==0||l[n%5D==n+1;if(k){O.value=L+'\n';V=[%5D;C(m[0%5D);return}else{if(j>2)V.p([m[0%5D.c(l[j-3%5D),m[1%5D.r(l[j%5D,l[j-3%5D).r(l[j-3%5D,l[j%5D)%5D);if(j<6)V.p([m[0%5D.c(l[j+3%5D),m[1%5D.r(l[j+3%5D,l[j%5D).r(l[j%5D,l[j+3%5D)%5D);if(j%253>0)V.p([m[0%5D.c(l[j-1%5D),m[1%5D.r(l[j%5D,l[j-1%5D).r(l[j-1%5D,l[j%5D)%5D);if(j%253<2)V.p([m[0%5D.c(l[j+1%5D),m[1%5D.r(l[j+1%5D,l[j%5D).r(l[j%5D,l[j+1%5D)%5D)}}}O.value=L+((V.length>0&&sT(H,1)||C(F))%3F'\nTrying solutions of '+V[0%5D[0%5D.length+' moves':'\nNo solution exists.')+'\nPermutations: '+N};I=function(n,k){if(typeof d==u||!d){K(n);d=E('s'+n);C=k;p=X-x;q=Y-y;r=pI((Z=d.style).left)+36p;t=pI(Z.top)+36q}if(pI(Z.left)!=r||pI(Z.top)!=t){Z.left=pI(Z.left)+p;Z.top=pI(Z.top)+q;sT(I,10)}else{d=void(0);sT(C,10)}};O=D.forms[j=0%5D.output;U=F;b=E('r');for(s=D.getElementsByClassName('s');j<s.length;++j){s[j%5D.onmousemove=K;s[j%5D.onmousedown=function(e){if(typeof d!=u||K(this)==F)return F;d=this;B.style.cursor=d.style.cursor='none';x=e.clientX(X-x);X=d.offsetLeft;y=e.clientY(Y-y);Y=d.offsetTop;B.onmousemove=function(e){if(e.buttons<1||typeof d==u)return A();j=x!=0%3Fe.clientX-Ma(x):0;k=y!=0%3Fe.clientY-Ma(y):0;if(Ma(j=jx>0)>36)j=Ma(j)/j36;if(Ma(k=ky>0)>36)k=Ma(k)/k36;(s=d.style).left=X+j-1;s.top=Y+k-1;if(Ma(j)+Ma(k)>=36)A()};B.onmouseup=A;J();if(O.value.i('D')>0)O.value=l.j('');return false};s[j%5D.style.position=ab;s[j%5D.id='s'+j}Q()"ondragover="if((e=event).dataTransfer.types.contains('Files'))e.p()"ondrop="if(!((j=(f=(e=event).dataTransfer).types).contains('application/x-moz-file')||j.contains('text/uri-list')))return;i=_('img');if((k=f.files).length){g=k[0%5D;if(!g.type.M(/image./))return;e.p();R=new FileReader();R.onload=(function(i){return function(e){i.src=e.target.result;i.onload=function(e){i=e.target;if(i.height<i.width)i.width=i.naturalWidth/i.naturalHeight(i.height=440);else i.height=i.naturalHeight/i.naturalWidth(i.width=440);c=('canvas');c.width=M.min(w=i.width,h=i.height);c.height=M.min(w,h);x=c.getContext('2d');x.drawImage(i,w>h%3F(h-w)/2:0,h>w%3F(w-h)/2:0,w,h);n=('canvas');n.width=n.height=120;for(j=0;j<8;++j){n.getContext('2d').putImageData(x.getImageData(16+j%253144,16+(j-j%253)48,120,120),0,0);x.clearRect(8+j%253144,8+(j-j%253)48,136,136);s=E('s'+j);(k=s.style).backgroundImage='url('+n.toDataURL(im)+')';k.backgroundSize=co;k.backgroundPosition=s.innerHTML=''}(k=b.style).backgroundImage='url('+c.toDataURL(im)+')';k.backgroundSize=co;k.backgroundPosition='';sT(G,1)}}})(i);R.readAsDataURL(g)}else{e.p();i.src=f.getData('text/uri-list');i.onload=function(e){i=e.target;(s=b.style).backgroundImage='url('+i.src+')';s.backgroundSize=co;v=w=j=0;if(i.width>i.height){v=MR(55-55/i.heighti.width);i.width=(i.height=110)/i.naturalHeighti.naturalWidth}else{w=MR(55-55/i.widthi.height);i.height=(i.width=110)/i.naturalWidthi.naturalHeight}for(console.log(s.backgroundPosition=v+'px '+w+'px');j<8;++j){s=E('s'+j);(k=s.style).backgroundImage='url('+i.src+')';console.log(k.backgroundSize=i.width+'px '+i.height+'px');console.log(k.backgroundPosition=v-4-j%253*36+'px '+(w-4-(j-j%253)12)+'px');s.innerHTML='';if(E('h'+j)==null){m=_('div');(k=m.style).background='white';k.position=ab;k.display='block';k.height=k.width=34;k.left=2+j%25336;k.top=2+(j-j%253)*12;k.zIndex=0;m.id='h'+j;(n=s.parentNode).insertBefore(m,n.firstChild)}}};if(i.complete){i.onload({target:i});i.onload=null}}">
<form><input type="button" value="Scramble" onclick="l=[%5D;n=[0,1,2,3,4,5,6,7,8%5D;while(n.length>0)l.p(n.splice(Mf(Mr()*n.length),1)[0%5D);Q(l);while(!G()){j=Mf(Mr()*9);k=Mf(Mr()*8);m=l[j%5D;l[j%5D=l[k+=k>j%5D;l[k%5D=m;Q(l)}"/> <input type="button" value="Set..." onclick="J();Q(prompt('Enter %23s (the solved state is 123456780)',l.j('')))"/> <input type="button" value="Solve" onclick="S()"/><br/><textarea name="output" rows="7" style="width:100%25" readonly="">">data:...</a></p> <pre><span style="color:blue;"><html> <head> <meta</span> <span style="color:red;">http-equiv</span>=<span style="color:#8000ff;">"Content-Type"</span> <span style="color:red;">content</span>=<span style="color:#8000ff;">"text/html; charset=utf-8"</span><span style="color:blue;">> <title></span>Sliders<span style="color:blue;"></title> <style</span> <span style="color:red;">type</span>=<span style="color:#8000ff;">"text/css"</span><span style="color:blue;">></span> div#rect { border: inset 2px; height: 108px; width: 108px; float: left; padding: 1px; position: relative; cursor: inherit; } span#move { cursor: move; } div.sq { border: outset 2px; background: buttonface; text-align: center; line-height: 30px; height: 30px; width: 30px; float: left; margin: 1px; } <span style="color:blue;"></style> <p><script</span> <span style="color:red;">type</span>=<span style="color:#8000ff;">"text/javascript"</span><span style="color:blue;">></span> <span style="color:#000080;"><i>function</i></span> setup() { <span style="color:#000080;"><i>var</i></span> divs = document.getElementsByClassName(<span style="color:#808080;">"sq"</span>); <span style="color:#000080;"><i>var</i></span> loc = []; <span style="color:#000080;"><i>for</i></span> (<span style="color:#000080;"><i>var</i></span> d = <span style="color:red;">0</span>; d < divs.length; ++ d) { divs[d].onmousemove = canMove; divs[d].onmousedown = beginMove; divs[d].style.position = <span style="color:#808080;">"absolute"</span>; divs[d].id = <span style="color:#808080;">"sq"</span> + (d + <span style="color:red;">1</span>); }</p> <pre><code>moveAll(); </code></pre> <p>}</p> <p><span style="color:#000080;"><i>function</i></span> getList() { <span style="color:#000080;"><i>var</i></span> num = document.getElementsByClassName(<span style="color:#808080;">"sq"</span>).length; <span style="color:#000080;"><i>var</i></span> list = [<span style="color:red;">0</span>, <span style="color:red;">0</span>, <span style="color:red;">0</span>, <span style="color:red;">0</span>, <span style="color:red;">0</span>, <span style="color:red;">0</span>, <span style="color:red;">0</span>, <span style="color:red;">0</span>, <span style="color:red;">0</span>]; <span style="color:#000080;"><i>for</i></span> (<span style="color:#000080;"><i>var</i></span> i = <span style="color:red;">1</span>; i <= num; ++ i) { <span style="color:#000080;"><i>var</i></span> x = Math.round((document.getElementById(<span style="color:#808080;">"sq"</span> + i).offsetLeft - <span style="color:red;">2</span>) / <span style="color:red;">36</span>); <span style="color:#000080;"><i>var</i></span> y = Math.round((document.getElementById(<span style="color:#808080;">"sq"</span> + i).offsetTop - <span style="color:red;">2</span>) / <span style="color:red;">36</span>); list[y * <span style="color:red;">3</span> + x] = i; } <span style="color:#000080;"><i>return</i></span> list; }</p> <p><span style="color:#000080;"><i>function</i></span> canMove(div) { <span style="color:#000080;"><i>if</i></span> (<span style="color:#000080;"><i>typeof</i></span> window[<span style="color:#808080;">"moving"</span>] != <span style="color:#808080;">"undefined"</span>) <span style="color:#000080;"><i>return false</i></span>;</p> <pre><code><span style="color:#000080;"><i>if</i></span> (div <span style="color:#000080;"><i>instanceof</i></span> Event) div = <span style="color:#000080;"><i>this</i></span>; <span style="color:#000080;"><i>if</i></span> (<span style="color:#000080;"><i>typeof</i></span> div != <span style="color:#808080;">"object"</span> || !(div <span style="color:#000080;"><i>instanceof</i></span> HTMLDivElement)) div = document.getElementById(<span style="color:#808080;">"sq"</span> + div); <span style="color:#000080;"><i>var</i></span> list = getList(), n = Number(div.id.split(<span style="color:#808080;">"sq"</span>)[<span style="color:red;">1</span>]); <span style="color:#000080;"><i>var</i></span> w = Math.sqrt(list.length); <span style="color:#000080;"><i>for</i></span> (<span style="color:#000080;"><i>var</i></span> i = <span style="color:red;">0</span>, blank, click; i < list.length; ++ i) { <span style="color:#000080;"><i>if</i></span> (list[<i></i>i] == <span style="color:red;">0</span>) blank = i; <span style="color:#000080;"><i>else if</i></span> (list[<i></i>i] == n) click = i; } <span style="color:#000080;"><i>var</i></span> x = click % w, y = Math.floor(click / w); <span style="color:#000080;"><i>var</i></span> x2 = blank % w, y2 = Math.floor(blank / w); <span style="color:#000080;"><i>if</i></span> (Math.abs(x2 - x) + Math.abs(y2 - y) != <span style="color:red;">1</span>) { div.style.cursor = <span style="color:#808080;">"not-allowed"</span>; <span style="color:#000080;"><i>return false</i></span>; <span style="color:#008000;">//not next to the blank space</span> } <span style="color:#000080;"><i>var</i></span> cur = solve.underway ? <span style="color:#808080;">"not-allowed"</span> : ((x2 - x) > <span style="color:red;">0</span> ? <span style="color:#808080;">"e"</span> : (x2 - x) < <span style="color:red;">0</span> ? <span style="color:#808080;">"w"</span> : (y2 - y) > <span style="color:red;">0</span> ? <span style="color:#808080;">"s"</span> : <span style="color:#808080;">"n"</span>) + <span style="color:#808080;">"-resize"</span>; <span style="color:#000080;"><i>if</i></span> (div.style.cursor != cur) div.style.cursor = cur; <span style="color:#000080;"><i>return</i></span> [x, y, x2, y2]; </code></pre> <p>}</p> <p><span style="color:#000080;"><i>function</i></span> beginMove(e) { <span style="color:#000080;"><i>if</i></span> (solve.underway) <span style="color:#000080;"><i>return false</i></span>;</p> <pre><code><span style="color:#000080;"><i>var</i></span> x, y, x2, y2; [x, y, x2, y2] = canMove(<span style="color:#000080;"><i>this</i></span>); <span style="color:#000080;"><i>if</i></span> (<span style="color:#000080;"><i>typeof</i></span> x == <span style="color:#808080;">"undefined"</span>) <span style="color:#000080;"><i>return false</i></span>; document.body.style.cursor = <span style="color:#808080;">"none"</span>; document.getElementById(<span style="color:#808080;">"move"</span>).style.cursor = <span style="color:#808080;">"none"</span>; this.style.cursor = <span style="color:#808080;">"none"</span>; window[<span style="color:#808080;">"moving"</span>] = this.id; window[<span style="color:#808080;">"startX"</span>] = e.clientX * (x2 - x); window[<span style="color:#808080;">"startXo"</span>] = this.offsetLeft; window[<span style="color:#808080;">"startY"</span>] = e.clientY * (y2 - y); window[<span style="color:#808080;">"startYo"</span>] = this.offsetTop; document.body.onmousemove = midMove; document.body.onmouseup = endMove; <span style="color:#000080;"><i>if</i></span> (document.forms[<span style="color:red;">0</span>].output.value.indexOf(<span style="color:#808080;">"Done"</span>) > <span style="color:red;">0</span>) document.forms[<span style="color:red;">0</span>].output.value = getList().join(<span style="color:#808080;">""</span>); <span style="color:#000080;"><i>return false</i></span>; </code></pre> <p>}</p> <p><span style="color:#000080;"><i>function</i></span> midMove(e) { <span style="color:#000080;"><i>if</i></span> (e.buttons == <span style="color:red;">0</span> || <span style="color:#000080;"><i>typeof</i></span> window[<span style="color:#808080;">"moving"</span>] == <span style="color:#808080;">"undefined"</span>) <span style="color:#000080;"><i>return</i></span> endMove();</p> <pre><code><span style="color:#000080;"><i>var</i></span> Xo = <span style="color:red;">0</span>, Yo = <span style="color:red;">0</span>; <span style="color:#000080;"><i>if</i></span> (window[<span style="color:#808080;">"startX"</span>] != <span style="color:red;">0</span>) Xo = e.clientX - Math.abs(window[<span style="color:#808080;">"startX"</span>]); <span style="color:#000080;"><i>if</i></span> (window[<span style="color:#808080;">"startY"</span>] != <span style="color:red;">0</span>) Yo = e.clientY - Math.abs(window[<span style="color:#808080;">"startY"</span>]); <span style="color:#000080;"><i>if</i></span> (Xo * window[<span style="color:#808080;">"startX"</span>] < <span style="color:red;">0</span>) Xo = <span style="color:red;">0</span>; <span style="color:#000080;"><i>if</i></span> (Yo * window[<span style="color:#808080;">"startY"</span>] < <span style="color:red;">0</span>) Yo = <span style="color:red;">0</span>; <span style="color:#000080;"><i>var</i></span> div = document.getElementById(window[<span style="color:#808080;">"moving"</span>]); <span style="color:#000080;"><i>if</i></span> (Math.abs(Xo) > <span style="color:red;">36</span>) Xo = Math.abs(Xo) / Xo * <span style="color:red;">36</span>; <span style="color:#000080;"><i>if</i></span> (Math.abs(Yo) > <span style="color:red;">36</span>) Yo = Math.abs(Yo) / Yo * <span style="color:red;">36</span>; div.style.left = window[<span style="color:#808080;">"startXo"</span>] + Xo - <span style="color:red;">1</span> + <span style="color:#808080;">"px"</span>; div.style.top = window[<span style="color:#808080;">"startYo"</span>] + Yo - <span style="color:red;">1</span> + <span style="color:#808080;">"px"</span>; <span style="color:#000080;"><i>if</i></span> (Math.abs(Xo) + Math.abs(Yo) >= <span style="color:red;">36</span>) endMove(); </code></pre> <p>}</p> <p><span style="color:#000080;"><i>function</i></span> endMove() { document.body.onmousemove = void(<span style="color:red;">0</span>); document.body.onmouseup = void(<span style="color:red;">0</span>); document.body.style.cursor = <span style="color:#808080;">""</span>; document.getElementById(<span style="color:#808080;">"move"</span>).style.cursor = <span style="color:#808080;">""</span>;</p> <pre><code><span style="color:#000080;"><i>if</i></span> (<span style="color:#000080;"><i>typeof</i></span> window[<span style="color:#808080;">"moving"</span>] == <span style="color:#808080;">"undefined"</span>) <span style="color:#000080;"><i>return</i></span>; <span style="color:#008000;">//check move for validity</span> <span style="color:#000080;"><i>var</i></span> div = document.getElementById(window[<span style="color:#808080;">"moving"</span>]); <span style="color:#000080;"><i>var</i></span> Xo = div.offsetLeft - window[<span style="color:#808080;">"startXo"</span>]; <span style="color:#000080;"><i>var</i></span> Yo = div.offsetTop - window[<span style="color:#808080;">"startYo"</span>]; <span style="color:#000080;"><i>if</i></span> (Math.abs(Xo) + Math.abs(Yo) != <span style="color:red;">36</span>) { div.style.left = window[<span style="color:#808080;">"startXo"</span>] - <span style="color:red;">1</span> + <span style="color:#808080;">"px"</span>; div.style.top = window[<span style="color:#808080;">"startYo"</span>] - <span style="color:red;">1</span> + <span style="color:#808080;">"px"</span>; } <span style="color:#000080;"><i>else</i></span> { document.forms[<span style="color:red;">0</span>].output.value += (document.forms[<span style="color:red;">0</span>].output.value.indexOf("\n") < <span style="color:red;">0</span> ? "\r\n" : " ") + window[<span style="color:#808080;">"moving"</span>].substring(<span style="color:red;">2</span>); } window[<span style="color:#808080;">"moving"</span>] = void(<span style="color:red;">0</span>); compute(); </code></pre> <p>}</p> <p><span style="color:#000080;"><i>function</i></span> compute() { <span style="color:#000080;"><i>var</i></span> list = getList(), parity = <span style="color:red;">0</span>, temp; <span style="color:#000080;"><i>for</i></span> (<span style="color:#000080;"><i>var</i></span> i = <span style="color:red;">0</span>; i < list.length - <span style="color:red;">1</span>; ++ i) <span style="color:#000080;"><i>if</i></span> (list[<i></i>i] != i + <span style="color:red;">1</span>) { ++ parity; <span style="color:#000080;"><i>for</i></span> (<span style="color:#000080;"><i>var</i></span> j = i + <span style="color:red;">1</span>; j < list.length; ++ j) <span style="color:#000080;"><i>if</i></span> (list[j] == i + <span style="color:red;">1</span>) { temp = list[<i></i>i]; list[<i></i>i] = list[j]; list[j] = temp; j = list.length; } } <span style="color:#000080;"><i>var</i></span> list = getList(), dist = <span style="color:red;">0</span>; <span style="color:#000080;"><i>for</i></span> (<span style="color:#000080;"><i>var</i></span> i = <span style="color:red;">0</span>; i < list.length; ++ i) <span style="color:#000080;"><i>if</i></span> (list[<i></i>i] == <span style="color:red;">0</span>) { <span style="color:#000080;"><i>var</i></span> x = i % <span style="color:red;">3</span>, y = (i - x) / <span style="color:red;">3</span>; dist = x + y - <span style="color:red;">4</span>; i = list.length; }</p> <pre><code><span style="color:#000080;"><i>var</i></span> res = <span style="color:#808080;">"yellow"</span>; <span style="color:#000080;"><i>if</i></span> (parity == <span style="color:red;">0</span>) res = <span style="color:#808080;">"green"</span>; <span style="color:#000080;"><i>else if</i></span> ((parity + dist) % <span style="color:red;">2</span> != <span style="color:red;">0</span>) res = <span style="color:#808080;">"red"</span>; <span style="color:#000080;"><i>if</i></span> (document.getElementById(<span style="color:#808080;">"rect"</span>).style.borderColor != res) document.getElementById(<span style="color:#808080;">"rect"</span>).style.borderColor = res; <span style="color:#000080;"><i>return</i></span> res != <span style="color:#808080;">"red"</span>; </code></pre> <p>}</p> <p><span style="color:#000080;"><i>function</i></span> moveAll(list) { <span style="color:#008000;">//list may be an arrays of numbers or a string (with or without commas) //does not check for validity (numbers 0-8 should be found exactly once)</span> <span style="color:#000080;"><i>if</i></span> (<span style="color:#000080;"><i>typeof</i></span> list == <span style="color:#808080;">"string"</span>) list = list.split(<span style="color:#8000ff;">/[ ,]+/</span>); <span style="color:#000080;"><i>if</i></span> (<span style="color:#000080;"><i>typeof</i></span> list != <span style="color:#808080;">"undefined"</span> && list.length == <span style="color:red;">1</span>) list = list[<span style="color:red;">0</span>].split(<span style="color:#808080;">""</span>);</p> <pre><code><span style="color:#000080;"><i>for</i></span> (<span style="color:#000080;"><i>var</i></span> i = <span style="color:red;">0</span>; <span style="color:#000080;"><i>typeof</i></span> list == <span style="color:#808080;">"undefined"</span> || i < list.length; ++ i) { <span style="color:#000080;"><i>var</i></span> sq = document.getElementById(<span style="color:#808080;">"sq"</span> + (<span style="color:#000080;"><i>typeof</i></span> list == <span style="color:#808080;">"undefined"</span> ? i + <span style="color:red;">1</span> : list[<i></i>i])); <span style="color:#000080;"><i>if</i></span> (sq != null) { sq.style.left = i % 3 * <span style="color:red;">36</span> + <span style="color:red;">1</span> + <span style="color:#808080;">"px"</span>; sq.style.top = (i - i % 3) * 12 + <span style="color:red;">1</span> + <span style="color:#808080;">"px"</span>; } <span style="color:#000080;"><i>else if</i></span> (<span style="color:#000080;"><i>typeof</i></span> list == <span style="color:#808080;">"undefined"</span>) list = []; } document.forms[<span style="color:red;">0</span>].output.value = getList().join(<span style="color:#808080;">""</span>) + (compute() ? <span style="color:#808080;">""</span> : <span style="color:#808080;">"\r\nUnsolveable"</span>); </code></pre> <p>} <span style="color:blue;"></script> <script</span> <span style="color:red;">type</span>=<span style="color:#8000ff;">"text/javascript"</span><span style="color:blue;">></span> <span style="color:#008000;">//automatic scramble & solve</span> <span style="color:#000080;"><i>function</i></span> scramble() { <span style="color:#000080;"><i>var</i></span> list = [], l2 = [<span style="color:red;">0</span>, <span style="color:red;">1</span>, <span style="color:red;">2</span>, <span style="color:red;">3</span>, <span style="color:red;">4</span>, <span style="color:red;">5</span>, <span style="color:red;">6</span>, <span style="color:red;">7</span>, <span style="color:red;">8</span>]; <span style="color:#000080;"><i>while</i></span> (l2.length > <span style="color:red;">0</span>) { <span style="color:#000080;"><i>var</i></span> i = Math.floor(Math.random() * l2.length); list.push(l2.splice(i, <span style="color:red;">1</span>)[<span style="color:red;">0</span>]); } moveAll(list);</p> <pre><code><span style="color:#000080;"><i>while</i></span> (!compute()) { <span style="color:#008000;">//unsolveable, switch 2 tiles to fix it</span> <span style="color:#000080;"><i>var</i></span> i = Math.floor(Math.random() * <span style="color:red;">9</span>); <span style="color:#000080;"><i>var</i></span> j = Math.floor(Math.random() * <span style="color:red;">8</span>); <span style="color:#000080;"><i>if</i></span> (j >= i) ++ j; <span style="color:#000080;"><i>var</i></span> temp = list[<i></i>i]; list[<i></i>i] = list[j]; list[j] = temp; moveAll(list); } </code></pre> <p>}</p> <p><span style="color:#000080;"><i>function</i></span> solve() { <span style="color:#000080;"><i>var</i></span> output = document.forms[<span style="color:red;">0</span>].output;</p> <pre><code><span style="color:#000080;"><i>var</i></span> list = getList(); <span style="color:#000080;"><i>if</i></span> (typeof solve.underway == <span style="color:#808080;">"undefined"</span> || !solve.underway) { output.value = list.join(<span style="color:#808080;">""</span>) + <span style="color:#808080;">"\r\n"</span>; solve.underway = <span style="color:#000080;"><i>true</i></span>; solve.solution = []; solve.moves = []; <span style="color:#000080;"><i>for</i></span> (<span style="color:#000080;"><i>var</i></span> e = document.forms[<span style="color:red;">0</span>].elements, i = <span style="color:red;">0</span>; i < e.length; ++ i) <span style="color:#000080;"><i>if</i></span> (e[<i></i>i].type == <span style="color:#808080;">"button"</span>) e[<i></i>i].disabled = <span style="color:#000080;"><i>true</i></span>; } <span style="color:#000080;"><i>for</i></span> (<span style="color:#000080;"><i>var</i></span> i = <span style="color:red;">0</span>, solved = <span style="color:#000080;"><i>true</i></span>, moveable = []; i < list.length; ++ i) <span style="color:#000080;"><i>if</i></span> (list[<i></i>i] != <span style="color:red;">0</span>) { <span style="color:#000080;"><i>if</i></span> (canMove(list[<i></i>i]) != <span style="color:#000080;"><i>false</i></span>) moveable.push(list[<i></i>i]); <span style="color:#000080;"><i>if</i></span> (list[<i></i>i] != i + <span style="color:red;">1</span>) solved = <span style="color:#000080;"><i>false</i></span>; } <span style="color:#000080;"><i>if</i></span> (solved) document.forms[<span style="color:red;">0</span>].output.value += (output.value.match(<span style="color:#8000ff;">/[\r\n]$/</span>) == null ? <span style="color:#808080;">"\r\n"</span> : <span style="color:#808080;">""</span>) + <span style="color:#808080;">"Done in "</span> + solve.solution.length + <span style="color:#808080;">" moves"</span>; <span style="color:#000080;"><i>if</i></span> (solved || arguments.length > <span style="color:red;">0</span> && arguments[<span style="color:red;">0</span>] == <span style="color:#000080;"><i>false</i></span>) { solve.underway = <span style="color:#000080;"><i>false</i></span>; <span style="color:#000080;"><i>for</i></span> (<span style="color:#000080;"><i>var</i></span> e = document.forms[<span style="color:red;">0</span>].elements, i = <span style="color:red;">0</span>; i < e.length; ++ i) e[<i></i>i].disabled = <span style="color:#808080;">""</span>; compute(); <span style="color:#000080;"><i>return</i></span>; } <span style="color:#008000;">//enumerates every possible series of moves, beginning with 1 move and growing progressively longer, //until the shortest solution is found. reject moves which return the puzzle to a previous state, as //the first path to any state is guaranteed to be the shortest sequence of moves to reach that state. //note that this finds the ideal solution, but probably does so with less-than-ideal efficiency.</span> <span style="color:#000080;"><i>if</i></span> (solve.moves.length + solve.solution.length == <span style="color:red;">0</span>) { <span style="color:#000080;"><i>if</i></span> (arguments.length > <span style="color:red;">0</span>) solve.moves = arguments[<span style="color:red;">0</span>]; <span style="color:#000080;"><i>else return</i></span> pleaseSolve(list.join(<span style="color:#808080;">""</span>), solve); } <span style="color:#000080;"><i>if</i></span> (solve.moves.length > <span style="color:red;">0</span>) { <span style="color:#000080;"><i>var</i></span> n = solve.moves.shift(); solve.solution.push(n); output.value += (output.value.match(<span style="color:#8000ff;">/[\r\n ]$/</span>) == null ? <span style="color:#808080;">" "</span> : <span style="color:#808080;">""</span>) + n; move(n, solve); } <span style="color:#000080;"><i>else</i></span> compute(); </code></pre> <p>}</p> <p><span style="color:#000080;"><i>function</i></span> pleaseSolve(<span style="color:#008000;">/<em>list, callback</em>/</span>) { <span style="color:#008000;">//attempts to solve a given list. runs iteratively rather than recursively and displays //status, politely exiting now and then to give the user interface a chance to update. //when a solution is found, callback is called with the list of moves.</span> <span style="color:#000080;"><i>var</i></span> i, l, m, n, solved, count = <span style="color:red;">0</span>; <span style="color:#000080;"><i>if</i></span> (arguments.length == <span style="color:red;">2</span>) { pleaseSolve.list = arguments[<span style="color:red;">0</span>]; pleaseSolve.moves = [[[], arguments[<span style="color:red;">0</span>]]]; pleaseSolve.prev = {}; pleaseSolve.c = <span style="color:red;">0</span>; pleaseSolve.callback = arguments[<span style="color:red;">1</span>]; }</p> <pre><code><span style="color:#000080;"><i>var</i></span> t = <span style="color:#000080;"><i>new</i></span> Date(); <span style="color:#000080;"><i>while</i></span> (pleaseSolve.moves.length > <span style="color:red;">0</span> && (<span style="color:#000080;"><i>new</i></span> Date()) - t < <span style="color:red;">100</span>) { m = pleaseSolve.moves.shift(); <span style="color:#000080;"><i>if</i></span> (typeof pleaseSolve.prev[m[<span style="color:red;">1</span>]] == <span style="color:#808080;">"undefined"</span>) { ++ pleaseSolve.c; pleaseSolve.prev[m[<span style="color:red;">1</span>]] = <span style="color:#000080;"><i>true</i></span>; i = m[<span style="color:red;">1</span>].indexOf(<span style="color:red;">0</span>); l = m[<span style="color:red;">1</span>].split(<span style="color:#808080;">""</span>); solved = <span style="color:#000080;"><i>true</i></span>; <span style="color:#000080;"><i>for</i></span> (n = <span style="color:red;">0</span>; n < l.length; ++ n) <span style="color:#000080;"><i>if</i></span> (l[n] != <span style="color:red;">0</span> && l[n] != n + <span style="color:red;">1</span>) { solved = <span style="color:#000080;"><i>false</i></span>; n = l.length; } <span style="color:#000080;"><i>if</i></span> (solved) { document.forms[<span style="color:red;">0</span>].output.value = pleaseSolve.list + <span style="color:#808080;">"\r\n"</span>; pleaseSolve.moves = []; pleaseSolve.callback(m[<span style="color:red;">0</span>]); <span style="color:#000080;"><i>return</i></span>; } <span style="color:#000080;"><i>else</i></span> { <span style="color:#008000;">//pleaseSolve.moves contains the queue of possible moves, each being [moves[], newlist] //where moves[] is the list of moves to get to that point and newlist is the list after //that move. array.concat and string.replace are used to add the new move and swap two //items in the list without modifying either of the originals.</span> <span style="color:#000080;"><i>var</i></span> move; <span style="color:#000080;"><i>if</i></span> (i > <span style="color:red;">2</span>) pleaseSolve.moves.push([m[<span style="color:red;">0</span>].concat(l[i - <span style="color:red;">3</span>]), m[<span style="color:red;">1</span>].replace(l[<i></i>i], l[i - <span style="color:red;">3</span>]).replace(l[i - <span style="color:red;">3</span>], l[<i></i>i])]); <span style="color:#000080;"><i>if</i></span> (i < <span style="color:red;">6</span>) pleaseSolve.moves.push([m[<span style="color:red;">0</span>].concat(l[i + <span style="color:red;">3</span>]), m[<span style="color:red;">1</span>].replace(l[i + <span style="color:red;">3</span>], l[<i></i>i]).replace(l[<i></i>i], l[i + <span style="color:red;">3</span>])]); <span style="color:#000080;"><i>if</i></span> (i % <span style="color:red;">3</span> > <span style="color:red;">0</span>) pleaseSolve.moves.push([m[<span style="color:red;">0</span>].concat(l[i - <span style="color:red;">1</span>]), m[<span style="color:red;">1</span>].replace(l[<i></i>i], l[i - <span style="color:red;">1</span>]).replace(l[i - <span style="color:red;">1</span>], l[<i></i>i])]); <span style="color:#000080;"><i>if</i></span> (i % <span style="color:red;">3</span> < <span style="color:red;">2</span>) pleaseSolve.moves.push([m[<span style="color:red;">0</span>].concat(l[i + <span style="color:red;">1</span>]), m[<span style="color:red;">1</span>].replace(l[i + <span style="color:red;">1</span>], l[<i></i>i]).replace(l[<i></i>i], l[i + <span style="color:red;">1</span>])]); } } } <span style="color:#008000;">//not done searching yet: print a status update and set a timeout to resume //searching where we left off after the user interface has a chance to update.</span> <span style="color:#000080;"><i>if</i></span> (pleaseSolve.moves.length > <span style="color:red;">0</span>) { document.forms[<span style="color:red;">0</span>].output.value = pleaseSolve.list + <span style="color:#808080;">"\r\nTrying solutions of "</span> + pleaseSolve.moves[<span style="color:red;">0</span>][<span style="color:red;">0</span>].length + <span style="color:#808080;">" moves\r\nPermutations: "</span> + pleaseSolve.c; setTimeout(pleaseSolve, <span style="color:red;">1</span>); <span style="color:#008000;">//we'll be back</span> } <span style="color:#000080;"><i>else</i></span> { document.forms[<span style="color:red;">0</span>].output.value = pleaseSolve.list + <span style="color:#808080;">"\r\nNo solution exists.\r\nPermutations: "</span> + pleaseSolve.c; pleaseSolve.callback(<span style="color:#000080;"><i>false</i></span>); } </code></pre> <p>}</p> <p><span style="color:#000080;"><i>function</i></span> move(n, callback) { <span style="color:#008000;">//animates moving a piece of the puzzle and calls callback when finished</span> <span style="color:#000080;"><i>if</i></span> (typeof move.moving == <span style="color:#808080;">"undefined"</span> || !move.moving) { move.moving = document.getElementById(<span style="color:#808080;">"sq"</span> + n); move.callback = callback; [move.x, move.y, move.x2, move.y2] = canMove(n); move.xo = move.x2 - move.x; move.yo = move.y2 - move.y; <span style="color:#008000;">//parseInt stops when it reaches "px" at the end of each value</span> move.destX = parseInt(move.moving.style.left, <span style="color:red;">10</span>) + <span style="color:red;">36</span> * move.xo + <span style="color:#808080;">"px"</span>; move.destY = parseInt(move.moving.style.top, <span style="color:red;">10</span>) + <span style="color:red;">36</span> * move.yo + <span style="color:#808080;">"px"</span>; }</p> <pre><code><span style="color:#000080;"><i>if</i></span> (move.moving.style.left != move.destX || move.moving.style.top != move.destY) { move.moving.style.left = parseInt(move.moving.style.left, <span style="color:red;">10</span>) + move.xo + <span style="color:#808080;">"px"</span>; move.moving.style.top = parseInt(move.moving.style.top, <span style="color:red;">10</span>) + move.yo + <span style="color:#808080;">"px"</span>; setTimeout(move, <span style="color:red;">10</span>); //we must exit to let the browser repaint } <span style="color:#000080;"><i>else</i></span> { move.moving = undefined; setTimeout(move.callback, <span style="color:red;">10</span>); //finished - call callback to tell it we're done } </code></pre> <p>} <span style="color:blue;"></script> <script</span> <span style="color:red;">type</span>=<span style="color:#8000ff;">"text/javascript"</span><span style="color:blue;">></span> <span style="color:#008000;">/* drag & drop */</span> <span style="color:#000080;"><i>function</i></span> allowDrop(e) { <span style="color:#000080;"><i>if</i></span> (!e.dataTransfer.types.contains(<span style="color:#808080;">"Files"</span>)) <span style="color:#000080;"><i>return</i></span>; e.preventDefault(); }</p> <p><span style="color:#000080;"><i>function</i></span> drop(e) { <span style="color:#008000;">//accepts a local image file or an image dragged from the web</span> <span style="color:#000080;"><i>if</i></span> (!(e.dataTransfer.types.contains(<span style="color:#808080;">"application/x-moz-file"</span>) || e.dataTransfer.types.contains(<span style="color:#808080;">"text/uri-list"</span>))) <span style="color:#000080;"><i>return</i></span>;</p> <pre><code><span style="color:#000080;"><i>var</i></span> img = document.createElement(<span style="color:#808080;">"img"</span>); <span style="color:#000080;"><i>if</i></span> (e.dataTransfer.files.length > <span style="color:red;">0</span>) { <span style="color:#008000;">//local file - load onto canvas and chop</span> <span style="color:#000080;"><i>var</i></span> file = e.dataTransfer.files[<span style="color:red;">0</span>]; <span style="color:#000080;"><i>if</i></span> (!file.type.match(<span style="color:#8000ff;">/image.*/</span>)) <span style="color:#000080;"><i>return</i></span>; e.preventDefault(); <span style="color:#000080;"><i>var</i></span> reader = <span style="color:#000080;"><i>new</i></span> FileReader(); reader.onload = (<span style="color:#000080;"><i>function</i></span> (img) { <span style="color:#000080;"><i>return function</i></span> (e) { img.src = e.target.result; img.onload = process; }; })(img); reader.readAsDataURL(file); } <span style="color:#000080;"><i>else</i></span> { <span style="color:#008000;">//remote image files can't be loaded into a canvas due to cross-domain safety //restrictions. instead, set backgroundImage and use backgroundPosition to crop</span> e.preventDefault(); <span style="color:#000080;"><i>var</i></span> uriList = e.dataTransfer.getData(<span style="color:#808080;">"text/uri-list"</span>); img.src = uriList; img.onload = <span style="color:#000080;"><i>function</i></span> (e) { <span style="color:#000080;"><i>var</i></span> img = e.target; document.getElementById(<span style="color:#808080;">"rect"</span>).style.backgroundImage = <span style="color:#808080;">"url(\""</span> + img.src + <span style="color:#808080;">"\")"</span>; document.getElementById(<span style="color:#808080;">"rect"</span>).style.backgroundSize = <span style="color:#808080;">"cover"</span>; <span style="color:#000080;"><i>var</i></span> x = <span style="color:red;">0</span>, y = <span style="color:red;">0</span>; <span style="color:#000080;"><i>if</i></span> (img.width > img.height) { x = Math.round((<span style="color:red;">110</span> - <span style="color:red;">110</span> / img.height * img.width) / <span style="color:red;">2</span>); img.height = <span style="color:red;">110</span>; img.width = <span style="color:red;">110</span> / img.naturalHeight * img.naturalWidth; } <span style="color:#000080;"><i>else if</i></span> (img.height > img.width) { y = Math.round((<span style="color:red;">110</span> - <span style="color:red;">110</span> / img.width * img.height) / <span style="color:red;">2</span>); img.height = <span style="color:red;">110</span> / img.naturalWidth * img.naturalHeight; img.width = <span style="color:red;">110</span>; } document.getElementById(<span style="color:#808080;">"rect"</span>).style.backgroundPosition = x + <span style="color:#808080;">"px "</span> + y + <span style="color:#808080;">"px"</span>; <span style="color:#000080;"><i>for</i></span> (<span style="color:#000080;"><i>var</i></span> i = <span style="color:red;">0</span>; i < <span style="color:red;">8</span>; ++ i) { <span style="color:#000080;"><i>var</i></span> sq = document.getElementById(<span style="color:#808080;">"sq"</span> + (i + <span style="color:red;">1</span>)); sq.style.backgroundImage = <span style="color:#808080;">"url(\""</span> + img.src + <span style="color:#808080;">"\")"</span>; sq.style.backgroundSize = img.width + <span style="color:#808080;">"px "</span> + img.height + <span style="color:#808080;">"px"</span>; sq.style.backgroundPosition = x - <span style="color:red;">4</span> - i % <span style="color:red;">3</span> * <span style="color:red;">36</span> + <span style="color:#808080;">"px "</span> + (y - <span style="color:red;">4</span> - (i - i % <span style="color:red;">3</span>) * <span style="color:red;">12</span>) + <span style="color:#808080;">"px"</span>; sq.innerHTML = <span style="color:#808080;">""</span>; <span style="color:#000080;"><i>if</i></span> (document.getElementById(<span style="color:#808080;">"h"</span> + (i + <span style="color:red;">1</span>)) == null) { <span style="color:#000080;"><i>var</i></span> div = document.createElement(<span style="color:#808080;">"div"</span>); div.style.background = <span style="color:#808080;">"white"</span>; div.style.position = <span style="color:#808080;">"absolute"</span>; div.style.display = <span style="color:#808080;">"block"</span>; div.style.height = <span style="color:#808080;">"34px"</span>; div.style.width = <span style="color:#808080;">"34px"</span>; div.style.left = <span style="color:red;">2</span> + i % <span style="color:red;">3</span> * <span style="color:red;">36</span> + <span style="color:#808080;">"px"</span>; div.style.top = <span style="color:red;">2</span> + (i - i % <span style="color:red;">3</span>) * <span style="color:red;">12</span> + <span style="color:#808080;">"px"</span>; div.style.zIndex = <span style="color:#808080;">"0"</span>; div.id = <span style="color:#808080;">"h"</span> + (i + <span style="color:red;">1</span>); sq.parentNode.insertBefore(div, sq.parentNode.firstChild); } } }; <span style="color:#000080;"><i>if</i></span> (img.complete) { img.onload({target: img}); <span style="color:#008000;">//cached image won't fire the onload event</span> img.onload = null; } } </code></pre> <p>}</p> <p><span style="color:#000080;"><i>function</i></span> process(e) { <span style="color:#008000;">//process a local file - load onto canvas, chop, and use as backgroundImage</span> <span style="color:#000080;"><i>var</i></span> img = e.target; <span style="color:#008000;">//drawImage uses nearest-neighbor to resize, and it looks bad. make size 4x larger than necessary to compensate. //it will be scaled back down to the correct size with backgroundSize, yielding a much better-looking result.</span> <span style="color:#000080;"><i>var</i></span> size = <span style="color:red;">440</span>; <span style="color:#000080;"><i>if</i></span> (img.height < img.width) { <span style="color:#008000;">//scale smallest dimension to size</span> img.height = size; img.width = img.naturalWidth / img.naturalHeight * size; } <span style="color:#000080;"><i>else</i></span> { img.width = size; img.height = img.naturalHeight / img.naturalWidth * size; }</p> <pre><code><span style="color:#008000;">//create a square canvas & center image on it</span> <span style="color:#000080;"><i>var</i></span> canvas = document.createElement(<span style="color:#808080;">"canvas"</span>); canvas.width = Math.min(img.width, img.height); canvas.height = Math.min(img.width, img.height); <span style="color:#000080;"><i>var</i></span> context = canvas.getContext(<span style="color:#808080;">"2d"</span>); context.drawImage(img, img.width > img.height ? (img.height - img.width) / <span style="color:red;">2</span> : <span style="color:red;">0</span>, img.height > img.width ? (img.width - img.height) / <span style="color:red;">2</span> : <span style="color:red;">0</span>, img.width, img.height); <span style="color:#008000;">//this canvas will hold a single piece of the image, again 4x larger than necessary</span> <span style="color:#000080;"><i>var</i></span> canvas2 = document.createElement(<span style="color:#808080;">"canvas"</span>); canvas2.width = <span style="color:red;">120</span>; canvas2.height = <span style="color:red;">120</span>; <span style="color:#000080;"><i>var</i></span> context2 = canvas2.getContext(<span style="color:#808080;">"2d"</span>); <span style="color:#000080;"><i>for</i></span> (<span style="color:#000080;"><i>var</i></span> sq, i = <span style="color:red;">0</span>; i < <span style="color:red;">8</span>; ++ i) { sq = context.getImageData( <span style="color:red;">16</span> + i % <span style="color:red;">3</span> * <span style="color:red;">144</span>, <span style="color:red;">16</span> + (i - i % <span style="color:red;">3</span>) * <span style="color:red;">48</span>, <span style="color:red;">120</span>, <span style="color:red;">120</span>); context.clearRect( <span style="color:red;">8</span> + i % <span style="color:red;">3</span> * <span style="color:red;">144</span>, <span style="color:red;">8</span> + (i - i % <span style="color:red;">3</span>) * <span style="color:red;">48</span>, <span style="color:red;">136</span>, <span style="color:red;">136</span>); context2.putImageData(sq, <span style="color:red;">0</span>, <span style="color:red;">0</span>); sq = document.getElementById(<span style="color:#808080;">"sq"</span> + (i + <span style="color:red;">1</span>)); dataURL = canvas2.toDataURL(<span style="color:#808080;">"image/png"</span>); sq.style.backgroundImage = <span style="color:#808080;">"url(\""</span> + dataURL + <span style="color:#808080;">"\")"</span>; sq.style.backgroundSize = <span style="color:#808080;">"cover"</span>; sq.style.backgroundPosition = <span style="color:#808080;">""</span>; sq.innerHTML = <span style="color:#808080;">""</span>; } <span style="color:#000080;"><i>var</i></span> dataURL = canvas.toDataURL(<span style="color:#808080;">"image/png"</span>); document.getElementById(<span style="color:#808080;">"rect"</span>).style.backgroundImage = <span style="color:#808080;">"url(\""</span> + dataURL + <span style="color:#808080;">"\")"</span>; document.getElementById(<span style="color:#808080;">"rect"</span>).style.backgroundSize = <span style="color:#808080;">"cover"</span>; document.getElementById(<span style="color:#808080;">"rect"</span>).style.backgroundPosition = <span style="color:#808080;">""</span>; setTimeout(compute, <span style="color:red;">1</span>); </code></pre> <p>} <span style="color:blue;"></script></p> </head> <p><body</span> <span style="color:red;">onload</span>=<span style="color:#8000ff;">"setup();"</span> <span style="color:red;">ondragover</span>=<span style="color:#8000ff;">"allowDrop(event);"</span> <span style="color:red;">ondrop</span>=<span style="color:#8000ff;">"drop(event);"</span><span style="color:blue;">> <div</span> <span style="color:red;">id</span>=<span style="color:#8000ff;">"rect"</span><span style="color:blue;">><span</span> <span style="color:red;">id</span>=<span style="color:#8000ff;">"move"</span><span style="color:blue;">> <div</span> <span style="color:red;">class</span>=<span style="color:#8000ff;">"sq"</span>>1<span style="color:blue;"></div> <div</span> <span style="color:red;">class</span>=<span style="color:#8000ff;">"sq"</span>>2<span style="color:blue;"></div> <div</span> <span style="color:red;">class</span>=<span style="color:#8000ff;">"sq"</span>>3<span style="color:blue;"></div> <div</span> <span style="color:red;">class</span>=<span style="color:#8000ff;">"sq"</span>>4<span style="color:blue;"></div> <div</span> <span style="color:red;">class</span>=<span style="color:#8000ff;">"sq"</span>>5<span style="color:blue;"></div> <div</span> <span style="color:red;">class</span>=<span style="color:#8000ff;">"sq"</span>>6<span style="color:blue;"></div> <div</span> <span style="color:red;">class</span>=<span style="color:#8000ff;">"sq"</span>>7<span style="color:blue;"></div> <div</span> <span style="color:red;">class</span>=<span style="color:#8000ff;">"sq"</span>>8<span style="color:blue;"></div> </span></div> <br</span> <span style="color:red;">clear</span>=<span style="color:#8000ff;">"both"</span><span style="color:blue;">/></p> <form> <input</span> <span style="color:red;">type</span>=<span style="color:#8000ff;">"button"</span> <span style="color:red;">value</span>=<span style="color:#8000ff;">"Scramble"</span> <span style="color:red;">onclick</span>=<span style="color:#8000ff;">"scramble();"</span><span style="color:blue;">/> <input</span> <span style="color:red;">type</span>=<span style="color:#8000ff;">"button"</span> <span style="color:red;">value</span>=<span style="color:#8000ff;">"Set..."</span> <span style="color:red;">onclick</span>=<span style="color:#8000ff;">"moveAll(prompt('Enter #s (the solved state is 123456780)',getList().join('')));"</span><span style="color:blue;">/> <input</span> <span style="color:red;">type</span>=<span style="color:#8000ff;">"button"</span> <span style="color:red;">value</span>=<span style="color:#8000ff;">"Solve"</span> <span style="color:red;">onclick</span>=<span style="color:#8000ff;">"solve();"</span><span style="color:blue;">/> <br/> <textarea</span> <span style="color:red;">name</span>=<span style="color:#8000ff;">"output"</span> <span style="color:red;">rows</span>=<span style="color:#8000ff;">"7"</span> <span style="color:red;">style</span>=<span style="color:#8000ff;">"width:100%;"</span> <span style="color:red;">readonly</span><span style="color:blue;">></textarea> </form> </body> </html></span></pre> </textarea></form>