#include <iostream>
#include <map>
using namespace std;

/* Consider a bee walking on a honeycomb (hexagonal tiling of the plane).
For given n, count the number of n-step paths that end at the same cell from which they started.  Each step is from a honeycomb cell to an adjacent cell.

For example there are 6 two step paths from a cell back to the same cell and there are 12 3 step paths.
*/

typedef pair<int, int> cell;

ostream& operator<< (ostream& out, const cell& a) 
{ return out << "[" << a.first << "," << a.second << "]"; }

// A cell is denoted by an integer (i, j) point whose sum i + j is even.

cell nbr(cell c, int i)
// precondition: 0 <= i < 6.
// postcondition: returns one of the 6 neighbors of c (in an arbitrary order)
{
	switch (i)
	{
		case 0: return cell(c.first + 2, c.second); 
		case 1: return cell(c.first - 2, c.second); 
		case 2: return cell(c.first + 1, c.second + 1); 
		case 3: return cell(c.first + 1, c.second - 1); 
		case 4: return cell(c.first - 1, c.second + 1); 
		case 5: return cell(c.first - 1, c.second - 1); 
	}
}

inline int abs(int x){ return x < 0 ? -x : x;}

bool neighbor (const cell& a, const cell& b)
// Precondition: valid cells
// Postcondition: returns true iff a and b are adjacent cells (have edge in common).
{  return a.first != b.first && 2 == abs(a.first - b.first) + abs(a.second - b.second) ; }

struct WaysObject
/* This class captures "global" data associated with the ways() function, such as the memo table, flags to determine how some aspects like memoization and base cases are handled, a counter to record how many recursive calls get made.
*/
{
  int operator()(cell a, cell b, int n) { return ways(a, b, n); }

  WaysObject(bool m, bool b) : callCount(0), memoize(m), usingBaseCaseOne(b) {}

  void reset(bool m, bool b) { memoTable.clear(); callCount = 0; memoize = m; usingBaseCaseOne = b; }

  int ways(cell a, cell b, int n)
  // Postcondition: returns the number of paths of length n from a to b.
  // Precondition: 0 <= n <= 14 
  // The boolean "memoize" allows us to try it with and without memoization.
  // The boolean "usingBaseCaseOne" allows us to try it with and without handling the 
  // case n == 1 directly (rather than recursion down to the case n == 0).
  // 
  // Beyond n = 14, 32 bit ints do not suffice for the counting.
  {
    //cout << "ways(" << a << ", " << b << ", " << n << ")" << endl;
    ++callCount;
    int w, i;
    if (n == 0) 
      return (a == b) ? 1 : 0;
    else if (usingBaseCaseOne && n == 1) 
      return neighbor(a, b) ? 1 : 0;
    else if ( memoize && (w = memoTable[triple(cellpair(a, b), n)]) != 0 ) 
      // we are using a previous memoization.
      return w;
    else // compute and then make a note of it for future use.
    {
      for (w = 0, i = 0; i < 6; ++i) w += ways(a, nbr(b, i), n-1);
      // now the memoization.
      if (memoize) memoTable[triple(cellpair(a, b), n)] = w; 
      return w;
    }
  }

  // Datatype for the memoTable keys
  typedef pair<cell, cell> cellpair;
  typedef pair<cellpair, int> triple;

  // table for memoization.  
  map < triple, int > memoTable;

  // vars modifying details of what happens.
  bool memoize;
  bool usingBaseCaseOne;

  int callCount; // for counting the number of calls to ways() function.

};

int main(int ac, char* av[])
{
  cell origin(0,0);
  if (ac != 4)
  { cerr << "usage: " << av[0] << "<n> <m> <b>" << endl;
    cerr << "<n> is the path length (0 <= n <= 14)," << endl;
    cerr << "<m> (0 or 1) indicates whether to use memoization, m = 1 means yes, and" << endl;
    cerr << "<b> (0 or 1) indicates whether to use the base case at n = 1." << endl;
    return 0; 
  }
  int n = atoi(av[1]);
  WaysObject ways(*av[2] == '1', *av[3] == '1'); // initialize callCount, memoize, and usingBaseCaseOne.

  int m = ways(origin, origin, n);

  cout << "For n = " << n << ", number of ways is " << m << endl;
  cout << "Number of calls to the ways function is " << ways.callCount << endl;
  cout << "memoize is " << ways.memoize << ", usingBaseCaseOne is " << ways.usingBaseCaseOne << endl;
}
