
// demo-is-self-contained

#include "comb/comb-print.h"

#include "fxttypes.h"
#include "fxtiomanip.h"
#include "jjassert.h"
#include "nextarg.h"


//% Recursive generation of a curious Gray code ("cgray" order) for mixed radix numbers.

// Cf. mixedradix-cgray-demo.cc for an iterative generator.


ulong N;
ulong K;
ulong *rv;  // digits of mixed radix number

ulong ct;   // count objects


void visit()
{
    ++ct;
    cout << setw(4) << ct << ":";
    print_vec("  ", rv, N, 1);
    cout << endl;
}
// -------------------------

void
rec(ulong n, bool z=true)
{
    if ( n==N )
    {
        visit();
        return;
    }

    const ulong k = K;  // fixed radix
//    const ulong k = n + 2;  // rising factorial basis
//    const ulong k = N - n + 1;  // falling factorial basis

    if ( z )  // forward:
    {
        ulong j = 1;
        while ( j<k )
        {
            rv[n] = j;
            for (ulong i=n+1; i<N; ++i)  rv[i] = 0;
            visit();
            ++j;
        }

        if ( n < N - 1 )
        {
            --j;
            do
            {
                rv[n] = j;
                rec(n+1, z);
                z = ! z;
            }
            while ( j-- );
        }
    }
    else     // backward:
    {
        if ( n < N - 1 )
        {
            if ( (k%2) != 0 )  z = !z;  // fixup for odd K

            ulong j = 0;
            do
            {
                z = ! z;
                rv[n] = j;
                rec(n+1, z);
            }
            while ( ++j < k );
        }

        ulong j = k - 1;
        while ( j>0 )
        {
            rv[n] = j;
            for (ulong i=n+1; i<N; ++i)  rv[i] = 0;
            visit();
            --j;
        }
    }
}
// -------------------------

int
main(int argc, char **argv)
{
    N = 3;
    NXARG(N, "Number of digits");
    K = 4;
    NXARG(K, "Radix");

    rv = new ulong[N];
    for (ulong j=0; j<N; ++j)  rv[j] = 0;

    ct = 0;
    visit();
    rec(0);

    cout << "ct=" << ct << endl;

    delete [] rv;

    return 0;
}
// -------------------------


/// Emacs:
/// Local Variables:
/// MyRelDir: "demo/comb"
/// makefile-dir: "../../"
/// make-target: "1demo DSRC=demo/comb/mixedradix-cgray-rec-demo.cc"
/// make-target2: "1demo DSRC=demo/comb/mixedradix-cgray-rec-demo.cc DEMOFLAGS=-DTIMING"
/// End:
