Thread: Modded Tower of Hanoi

  1. #1
    Registered User
    Join Date
    Sep 2006
    Posts
    26

    Modded Tower of Hanoi

    Okay, so here's a modded tower of hanoi problem:


    Instead of 3, we have 4 pegs, a source peg, a target peg, and 2 auxiliary pegs. Disks can
    be moved from any stack to any other stack, with one exception. Direct moves between
    the auxiliary pegs are not allowed. (Naturally, we maintain the rule that we cannot put
    a larger disk on top of a smaller disk.)
    As a data structure, you use an array of four stacks (with source being stack number 0 and
    target being stack number 3). A simple array implementation of the stacks themselves is
    sufficient. If you use a global array of stacks then the various procedures (called functions in
    C++) can just pass the array indices instead of actual stacks.
    You may assume n < 100. You may encode the bottom of each stack by a disk of size
    n + 1 that is never moved.


    Here's my Main function: I get an error trying to pass the stack array through the function...it's been a few years since I've coded at all and I am stumped.

    Code:
    #include <iostream>
    #include <stack>
    using namespace std; 
    int counter = 0;
    int m;
    stack<int> Peg[4];
    
    int main ()  
    { 
        int n = 0; 
        counter = 0;  
    
        cout << "Please enter a number between 1 and 100: "; 
        cin >> n; 
        cout << endl; 
        cout << "OK. Run Towers of Hanoi puzzle with " << n << " disks:" << endl; 
        cout << endl; 
        Peg[0].push(n+1);
    	Peg[1].push(n+1);
    	Peg[2].push(n+1);
    	Peg[3].push(n+1);
    	
    	for(int x=n; x > 0; x--)
    	{
    		Peg[0].push(x);
    	} 
    
    	Hanoi(n, Peg[0],Peg[1],Peg[2]);
    
        cout << endl; 
        cout << "That took " << counter << " moves." << endl; 
        cout << endl; 
    
        system ("PAUSE"); 
        return 0; 
    }
    Error stems from bolded portion.

    Anyway, so now I can not test and do the rest of the assignment, but want to make sure I'm on the right track

    2.
    Write a procedure move(i, j) to move the top disk of stack i to the top of stack j. The
    procedure tests whether i 6= j and whether a direct move from stack i to stack j is
    allowed, i.e., {i, j} is not the set of auxiliary stacks. The procedure also has to test
    whether the newly moved disk is indeed smaller than the disk on which it is placed.
    This procedure operates on a globally defined array of stacks. Naturally, it is a bit of
    a waste to do these tests at run time, but it should improve the confidence that your
    solutions are correct.
    Let m be a global variable, being the initial value of n, i.e., the total number of disks.
    If m 5, then move(i, j) should also produce the line of output, “move from i to j”.
    In any case, move(i, j) should also increment a global counter s counting the number of
    steps. The counter is output once at the end.


    Code:
    void Move(int i,int j)
    {
    	if(Peg[a].top() < Peg[j].top() && (a*j != 2))
    	{
    		Peg[j].push(Peg[a].top());
    		Peg[a].pop();
    		counter++;
    		cout<<"move disk " << a << " to " << j << " Moves: " << counter << endl;
    	}
    	else cout << "invalid";
    }
    This should be correct, I just haven't implemented only showing moves if m < 5.

    3.
    Write a procedure hanoi(n, s, t, u) for the regular Tower of Hanoi problem to move n
    disks from peg s to peg t with the help of the auxiliary peg u.


    Code:
    void Hanoi(int n, int from, int to, int aux)
    { 
    	if(n>0)
    	{
    		Hanoi(n-1,from,aux,to); 
    		Move(from,to); 
    		Hanoi(n-1,aux,to,from);
    	}
    }
    This, too, should be the correct algorithm for the original tower of hanoi problem


    4.
    Now we deal with the Tower of Hanoi problem with 2 auxiliary pegs. The task is to
    move n disks from source peg s to a target peg t with the help of 2 auxiliary pegs u and
    v.

    (a) Write a simple procedure simple long edge(n, s, t, u, v) based on calls to hanoi only.
    For a good choice of k, move k disks from s to u, then the remaining n − k disks
    from s to t, and finally the k disks from u to t.


    Code:
    Simple_long(int i,int from,int to,int aux1,int aux2) 
    {
    	int k=i/2; 
    	Hanoi(k, from,aux2,to); 
    	Hanoi(1-k,from,to,aux1); 
    	Hanoi(k, aux2,to,from);
    }
    I haven't optimized this yet, just initially choosing k at half of the stack. Other than that, that should be right as well.


    5.
    Write 3 procedures which might call each other. Run each of the procedures for n = 4
    and n = 20.
    You can get 20 points for each. 5 for describing the idea, 5 for the solution being nicely
    structured, 5 for a correct solution, and 5 for the output. You receive the first 10 points
    only if your solution is non-trivial, i.e., not just a call to hanoi.
    (a) Write a procedure short edge(n, s, t, u, v) moving n disks from s to t in the case
    where no direct moves between t and v are allowed.


    Code:
    Short_edge(int i, int from, int to, int aux1, int aux2)
    {
    	if (i==1) 
    		move(from,to); 
    	if (i==2) 
    		Hanoi(1-k,from,to,aux1); 
    	if(i>2) 
    	{
    		Short_edge(i/2,from,aux1,to,aux2); 
    		Hanoi(i-1/2,from,to,aux2); 
    		short_edge_back(i/2-1,aux1,from,aux2,to);  
    		move(aux1,aux2); 
    		move(aux2,to); 
    		short_edge(i/2-1,from,to,aux1,aux2);
    	}
    }
    This one I'm not completely sure on the algorithm....

    (b) Write a procedure short edge backward(n, s, t, u, v) moving n disks from s to t in
    the case where no direct moves between s and v are allowed.


    Code:
    Short_edge_back(int i, int from, int to, int aux1, int aux2)
    {
    	if(i>3)
    	{
    		Short_edge_back(i/2-1,from,to,aux1,aux2);
    		move(from,aux1);
    		move(aux1,aux2);
    		Short_edge(i/2,to,aux2,from,aux1);
    		Hanoi(aux1,to,from);
    		Short_edge_back(aux2,to,aux1,from);
    	}
    }
    I haven't hard coded if there are only 1 or 2 disks, but the logic seems right to me.

    (c) Write a procedure long edge(n, s, t, u, v) moving n disks from s to t in the case
    where no direct moves between u and v are allowed.


    This one kind of has me stumped :\



    If you need anything else, just let me know. Thanks in advance for any help


    EDIT: NEvermind on the error, I don't know what I was thinking, I can just use Hanoi(n, 1, 2, 3); lol, whoops.
    Last edited by Saggio; 09-12-2007 at 02:39 PM.

  2. #2
    Frequently Quite Prolix dwks's Avatar
    Join Date
    Apr 2005
    Location
    Canada
    Posts
    8,057
    Unless they're constructors for classes, many of your functions are missing a return type -- probably void.

    You never use counter in main(), so it will always be zero. Perhaps you should use the return value of Hanoi to count the number of moves . . .
    dwk

    Seek and ye shall find. quaere et invenies.

    "Simplicity does not precede complexity, but follows it." -- Alan Perlis
    "Testing can only prove the presence of bugs, not their absence." -- Edsger Dijkstra
    "The only real mistake is the one from which we learn nothing." -- John Powell


    Other boards: DaniWeb, TPS
    Unofficial Wiki FAQ: cpwiki.sf.net

    My website: http://dwks.theprogrammingsite.com/
    Projects: codeform, xuni, atlantis, nort, etc.

  3. #3
    Registered User
    Join Date
    Sep 2006
    Posts
    26
    That's because I wrote pseudo-code in word, I didn't include the return types.


    Anyway, now that I got past that, I still can't get it to run properly. It goes through one move then crashes at the bold point.

    I tried to debug it, and it seems that the second time it goes to the Move() function, Peg[i] is empty for some reason....

    Code:
    void Move(int i,int j)
    {
    	if(Peg[i].top() <= Peg[j].top() /*&& (i*j != 2)*/)
    	{
    		Peg[j].push(Peg[i].top());
    		Peg[i].pop();
    		counter++;
    		cout<<"move disk " << i << " to " << j << " Moves: " << counter << endl;
    	}
    	else cout << "invalid";
    }
    
    
    void Hanoi(int n, int from, int to, int aux)
    { 
    	if(n>0)
    	{
    		Hanoi(n-1,from,aux,to); 
    		Move(to,from); 
    		Hanoi(n-1,aux,to, from);
    	}
    }

    Here's my main functino again if you need it:

    Code:
    int main ()  
    { 
        int n = 0; 
        counter = 0;  
    
        cout << "Please enter a number between 1 and 100: "; 
        cin >> n; 
        cout << endl; 
        cout << "OK. Run Towers of Hanoi puzzle with " << n << " disks:" << endl; 
        cout << endl; 
        Peg[0].push(n+1);
    	Peg[1].push(n+1);
    	Peg[2].push(n+1);
    	Peg[3].push(n+1);
    	
    	for(int x=n; x > 0; x--)
    	{
    		Peg[0].push(x);
    	} 
    
    	Hanoi(n,1,2,3);
    
        cout << endl; 
        cout << "That took " << counter << " moves." << endl; 
        cout << endl; 
        return 0; 
    }
    NOTE: I'm still just trying to get the regular 3 peg tower of hanoi problem to work correctly.

  4. #4
    Registered User
    Join Date
    Sep 2006
    Posts
    26
    Okay, I figured out some stuff:

    Here's my new code if anyone is interested:

    Code:
    void Move(int i,int j)
    {
    	if(Peg[i].top() <= Peg[j].top() /*&& (i*j != 2)*/)
    	{
    		Peg[j].push(Peg[i].top());
    		Peg[i].pop();
    		counter++;
    		if(m <= 5)
    			cout<<"move disk " << i << " to " << j << " Moves: " << counter << endl;
    	}
    	else cout << "invalid";
    }
    
    void Hanoi(int n, int from, int to, int aux)
    { 
    	if(n>0)
    	{
    		Hanoi(n-1,from,aux,to); 
    		Move(from,to); 
    		Hanoi(n-1,aux,to,from);
    	}
    }
    
    
    int main ()  
    { 
        int n = 0; 
        counter = 0;  
    
        cout << "Please enter a number between 1 and 100: "; 
        cin >> n; 
    
    	m = n;
        cout << endl; 
        cout << "OK. Run Towers of Hanoi puzzle with " << n << " disks:" << endl; 
        cout << endl; 
        Peg[0].push(n+1);
    	Peg[1].push(n+1);
    	Peg[2].push(n+1);
    	Peg[3].push(n+1);
    	Peg[4].push(n+1);
    	
    	for(int x=n; x > 0; x--)
    	{
    		Peg[1].push(x);
    	} 
    
    	Hanoi(n,1,2,3);
    
    	//Simple_long(n,1,2,3,4);
    
        cout << endl; 
        cout << "That took " << counter << " moves." << endl; 
        cout << endl; 
        return 0; 
    }
    Basically, I mixed up some stuff implementing the algorithm I had to look over, and It messed up when I tried to send 0 since it tried to store it as a peg # too, so I had to send pegs 1,2,3 (and 1,2,3,4 when I needed 4). probably not the neatest way to fix it, but it fixes it, heh...

    I also figured out the one with 4 towers:

    Code:
    void Simple_long(int i,int from,int to,int aux1,int aux2) 
    {
    	int k=i/2; 
    	Hanoi(k, from,aux2,to); 
    	Hanoi(1-k,from,to,aux1); 
    	Hanoi(k, aux2,to,from);
    }
    it finds the minimum amount of moves with 2 auxiliary pegs. k is the amount of pegs it does first. I just naturally went with 1/2...probably a better number based on the amount of pegs.

    Anyway, now I'm trying to figure out this one:

    Write a procedure short edge(n, s, t, u, v) moving n disks from s to t in the case
    where no direct moves between t and v are allowed.


    t and v being the destination peg and the second aux peg, respectively.

    Code:
    void Short_edge(int i, int from, int to, int aux1, int aux2)
    {
    	if (i==1) 
    		Move(from,to); 
    	if (i==2) 
    		Hanoi(i,from,to,aux1); 
    	if(i>2) 
    	{
    		Short_edge(i/2,from,aux1,to,aux2); 
    		Hanoi(i-i/2,from,to,aux2); 
    		Short_edge_back(i/2-1,aux1,from,aux2,to);  
    		Move(aux1,aux2); 
    		Move(aux2,to); 
    		Short_edge(i/2-1,from,to,aux1,aux2);
    	}
    }

    and it does work, kind of...it compiles and runs, but anything over 5 disks and it starts having invalid moves. the higher the number, the higher the number of invalid moves...

    Can anyone see any flaws in the algorithm?

    EDIT: Crap, I forgot that there's a call to another one of my functions, which is the next part of the question:

    Write a procedure short edge backward(n, s, t, u, v) moving n disks from s to t in
    the case where no direct moves between s and v are allowed.


    and here's what I have, this actually might be where it's messed up:

    Code:
    void Short_edge_back(int i, int from, int to, int aux1, int aux2)
    {
    	if(i>3)
    	{
    		Short_edge_back(i/2-1,from,to,aux1,aux2);
    		Move(from,aux1);
    		Move(aux1,aux2);
    		Short_edge(i/2,to,aux2,from,aux1);
    		Hanoi(i/2-1,aux1,to,from);
    		Short_edge_back(i/2-1,aux2,to,aux1,from);
    	}
    }
    Last edited by Saggio; 09-12-2007 at 06:04 PM.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Tower of Hanoi
    By dmkanz07 in forum C Programming
    Replies: 13
    Last Post: 03-29-2007, 12:37 PM
  2. towers of hanoi problem
    By aik_21 in forum C Programming
    Replies: 1
    Last Post: 10-02-2004, 01:34 PM
  3. Tower of Hanoi
    By carrja99 in forum C++ Programming
    Replies: 2
    Last Post: 02-09-2003, 12:15 PM
  4. Hanoi tower
    By Unregistered in forum C Programming
    Replies: 3
    Last Post: 04-24-2002, 06:35 PM
  5. Tower Of Hanoi
    By Unregistered in forum C Programming
    Replies: 7
    Last Post: 12-18-2001, 11:12 PM