Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
0% found this document useful (0 votes)
50 views

Algorithms and Data Structures I

The document discusses the Tower of Hanoi puzzle and provides pseudocode to recursively solve it. It explains that the puzzle involves moving disks of different sizes between three towers according to rules of only moving one disk at a time and not placing a larger disk on top of a smaller one. The recursive solution works by breaking the problem down into smaller subproblems of moving all but the largest disk, moving the largest disk, and then moving the remaining disks. It also provides Java code examples to both print out the moves and to actually maintain the state of the towers using stacks.

Uploaded by

jahanzeb
Copyright
© © All Rights Reserved
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
50 views

Algorithms and Data Structures I

The document discusses the Tower of Hanoi puzzle and provides pseudocode to recursively solve it. It explains that the puzzle involves moving disks of different sizes between three towers according to rules of only moving one disk at a time and not placing a larger disk on top of a smaller one. The recursive solution works by breaking the problem down into smaller subproblems of moving all but the largest disk, moving the largest disk, and then moving the remaining disks. It also provides Java code examples to both print out the moves and to actually maintain the state of the towers using stacks.

Uploaded by

jahanzeb
Copyright
© © All Rights Reserved
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 20

1/15/2016

AlgorithmsandDataStructuresI

Module9:Recursion,PartII
Supplementalmaterial
TheTowerofHanoi

IntheTowerofHanoipuzzle:
Therearethreestacks(towers),numbered0,1,2.

ThereareNdisksnumbered0,...,N1.
=>0isthesmallest.
Initially,thedisksareplacedintower0,intheorderlargesttosmallest.
=>Smallestontop.
Goal:tomovethediskstotower1usingonlylegalmoves.
What'salegalmove?
Youcanmoveonlyadiskatthetopofatower.
Youcanmoveonlyonediskatatime.
Youcannotplaceadiskontopofasmallerone.

Wewillsolvetheproblemusing(ofcourse)recursion:
Therearethreekeystepsintherecursion:

Step1:movedisks0,...,N2fromtower0totower2
http://www.seas.gwu.edu/~drum/cs1112/lectures/module9/module9.html

1/20

1/15/2016

AlgorithmsandDataStructuresI

=>Subproblemofsmallersize.

Step2:movediskN1fromtower0totower1.

Step3:movedisks0,...,N2fromtower2totower1.
=>Subproblemofsmallersize.

Inpseudocode(withoutbasecase):
AlgorithmtowerOfHanoi(n,i,j)
Input:Disksnumbered0,...,naretobemovedfromtoweritotowerj
1.//...basecase...
//Firstfindthethirdtower,otherthaniandj:
2.k=otherTower(i,j)
//Step1:movedisks0,..,n1fromitok
3.towerOfHanoi(n1,i,k)
//Step2:movedisk#nfromitoj
4.move(n,i,j)
//Step3:movedisks0,...,n1fromktoj
5.towerOfHanoi(n1,k,j)

Thebasecase:moveasingledisk

http://www.seas.gwu.edu/~drum/cs1112/lectures/module9/module9.html

2/20

1/15/2016

AlgorithmsandDataStructuresI

Here'stheprogram:(sourcefile)
publicclassTowerOfHanoi{
publicstaticvoidmain(String[]argv)
{
//A3diskpuzzle:
System.out.println("3Disksolution:");

solveHanoi(2,0,1);
//A4diskpuzzle:
System.out.println("4Disksolution:");

solveHanoi(3,0,1);
}
staticvoidsolveHanoi(intn,inti,intj)
{

//Bottomout.

if(n==0){
//Thesmallestdisk.

move(0,i,j);

return;

intk=other(i,j);
solveHanoi(n1,i,k);//Step1.
move(n,i,j);//Step2.
solveHanoi(n1,k,j);//Step3.

staticvoidmove(intn,inti,intj)
{
//Fornow,we'llmerelyprintoutthemove.
System.out.println("=>Movedisk#"+n+"fromtower"+i+"totower"+j);
}
staticintother(inti,intj)
{
//Giventwotowers,returnthethird.
if((i==0)&&(j==1)){
return2;
}
elseif((i==1)&&(j==0)){
return2;
}
elseif((i==1)&&(j==2)){
return0;
}
elseif((i==2)&&(j==1)){
return0;
}
elseif((i==0)&&(j==2)){
return1;
}
elseif((i==2)&&(j==0)){
return1;
}
//Weshouldn'treachhere.
return1;
}
}

Note:
Theaboveprogrammerelyprintsoutthemovesneeded
=>Wedon'tactuallymaintainthestateofeachtower.

http://www.seas.gwu.edu/~drum/cs1112/lectures/module9/module9.html

3/20

1/15/2016

AlgorithmsandDataStructuresI

Next,supposewewanttomaintainthestateofeachtower:
Theidealdatastructureisastack.
We'lluseonestackforeachtower.
Here'stheprogram:(sourcefile)
importjava.util.*;
publicclassTowerOfHanoi2{
//towers[0],towers[1]andtowers[2]arethethreestacks.
staticStack<Integer>[]towers;
publicstaticvoidmain(String[]argv)
{
//A3diskpuzzle:
System.out.println("3Disksolution:");

solveHanoi(2,0,1);
//A4diskpuzzle:
System.out.println("4Disksolution:");

solveHanoi(3,0,1);
}
staticvoidsolveHanoi(intn,inti,intj)
{
//Createthethreestacks.

towers=newStack[3];

for(intk=0;k<3;k++){

towers[k]=newStack<Integer>();

}
//Putdisks0,...,nonstack0.

for(intk=n;k>=0;k){

towers[0].add(k);

}
//Printtheinitialstack.

printTowers();
//Nowsolverecursively.Note:thisisthemethodbelow.

solveHanoiRecursive(n,i,j);
}

staticvoidsolveHanoiRecursive(intn,inti,intj)
{

//Bottomout.

if(n==0){

move(0,i,j);

return;

intk=other(i,j);

solveHanoiRecursive(n1,i,k);//Step1.

move(n,i,j);//Step2.

solveHanoiRecursive(n1,k,j);//Step3.
}
staticvoidmove(intn,inti,intj)
{
//Pulloutthetopdiskonstacki.

inttopVal=towers[i].pop();
//Putitonstackj.

towers[j].push(topVal);
//Printstatus.
System.out.println("Towersaftermoving"+n+"fromtower"+i+"totower"+j);

printTowers();
}
http://www.seas.gwu.edu/~drum/cs1112/lectures/module9/module9.html

4/20

1/15/2016

AlgorithmsandDataStructuresI

staticintother(inti,intj)
{
//...
}
staticvoidprintTowers()
{

for(inti=0;i<towers.length;i++){

System.out.print("Tower"+i+":");

if(!towers[i].isEmpty()){

for(IntegerI:towers[i]){

System.out.print(""+I);

System.out.println();

}
}
}

Note:
Sinceweneededtocreatethestacksaheadoftime,wemovedtherecursivepartofthecodeintoanewrecursive
methodsolveHanoiRecursive().
Toremoveadiskfromthetopofatower,wepop()fromthattower(stack):
//Pulloutthetopdiskonstacki.

inttopVal=towers[i].pop();

Toplaceadiskontopofatower,wepush()it:
//Putitonstackj.

towers[j].push(topVal);

NoticehowprintTowers()usesthe"collection"versionoftheforloop:

if(!towers[i].isEmpty()){
//Newtypeofforloop:

for(IntegerI:towers[i]){

System.out.print(""+I);

Astrangecompilationmessage:
Incompilingtheaboveprogram(withaJava1.5compiler),wegetawarning(notanerror):
Note:TowerOfHanoi2.javausesuncheckedorunsafeoperations.
Note:RecompilewithXlint:uncheckedfordetails.

Thisallowsyoutocontinuewithexecution.
Youcan,asitsuggests,recompilewiththeXlint:uncheckedoption:
javacXlint:uncheckedTowerOfHanoi2.java

Whatyouseeasaresult:
TowerOfHanoi2.java:25:warning:[unchecked]uncheckedconversion
found:java.util.Stack[]
required:java.util.Stack[]
towers=newStack[3];
^

Thecompilerdidnotlikethestatement:
http://www.seas.gwu.edu/~drum/cs1112/lectures/module9/module9.html

5/20

1/15/2016

AlgorithmsandDataStructuresI

towers=newStack[3];

So,shouldthisinsteadhavebeen
towers=newStack<Integer>[3];

asonemightintuitivelyexpect?
Unfortunately,thatresultsinacompilationerror.
ThereasonisquiteesotericandhastodowiththegorydetailsofgenerictypesarehandledinJava.
Essentially,itboilsdowntothis:adeclarationlike
towers=newStack<Integer>[3];

isunsafebecauseonecanassignnonIntegerstackstotowers,whichiswhythecompilerdoesn'tallowit.
Thus,weareleftwithusingtheslightlylessunsafe
towers=newStack[3];

whichthecompilerallowsbutwarnsagainst.
GenerictypesinJavaconstitutealargeandsomewhatadvancedtopic,toocomplicatedforthiscourse.

Anapplication:diskbackupschedules
Supposewehavefourdisks(A,B,CandD)onwhichwewishtoperformbackupseachday.
=>Thisisadifferentmeaningofdisk(harddrive,removablemedia)
Eachdayweneedtochooseadiskonwhichtobackup
=>Thebackupschedule.
Oneoptionistogoroundrobin
Day0usediskA
Day1usediskB
Day2usediskC
Day3usediskD
Day4usediskA
Day5usediskB
...
(andsoon)

Withthissystem,wecanonlygobackatmostfourdays.
Wearenotabletoretrievethestateofthesystemfrom,say,6daysago.
Anotherapproach:staggerthedisks:
Day0usediskA
Day1usediskB
Day2usediskA
Day3usediskC
Day4usediskA
Day5usediskB
Day6usediskA
Day7usediskD
Day8usediskA
...
(andsoon)

Withthisapproach,we'dhaveadistributionlike
DiskA1or2daysbefore
DiskBatmost4daysbefore
DiskCatmost8daysbefore
DiskDatmost16daysbefore

http://www.seas.gwu.edu/~drum/cs1112/lectures/module9/module9.html

6/20

1/15/2016

AlgorithmsandDataStructuresI

Thisdistributionallowsadeeperreachintothepast.
ThesequenceaboveisexactlytheTowerofHanoimovesequencefordisksnumberedA,B,CandD.

Recursion:areview

First,let'sreviewasimpleexamplefromModule4:
Recalltherecursivecomputationofpower:
//Computeab
staticintpower(inta,intb)
{
//Bottomout:
if(b==0){
return1;
}
//Recursion:
return(a*power(a,b1));
}

What'simportant:
Wemusttestforthebottomoutcasebeforerecursing.
Thebottomoutcaseteststhevalue(orvalues)oftheparameter(orparameters)thatchangesinthe
recursion.
=>Thesearetheparametersthatcontroltherecursion.
Therecursivecallsmustchange(usuallydecrease)theparametersthatcontroltherecursion.
=>Above,thereisonlyonerecursivecall,butTowerofHanoihastwo.
Howrecursionworks:
Eachmethodcallcreatesanactivationrecordonthesystemstack.
Theactivationrecordconsistsofspaceallocatedfortheparticularparametersandlocalvariablesforthat
methodcall.
Thus,arecursivecallresultsinanewactivationrecordforeachsuchrecursivecall.
=>Thisiswhyeachexecutionofthemethodretainsitsownparametersandlocalvariables.
Theactivationrecordalsoknowsthatwhenexecutionofamethodcallcompletes,executionreturnstothe
callingmethodjustafterthecalledmethodwascalled.
Forrecursionit'snodifferentexceptthatit'sthesamecodeinvolvedinallmethodcalls.
Thebestwaytounderstandrecursioninitiallyistodrawthestackpictureandworkthroughanexample.

Let'snowreviewanotherexamplefromModule4:
Thisisthepermutationseatingexamplewhereweprintthearrangement:
//Theparameterstothismethodare:
//numSpacestotalnumberofremainingseatsavailable
//numRemainingtotalnumberofpeoplelefttoseat
//seatsanarraywhereseats[i]==0ifseatisavailable
//personwhichpersonweneedtoseat
staticvoidprintPermutations(intnumSpaces,intnumRemaining,int[]seats,intperson)
{
//Bottomoutcase.

if(numRemaining==0){

//Print.

System.out.println(Arrays.toString(seats));

return;

}
http://www.seas.gwu.edu/~drum/cs1112/lectures/module9/module9.html

7/20

1/15/2016

AlgorithmsandDataStructuresI

//Otherwise,nonbasecase:lookforanemptyspotfor"person"
for(inti=0;i<seats.length;i++){
if(seats[i]==0){

//Emptyspot.
seats[i]=person;

//Recursivelyassignremaining,startingwithperson+1

printPermutations(numSpaces1,numRemaining1,seats,person+1);
//Important:weneedtoundotheseatingforothertrials.

seats[i]=0;

}//endfor
}

What'ssimilaraboutthisrecursivemethod:
Theparameterthatcontrolsrecursionis:numSpaces
=>Thisiswhatwecheckinthebottomoutcase.
Otherparameterspassalonginformation:personandseats.
What'sdifferent(fromthepower()example):
Whenwefillintheseatsarray,weundothisassignmentaftertherecursivecall:
//Makesomechangetoaparameter:

seats[i]=person;
//Recurse:

printPermutations(numSpaces1,numRemaining1,seats,person+1);
//Undothechange(restoretheoriginal)forfuturerecursions:

seats[i]=0;

Twotypesofrecursion:
Recursionwhereyoudon'tundochanges.
=>Sometimesthisiscalledtailrecursion.
Recursionwhereyouneedtoundochangessothatyoucanproperlyexploreallpossibilities
=>Sometimesthisiscalledrecursionwithbacktracking.
Manyexamplesoftailrecursioncaneasilybewrittennonrecursively(usingiteration)
=>Formanyoftheseexamples(power,factorial,fibonacci),it'sbettertouseiteration.
However,whenthere'sbacktracking,itcanbeverydifficulttoavoidrecursion.

Mazeconstructionandtraversal:a(long)exampleofrecursionwithbacktracking

Wewillnowexamineamazeapplicationindetailtoillustraterecursionwithbacktracking:
First,wewilluserecursiontocreateamazelikethis:

http://www.seas.gwu.edu/~drum/cs1112/lectures/module9/module9.html

8/20

1/15/2016

AlgorithmsandDataStructuresI

Then,wewilluserecursiontosolvesuchamaze(byfindingapathfromagivenstartcell(e.g.,thetopleft)toa
givenendcell(e.g.,thebottomright):

WewillputawholebunchofusefulcodeinaclasscalledMazeandinsteadfocusonusingthatclassthroughits
methods.
http://www.seas.gwu.edu/~drum/cs1112/lectures/module9/module9.html

9/20

1/15/2016

AlgorithmsandDataStructuresI

We'llusethiscellnumberingconvention:
Rowsstartnumberingat0,andincreasedownwards.
Columnsstartat0andincreaserightwards.
Thus,thetopleftcellis(0,0).Theonetoitsrightis(0,1)andtheonedirectlybelowis(1,0).

Tostartwith,let'sexaminethemethodsintheclassMaze:
Theconstructor:wecreateaninstancebyspecifyingthenumberofrowsandcolumns:
Mazemaze=newMaze(5,5);

Ourexampleswillusesquaremazes.
display():callthismethodtodisplaythemaze:
Mazemaze=newMaze(5,5);
//BringuptheGUI:
maze.display();

breakWall():

Initially,themazeconsistsofcompletecells.Toactuallycreateawalkablemaze,wewill"breakwalls"
betweenneighboringcells.
Forexample,wecanbreakthewallbetweencells(3,4)and(2,4)asfollows:
Mazemaze=newMaze(5,5);
//NotetheuseoftheCoordclass:
Coordc1=newCoord(3,4);
Coordc2=newCoord(2,4);
maze.breakWall(c1,c2);
maze.display();

Or,alternatively,withshortercode:
Mazemaze=newMaze(5,5);
//Createaninstancedirectlyinthemethodargumentlist:
maze.breakWall(newCoord(3,4),newCoord(2,4));
maze.display();

TheCoordclasslookslikethis:
publicclassCoord{
publicintrow=1,col=1;
publicCoord(intr,intc)
{
row=r;
col=c;
}

publicStringtoString()
{
return"["+row+","+col+"]";
}

Thus,toaccessthestoredcoordinates:
Coordc=newCoord(3,4);
System.out.println("Row="+c.row+"Col="+c.col);
http://www.seas.gwu.edu/~drum/cs1112/lectures/module9/module9.html

10/20

1/15/2016

AlgorithmsandDataStructuresI

//Or,toprintbothusingtoString():
System.out.println(c);

Anumberofmethods(intheclassMaze)allowustomarkandunmarkcellsasvisited:
markVisited(Coordc):markcellcasvisited.
markUnVisited(Coordc):markcellcasnotvisited.
markAllUnvisited():markallcellsasunvisited.
isVisited(Coordc):seewhethercellchasbeenvisited.
Anumberofmethodsrelatedtofetchingalist(array)ofacell'sneighbors:
Coord[]getUnvisitedClosedNeighbors(Coordc):getcellc'sneighborsthatareclosedofffromc(there's
awallbetween)andhaven'tbeenvisitedyet.
Coord[]getClosedNeighbors(Coordc):getneighborsofcthatshareawall(unbroken)withcwhether
visitedornot.
Coord[]getUnvisitedOpenNeighbors(Coordc):getthoseneighborsofcforwhichwecanwalkthrough
totheneighbor(nowall)andwhichhaven'tbeenvisited.
EachofthesemethodsreturnanarrayofCoordinstances.
Afewadditionalusefulmethods:
copy():makeafullcopyofthemaze,asin:
Mazem=newMaze(5,5);
//...dostuff:breakwallsetc...
Mazem2=m.copy();
//Nowm2isacopyofm.Makingchangestomwon'taffectm2.

setSolutionPath(LinkedList<Coord>solutionPath):wewillcallthismethodoncewehaveconstructed

asolution.

We'llnowwriteourfirstattempt:
Wewilltrytogenerateamazepathofagivenpathlength.
Thekeyidea:
Algorithm:recursiveGenerate(Coordc)
1.ifpathlengthhasbeenreached
2.return
//Otherwise...
3.c'=Pickarandomneighborofcellc
4.recursiveGenerate(c')

Here'stheprogram:(sourcefile)
publicclassMazeMaker{
//Thesevariableswillbeusedacrossmethods:
staticintdesiredPathLength;
staticMazemaze;
publicstaticvoidmain(String[]argv)
{
generateMaze(5,5);
}
publicstaticvoidgenerateMaze(intnumRows,intnumCols)
{
maze=newMaze(numRows,numCols);
//Wewanttogenerateapathofthislength:

desiredPathLength=numRows*numCols;

//Initially,we'llstartwiththetopleftcellandmarkthatasvisited.
Coordstart=newCoord(0,0);

maze.markVisited(start);
http://www.seas.gwu.edu/~drum/cs1112/lectures/module9/module9.html

11/20

1/15/2016

AlgorithmsandDataStructuresI

//Generatethemazepathrecursively.

booleanfound=recursiveGenerate(start,1);
if(!found){
System.out.println("Couldnotcreatethewholemaze");
}
maze.display();
}
staticbooleanrecursiveGenerate(Coordc,intpathLength)
{
//Bottomoutcondition1:

if(pathLength==desiredPathLength){

//Done.We'vecreateamazepathofthedesiredlength.

returntrue;

}
//Bottomoutcondition2:seeifthere'saneighbortovisit.

Coord[]validNeighbors=maze.getUnvisitedClosedNeighbors(c);

if((validNeighbors==null)||(validNeighbors.length==0)){
//There'snoneighborwhosewallwecanbreak.Soquittrying.

returnfalse;

}
//Otherwise,pickarandomneighborandproceed.
inti=UniformRandom.uniform(0,validNeighbors.length1);
//Breakthewallandmarktheneighborasvisited.
maze.breakWall(c,validNeighbors[i]);
maze.markVisited(validNeighbors[i]);

//Recurse.
returnrecursiveGenerate(validNeighbors[i],pathLength+1);
}
}

Nextattempt:
Simpletailrecursioncangetstuck.
=>Weneedawayto"undo"pathsandtrydifferentneighbors.
Wewillpickaneighbortoexplorerecursively
=>Ifthatdoesn'tworkout,we'lltryanother.
Here'stheprogram:(sourcefile)
publicclassMazeMaker2{
staticintdesiredPathLength;
staticMazemaze;
publicstaticvoidmain(String[]argv)
{
generateMaze(5,5);
}
publicstaticvoidgenerateMaze(intnumRows,intnumCols)
{
maze=newMaze(numRows,numCols);

desiredPathLength=numRows*numCols;

//Initially,we'llstartwiththetopleftcell.
Coordstart=newCoord(0,0);

maze.markVisited(start);
//Generatethemazepathrecursively.
http://www.seas.gwu.edu/~drum/cs1112/lectures/module9/module9.html

12/20

1/15/2016

AlgorithmsandDataStructuresI

booleanfound=recursiveGenerate(start,1);

if(!found){
System.out.println("Couldnotcreatethewholemaze");
}
maze.display();
}
staticbooleanrecursiveGenerate(Coordc,intpathLength)
{
//Bottomoutcondition1:

if(pathLength==desiredPathLength){

returntrue;

}
//Bottomoutcondition1:seeifwe'restuck.

Coord[]validNeighbors=maze.getUnvisitedClosedNeighbors(c);

if((validNeighbors==null)||(validNeighbors.length==0)){

returnfalse;

//Otherwise,wehavesomeneighborstoexplore.
//Permutethedirectionsrandomly.
permute(validNeighbors);

for(inti=0;i<validNeighbors.length;i++){

//Tryneighbori.
maze.breakWall(c,validNeighbors[i]);
maze.markVisited(validNeighbors[i]);

booleanok=recursiveGenerate(validNeighbors[i],pathLength+1);

if(ok){
//Ifneighboriworkedout,great.

returntrue;

//Otherwise,undoassignmenttoi.
maze.fixWall(c,validNeighbors[i]);
maze.markUnvisited(validNeighbors[i]);

}//endfor

//Couldn'tmakeitwork.
returnfalse;

staticvoidpermute(Coord[]coords)
{

for(inti=0;i<coords.length;i++){

//Findarandomelementtoplaceintoithplace.

intk=(int)UniformRandom.uniform(i,coords.length1);

Coordtemp=coords[i];

coords[i]=coords[k];

coords[k]=temp;

}
}
}

Note:
Thekeyideaistotryasmanyneighborsasneeded:
Algorithm:recursiveGenerate(Coordc)
1.ifpathlengthhasbeenreached
2.returntrue
3.endif
//Otherwise...
4.foreachneighborc'ofc
5.found=recursiveGenerate(c')
6.iffound
http://www.seas.gwu.edu/~drum/cs1112/lectures/module9/module9.html

13/20

1/15/2016

AlgorithmsandDataStructuresI

7.returntrue
8.endif
9.endfor
//Wereachhereonlyifeveryneighbordidnotworkout.
10.returnfalse

Notehowweundoabrokenwall:

for(inti=0;i<validNeighbors.length;i++){
//Tryneighbori.
maze.breakWall(c,validNeighbors[i]);
maze.markVisited(validNeighbors[i]);

//...recursionhere...

//Toundo:repairthewallandmarkasUNvisited.
maze.fixWall(c,validNeighbors[i]);
maze.markUnvisited(validNeighbors[i]);
}//endfor

Amazewithchoices:
Theabovemazepathhasnochoices
=>There'sonlyonewayfromthetoplefttotheendofthepath.
Wewillbuilduponthistocreateamazewithchoices
=>Aftergeneratingthelongpath,we'llbreaksomerandomwalls.
Here'stheprogram:(sourcefile)
publicclassMazeMaker3{
//...variables...
publicstaticvoidmain(String[]argv)
{
generateMaze(5,5);
}
publicstaticvoidgenerateMaze(intnumRows,intnumCols)
{
//...createandgeneratesinglepathmaze...
//Breakafewmorewalls,randomly.
breakRandomWalls(maze,10);
maze.display();
}
staticbooleanrecursiveGenerate(Coordc,intpathLength)
{
//...sameasbefore...
}

staticvoidbreakRandomWalls(Mazemaze,intnumWalls)
{

for(intk=0;k<numWalls;k++){
//Createrandomcoordinates,i.e.,identifyarandomcell.

intx=UniformRandom.uniform(0,maze.numRows1);

inty=UniformRandom.uniform(0,maze.numCols1);

Coordc=newCoord(x,y);
//Getitsneighborsthatareseparatedbyawall.

Coord[]validNeighbors=maze.getClosedNeighbors(c);

if(validNeighbors!=null){
http://www.seas.gwu.edu/~drum/cs1112/lectures/module9/module9.html

14/20

1/15/2016

AlgorithmsandDataStructuresI

//Pickoneandbreakthewall.
intm=UniformRandom.uniform(0,validNeighbors.length1);

maze.breakWall(c,validNeighbors[m]);

}
}
}

Let'sturnourattentiontosolvingthemaze:
We'llfirsttryasimpleidea:
Algorithm:recursivelyFindPath(Coordc)
1.ifcistheend
2.returntrue
3.endif
4.//Otherwisesearchfurther...
5.c'=pickarandom"open"neighbor
6.ifc'isnull
//Stuck:couldn'tfindapath.
7.returnfalse
8.endif
9.returnrecursivelyFindPath(c')

Here'stheprogram:(sourcefile)
importjava.util.*;
publicclassMazeMaker4{
staticintdesiredPathLength;
staticMazemaze;
publicstaticvoidmain(String[]argv)
{
Mazemaze=generateMaze(5,5);

if(maze!=null){
//Wewillseekapathfromthetoplefttothebottomrightcorner.

Coordstart=newCoord(0,0);

Coordend=newCoord(4,4);

solveMaze(maze,start,end);

maze.display();

else{

System.out.println("Mazecreationdidnotwork");

}
}
//Apathisalistofcells,i.e.,alistofCoordinstances.
staticLinkedList<Coord>solutionPath;
staticvoidsolveMaze(Mazemaze,Coordstart,Coordend)
{
//We'llmarkvisitedcellsaswegoalongourpath.Initially:

maze.markAllUnvisited();
//Markthestartcellasvisited.

maze.markVisited(start);
//Createthelist.

solutionPath=newLinkedList<Coord>();
//Recursivelyfindthepathandfillincoord'sintothelist.

recursivelyFindPath(maze,start,end);
//PassthepathintotheGUI.

maze.setSolutionPath(solutionPath);
http://www.seas.gwu.edu/~drum/cs1112/lectures/module9/module9.html

15/20

1/15/2016

AlgorithmsandDataStructuresI

}
staticbooleanrecursivelyFindPath(Mazemaze,Coordc,Coordend)
{
//Firstaddthecurrentcellintothepath.

solutionPath.add(c);
//Ifwe'vereachedtheend,we'redone.

if((c.row==end.row)&&(c.col==end.col)){

returntrue;

}
//Otherwise,let'sfindaneighbortoexplore.

Coord[]validNeighbors=maze.getUnvisitedOpenNeighbors(c);

if(validNeighbors==null){
//Iftherearen'tany,we'redone,butcouldn'tfindapath.

returnfalse;

//Takethefirstoneandexplorefromthere.
maze.markVisited(validNeighbors[0]);

returnrecursivelyFindPath(maze,validNeighbors[0],end);

//...Mazegenerationcode...sameasbefore...
}

Asolutionthatworks:
Whenexploringaneighbor,weneedawaytoundo(backtrack)ifitdoesn'tleadtoasolution.
Theideaistotryallpossibleneighbors,asmanyasneeded:
Algorithm:recursivelyFindPath(Coordc)
1.ifcistheend
2.returntrue
3.endif
4.//Otherwisesearchfurther...
5.foreach"open"neighborc'
6.found=recursivelyFindPath(c')
7.iffound
8.addc'topath
9.returntrue
10.endif
10.endfor
11.returnfalse

Here'stheprogram:(sourcefile)
importjava.util.*;
publicclassMazeMaker5{
//...variables...sameasbefore(forgeneration)...
publicstaticvoidmain(String[]argv)
{
//...same...
}
//Apathisalistofcells,i.e.,alistofCoordinstances.
staticLinkedList<Coord>solutionPath;

http://www.seas.gwu.edu/~drum/cs1112/lectures/module9/module9.html

16/20

1/15/2016

AlgorithmsandDataStructuresI

staticvoidsolveMaze(Mazemaze,Coordstart,Coordend)
{
//We'llmarkvisitedcellsaswegoalongourpath.Initially:

maze.markAllUnvisited();
//Markthestartcellasvisited.

maze.markVisited(start);
//Createthelist.

solutionPath=newLinkedList<Coord>();
//Recursivelyfindthepathandfillincoord'sintothelist.

recursivelyFindPath(maze,start,end);
//Thestartnodegetsaddedlast.Why?
solutionPath.addFirst(start);
//PassthepathintotheGUI.

maze.setSolutionPath(solutionPath);
}
staticbooleanrecursivelyFindPath(Mazemaze,Coordc,Coordend)
{
//Ifwe'vereachedtheend,we'redone.

if((c.row==end.row)&&(c.col==end.col)){

returntrue;

}
//Otherwise,let'sfindaneighbortoexplore.

Coord[]validNeighbors=maze.getUnvisitedOpenNeighbors(c);

if(validNeighbors==null){
//Ifwecouldn'tfindanyneighborstoexplore,we'restuck.

returnfalse;

}
//Tryeachneighbor,asmanyasneeded.
for(inti=0;i<validNeighbors.length;i++){
//Tryneighbori.

maze.markVisited(validNeighbors[i]);

booleanfound=recursivelyFindPath(maze,validNeighbors[i],end);

if(found){
//Noticethatweaddthistothefrontofthelist,andonly
//afterthesolutionhasbeenfounduptohere.

solutionPath.addFirst(validNeighbors[i]);

returntrue;

//Ifneighborididn'tworkout,undothevisitandcontinue.

maze.markUnvisited(validNeighbors[i]);

}
//Ifwereachedhere,thennoneoftheneighborsworkedout.

returnfalse;
}
}

TheNQueensproblem

Inthisproblem:
WearegivenanNxNchessboardandMqueens(whereM<=N).
Thegoalistoplacethequeensontheboardsothatnoqueen"attacks"another.
http://www.seas.gwu.edu/~drum/cs1112/lectures/module9/module9.html

17/20

1/15/2016

AlgorithmsandDataStructuresI

Forexample(N=8):

Recallthataqueencanattackanysquareinitsrow,columnordiagonal,e.g.

Wewillofcoursesolvethisrecursively:
Thisisanotherexampleofrecursionwithbacktracking.
Keyideas:
We'llproceedcolummbycolumn(lefttoright).
Whensolvingforthecurrentcolumn,trytoplaceaqueenoneachpossiblerow,andsolvethesub
problem(startingwiththenextcolumn)recursively.
Pseudocode:
Algorithm:solve(n,c)
Input:n=thenumberofqueenstoassign,c=thecolumntostartwith

//...Bottomoutconditions...(we'lldothislater)
1.foreachrowr
2.if[r,c]isanonattackedsquare
3.placequeennoncell[r,c]
4.found=solve(n1,c+1)//Assignremainingn1recursively
5.if(found)
6.returntrue
7.endif
8.endif
9.endfor
http://www.seas.gwu.edu/~drum/cs1112/lectures/module9/module9.html

18/20

1/15/2016

AlgorithmsandDataStructuresI

//Wereachhereifnoneoftherowsincolumncworkedout.
10.returnfalse

Thus,wetryeveryrowforaqueenandtrytosolvethesubproblemwithfewerqueens.
=>Ififthatgetssolved,wecanplacethequeenthereandrecursebackup
Thebottomoutconditions:
Checkiftherearenomorequeenstoassign
=>Problemgetssolved.
Checkiftherearenomorecolumnstotry
=>Nosolutionexists.
WewillbuildaclasscalledChessBoardwithmethodsthathidemostofthemessyboardmanipulationdetails:
addQueen(row,col):addaqueeninsquare[row,col].
removeQueen(row,col):removethequeeninsquare[row,col].
booleanisForbidden(row,col):seeif[row,col]isanattackedsquare.
display():tobringupaGUIwiththeboarddisplayed.
Here'stheprogram:(sourcefile)
importjava.awt.*;
importjava.util.*;
publicclassNQueens{
staticChessBoardboard;
publicstaticvoidmain(String[]argv)
{
solveQueens(8,8);
}
staticvoidsolveQueens(intnumQueens,intsize)
{
board=newChessBoard(size);
booleansolutionExists=solve(numQueens,0);
if(!solutionExists){
System.out.println("Nosolutionfor"+numQueens+"ona"+size+"x"+size+"board");
return;
}
System.out.println("Solutionfoundfor"+numQueens+"ona"+size+"x"+size+"board");
System.out.println(board);
board.display();
}

staticbooleansolve(intnumQueens,intwhichCol)
{
//Bottomoutcondition1:
if(numQueens==0){
//Nonetoassigndone.
returntrue;
}

//Bottomoutcondition2:
if(whichCol>=board.size()){
//Nocolumnslefttotrydone.
returnfalse;
}

//Tryeveryunforbiddenspotineachrow.
for(introw=0;row<board.size();row++){
if(!board.isForbidden(row,whichCol)){

http://www.seas.gwu.edu/~drum/cs1112/lectures/module9/module9.html

19/20

1/15/2016

AlgorithmsandDataStructuresI

//Trythislocation.
board.addQueen(row,whichCol);

booleansolutionExists=solve(numQueens1,whichCol+1);
if(solutionExists){
returntrue;
}
//Else,undo
board.removeQueen(row,whichCol);
}
}

//Couldn'tfindasolution.
returnfalse;
}
}

http://www.seas.gwu.edu/~drum/cs1112/lectures/module9/module9.html

20/20

You might also like