-1

The Towers of Hanoi is very interesting and hard problem, which I assume we all know, but if someone does not here it is:

Towers of Hanoi problem

I have been searching and trying to implement a complete C++ solution, where by "complete" I mean that for a given number of disks the program calculates the steps needed and prints out every step and current state of every rod. Where the rods are represented as stacks.

For example let's take 3 disks. The output in this case must be:

Enter number of disks: 3
Source: 3, 2, 1
Destination: empty rod
Spare: empty rod
----------------------------
Step #1: Moved disk 1
Source: 3, 2
Destination: 1
Spare: empty rod
----------------------------
Step #2: Moved disk 2
Source: 3
Destination: 1
Spare: 2
----------------------------
Step #3: Moved disk 1
Source: 3
Destination: empty rod
Spare: 2, 1
----------------------------
Step #4: Moved disk 3
Source: empty rod
Destination: 3
Spare: 2, 1
----------------------------
Step #5: Moved disk 1
Source: 1
Destination: 3
Spare: 2
----------------------------
Step #6: Moved disk 2
Source: 1
Destination: 3, 2
Spare: empty rod
----------------------------
Step #7: Moved disk 1
Source: empty rod
Destination: 3, 2, 1
Spare: empty rod
----------------------------

I'm having a very BIG trouble and headache when I try to do that with C++. I start with making the stacks hardcoded just to test the problem and attain the following:

#include <iostream>
#include <stack>

std::stack<int> src;
std::stack<int> dest;
std::stack<int> spare;

int setTowers()
{
    int disks;
    std::cout << "Enter number of disks: ";
    std::cin >> disks;

    for (int i = 0; i < disks; i++) src.push(disks - i);
    return disks;
}

void printRod(std::stack<int>tower)
{
    std::stack<int>temp;
    while (!tower.empty())
    {
        temp.push(tower.top());
        tower.pop();
    }
    if (!temp.size()) std::cout << "empty rod\n";
    else
    {
        while (!temp.empty())
        {
            std::cout << temp.top();
            temp.pop();
            if (temp.size() != 0) std::cout << ", ";
        }
        std::cout << '\n';
    }
}

void PrintRods()
{
    std::cout << "Source: "; printRod(src);
    std::cout << "Destination: ", printRod(dest);
    std::cout << "Spare: ", printRod(spare);
    std::cout << "----------------------------\n";
}

void MoveDisks(int disks, std::stack<int>& src, std::stack<int>& dest, std::stack<int>& spare,unsigned& stepsTaken)
{
    if (disks < 1)  return; 
    else if (disks == 1)
    {
        stepsTaken++;
        dest.push(src.top());
        src.pop();
        std::cout << "Step #" << stepsTaken << ": Moved disk " << disks << '\n';
        PrintRods();
        return;
    }
    else
    {
        MoveDisks(disks - 1, src, spare, dest, stepsTaken);
        stepsTaken++;
        dest.push(src.top());
        src.pop();
        std::cout << "Step #" << stepsTaken << ": Moved disk " << disks << '\n';
        PrintRods();
        MoveDisks(disks - 1, spare, dest, src, stepsTaken);
    }
}
int main()
{
    unsigned stepsTaken(0);
    int disks = setTowers();
    PrintRods();
    MoveDisks(disks, src, dest, spare, stepsTaken);
    return 0;
}

which works just fine, BUT when I try to make the stacks not hard coded the result collapses. It gives wrong result like:

Enter number of disks: 3
Source: 3, 2, 1
Destination: empty rod
Spare: empty rod
----------------------------
Step #1: Moved disk 1
Source: 3, 2
Destination: 1
Spare: empty rod
----------------------------
Step #2: Moved disk 2
Source: 3
Destination: 1
Spare: 2
----------------------------
Step #3: Moved disk 1
Source: empty rod
Destination: 2, 1
Spare: 3
----------------------------
Step #4: Moved disk 3
Source: empty rod
Destination: 2, 1
Spare: 3
----------------------------
Step #5: Moved disk 1
Source: 2
Destination: 1
Spare: 3
----------------------------
Step #6: Moved disk 2
Source: empty rod
Destination: 1
Spare: 3, 2
----------------------------
Step #7: Moved disk 1
Source: empty rod
Destination: 3, 2, 1
Spare: empty rod
----------------------------

or even worse when I try to fix it more deeply.

Can someone PLEASE help me how to move the stacks inside the main function?

code_fan
  • 11
  • 2
  • Did you try using a debugger to step through your code? – L. F. Sep 05 '19 at 13:26
  • I have somewhat trouble to under stand what you are trying to do. Which stack do you want to move to your main function? – Detonar Sep 05 '19 at 13:29
  • 1
    This needs a minimal complete and verifiable example. Emphasis on Minimal and Complete. You need to remove all this print and show the actual problem. Don't make us guess what it is. For me, I look at the bottom of the long print and see that the program succeeded! Also you say you try to make it not hardcoded, but what does that mean? Show the code that produces each output. – Fantastic Mr Fox Sep 05 '19 at 13:33
  • 1
    What do you mean by "making the stack not hardcoded"? – Jeffrey Sep 05 '19 at 13:37
  • If I understood you right, you want to make the stacks `src`, `dest`, and `spare` local variables in `main()`. So, you have to pass them to every function as arguments. If you want to help concerning your failed attempt you should present **this** instead of your previous attempt which is running fine. Btw. I compared the good result with the bad (in WinMerge). I struggled a bit to find out why the 2nd should be bad - it looked quite reasonable. Actually, the right stacks just seems to be labeled wrong. The trick with Towers of Hanoi is that the rods swap its role in each recursion level. – Scheff's Cat Sep 05 '19 at 13:56
  • Hence, the solution you are IMHO searching for is - how to pair the stacks/rods with the correct label for printing. And, that's actually the solution I would recommend: Use e.g. `std::pair` to "attach" the label of the stack to the stack itself. Then `printRod()` can use the correct label when printing it regardless how they have been swapped in recursion levels. – Scheff's Cat Sep 05 '19 at 13:58
  • @Scheff you mean when I put the stacks in the main function to make 3 pairs of every stack and corresponding string? – code_fan Sep 05 '19 at 14:24
  • I mean [**this**](http://coliru.stacked-crooked.com/a/a04bbd4dadd9c298). ;-) Of course, instead of `std::pair`, you just can wrap `std::string` and `std::stack` in your own `struct Rod` with better member names than `first` and `second`. – Scheff's Cat Sep 05 '19 at 14:31
  • I really wish to see how it would look with pairs or with additional set of of references as @BufferSpoofer advices, but I guess that won't happen so I will remain stupid. I just cannot manage to do it with pairs, even though I get the idea. It spits out a whole universe of errors which I manage to repair some of them but... – code_fan Sep 05 '19 at 14:49

1 Answers1

1

When recursion occurs the "src", "dest" and "spare" references are swapped, so if you pass those references to the PrintRods() function it will output the stacks in the wrong order.

To get around this you could have an additional set of references to the stacks as parameters to the MoveDisks() function.

Try this (it is not pretty but it works):

#include<iostream>
#include<stack>
using namespace std;
int setTowers(std::stack<int>& src)
{
    int disks;
    std::cout << "Enter number of disks: ";
    std::cin >> disks;

    for (int i = 0; i < disks; i++) src.push(disks - i);
    return disks;
}

void printRod(std::stack<int>tower)
{
    std::stack<int>temp;
    while (!tower.empty())
    {
        temp.push(tower.top());
        tower.pop();
    }
    if (!temp.size()) std::cout << "empty rod\n";
    else
    {
        while (!temp.empty())
        {
            std::cout << temp.top();
            temp.pop();
            if (temp.size() != 0) std::cout << ", ";
        }
        std::cout << '\n';
    }
}

void PrintRods(std::stack<int>& src, std::stack<int>& dest, std::stack<int>& spare)
{
    std::cout << "Source: "; printRod(src);
    std::cout << "Destination: ", printRod(dest);
    std::cout << "Spare: ", printRod(spare);
    std::cout << "----------------------------\n";
}

void MoveDisks(int disks, std::stack<int>& src, std::stack<int>& dest, std::stack<int>& spare,std::stack<int>&a,std::stack<int>&b,std::stack<int>&c,unsigned& stepsTaken)
{
    if (disks < 1)  return;
    else if (disks == 1)
    {
        stepsTaken++;
        dest.push(src.top());
        src.pop();
        std::cout << "Step #" << stepsTaken << ": Moved disk " << disks << '\n';
        PrintRods(a,b,c);
        return;
    }
    else
    {
        MoveDisks(disks - 1, src, spare, dest,a,b,c,stepsTaken);
        stepsTaken++;
        dest.push(src.top());
        src.pop();
        std::cout << "Step #" << stepsTaken << ": Moved disk " << disks << '\n';
        PrintRods(a,b,c);
        MoveDisks(disks - 1, spare, dest, src, a,b,c,stepsTaken);
    }
}
int main()
{
    std::stack<int> src;
    std::stack<int> dest;
    std::stack<int> spare;

    unsigned stepsTaken(0);
    int disks = setTowers(src);
    PrintRods(src, dest, spare);
    MoveDisks(disks, src, dest, spare,src,dest,spare,stepsTaken);
    return 0;
}
BufferSpoofer
  • 108
  • 1
  • 5