The Towers of Hanoi Puzzle: An Iterative Solution

By derek.illchuk, June 8, 2010 8:19 pm

Reading through the New Turing OmniBus: 66 Excursions in Computer Science, I turned upon the classic Towers of Hanoi Puzzle. The recursive solution, as many know, is mind-blowing in it’s simplicity; the first time I saw it, I remember saying, “OK… and then what?”

function hanoi( n, from, dest, aux )
{
  if ( n == 1 )
    printline 'Move the plate from ' + from + ' to ' + dest
  else
    hanoi( n-1, from, aux, dest )
    hanoi( 1, from, dest, aux )
    hanoi( n-1, aux , dest, from )
  endif
end



hanoi

The book goes on to present an iterative solution, as follows:

A. Always move the smallest disc first in a “clockwise” manner.

B. Then, move the smaller remaining disc onto the the other (in fact, that’s the only option).

C. Repeat A & B until finished.




Here’s a straightforward implementation (download).

#include <iostream>
#include <vector>
 
using namespace std;
typedef unsigned int uint32;
typedef int int32;
 
typedef uint32 Stack;
typedef uint32 Disc;
 
Stack next_stack( Stack curr_stack )
{
  return ( curr_stack + 1 ) % 3;
}
 
int32 main( void )
{
  cout << "Calculating tower of hanoi moves" << endl;
  cout << "Enter the number of discs: ";
  uint32 num_discs = 0; cin >> num_discs;
 
  /**
   * Set up the stacks, with discs loaded onto the first one.
   */
  vector<vector> stacks;
  for ( Stack stack_id = 0; stack_id < 3; stack_id++ ) {
    stacks.push_back(
      vector( 1, num_discs+1 ) // sentinel to avoid empty-stack logic
    );
  }
  Stack curr_stack = 0;
  for ( Disc disc = num_discs; disc > 0; disc-- ) {
    stacks[curr_stack].push_back( disc );
  }
 
  uint32 num_moves = 0;
  while ( true ) {
 
    /**
     * Smallest disc always moved one over.
     */
    Disc disc1 = stacks[curr_stack].back();
    stacks[curr_stack].pop_back();
    curr_stack = next_stack( curr_stack );
    stacks[curr_stack].push_back( disc1 );
    num_moves++;
 
    /**
     * Remaining move is forced.
     */
    Stack from_stack = next_stack( curr_stack );
    Stack to_stack = next_stack( from_stack );
    if ( stacks[from_stack].back() > stacks[to_stack].back() ) {
      Stack temp_stack = from_stack;
      from_stack = to_stack;
      to_stack = temp_stack;
    }
    Disc disc2 = stacks[from_stack].back();
    stacks[from_stack].pop_back();
    if ( stacks[from_stack].empty() ) { // we're done
      break;
    }
    stacks[to_stack].push_back( disc2 );
    num_moves++;
  }
 
  cout << "Total moves:" << num_moves << endl;
 
  return 0;
}



Is this particular iterative solution better than the recursive one? Aside from being a nice little exercise, no, it’s not that impressive. It takes longer to run than the recursive solution and requires more code. But, I think it’s easy to get how it works: “Move smallest clockwise then move what you can, repeat until we’re done.”.

There are iterative solutions out there that are much quicker, but they start to look like this:

void hanoi(void)
{
  int x, fr, to;
  unsigned int i, j;
 
  for (x=1; x < (1 << N); x++) {
    i=(x|x-1)+1; to=(i+i/3)&3;
    i=x&x-1; fr=(i+i/3)&3;
    for(i=x, j=1; ; i>>=1, j++) {
      if(i&1) break;
    }
  }
}

Leave a Reply

Panorama Theme by Themocracy