
#include "comb/perm-gray-wells.h"

#include "comb/comb-print.h"

#include "demo/nextarg.h"
#include "fxtio.h"
#include "fxttypes.h"
#include "jjassert.h"


//#include "comb/fact2perm.h"
//#include "perm/perminvert.h"


//% Two Gray codes for permutations (Wells' order and a variant of it), CAT algorithm.

//#define TIMING // uncomment to disable printing

#define INVERSE  // define to show inverse permutations

int
main(int argc, char **argv)
{
    ulong n = 5;
    NXARG(n, "Number of elements to permute");
    ulong r = 0;
    NXARG(r, "Ordering:"
          "\n    0 ==> Wells' order == Lipski(8),"
          "\n    1 ==> Lipski(14),"
          "\n    2 ==> Lipski(15)");
    cout << endl;

    bool dfz= true; // whether to print dots for zeros

    perm_gray_wells P(n, r);
    P.first();

    const ulong *x = P.data();
#ifdef INVERSE
    ulong *xi = new ulong[n];  // inverse permutations
    for (ulong k=0; k<n; ++k)  xi[k] = k;
#endif // INVERSE

    ulong ct = 0;
    do
    {
        ++ct;
#ifndef TIMING
        cout << setw(4) << ct << ":";
        print_perm("    ", x, n, dfz);

        ulong sw1, sw2;
        P.get_swap(sw1, sw2);
        cout << "     (" << sw1 << ", " << sw2 << ") ";


        print_mixedradix("    ", P.d_, n-1, dfz);

#ifdef INVERSE
        cout << "    ";
        swap2( xi[x[sw1]], xi[x[sw2]]);  // update inverse permutation
        print_perm("    ", xi, n, dfz);
//        perm2rfact(xi, n, rfc);
//        print_mixedradix("    ", rfc, n-1, dfz);
#endif // INVERSE

        cout << endl;
#endif
    }
    while ( P.next() );

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

#ifdef INVERSE
    delete [] xi;
#endif

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

/*
Timing:
 time ./bin 12 1
 ct=479001600
./bin 12  5.18s user 0.04s system 99% cpu 5.236 total
 ==>  479001600/5.18 == 92,471,351  per second

 time ./bin 12 0
 ct=479001600
./bin 12 0  4.97s user 0.03s system 99% cpu 4.995 total
 ==>  479001600/4.97 == 96,378,591  per second
*/


/// Emacs:
/// Local Variables:
/// MyRelDir: "demo/comb"
/// makefile-dir: "../../"
/// make-target: "1demo DSRC=demo/comb/perm-gray-wells-demo.cc"
/// make-target2: "1demo DSRC=demo/comb/perm-gray-wells-demo.cc DEMOFLAGS=-DTIMING"
/// End:
