
// demo-is-self-contained

#include "comb/comb-print.h"

#include "fxtiomanip.h"
#include "fxttypes.h"
#include "demo/nextarg.h"

//% Fredericksen, Kessler, Maiorana (FKM) algorithm for generating necklaces.

//#define TIMING // uncomment to disable printing

int
main(int argc, char **argv)
{
    ulong n = 6;
    NXARG(n, "Length of necklaces (n>=1)");
    ulong k = 2;
    NXARG(k, "Number of different beads (k>=2)");
    ulong *f = new ulong[n+1];  // 1-based, with sentinel at index zero
    f[0] = 0;

    for (ulong i=1; i<=n; ++i)  f[i] = 0;  // Initialize to 0
    ulong pct = 0, nct = 0, lct = 0;  // count pre-necklaces, necklaces and Lyndon words
    bool nq = 1;  // whether pre-necklace is a necklace
    bool lq = 0;  // whether pre-necklace is a Lyndon word
    ulong j = 1;
    while ( 1 )
    {
        ++pct;
        if ( nq )  ++nct;
        if ( lq )  ++lct;

        // Print necklace:
#ifndef TIMING
        cout << setw(4) << pct << ":";
        print_vec("    ", f+1, n, true);
        cout << "   j=" << j;
        if ( nq )  cout << "  N";
        if ( lq )  cout << "  L";
        cout << endl;
#endif  // TIMING


        // Find largest index where we can increment:
        j = n;
        while ( f[j]==k-1 )  { --j; };

        if ( j==0 )  break;

        ++f[j];

        // Copy periodically:
        for (ulong i=1,t=j+1; t<=n; ++i,++t)  f[t] = f[i];

        nq = ( (n%j)==0 );  // necklace if j divides n
        lq = ( j==n );      // Lyndon word if j equals n
    }

    cout << "" << pct << " (" << n << ", " << k << ") pre-necklaces." << endl;
    cout << "" << nct << " necklaces and " << lct << " Lyndon words." << endl;

    delete [] f;

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

/*
Timing:

 time ./bin 32 2
arg 1: 32 == n  [Length of necklaces (n>=1)]  default=6
arg 2: 2 == k  [Number of different beads (k>=2)]  default=2
Generated 277737797 (32, 2) pre-necklaces.
Generated 134219796 necklaces and 134215680 Lyndon words.
./bin 32  11.67s user 0.06s system 99% cpu 11.733 total
  23,671,507 pre-necklaces per second

BENCHARGS=32 2

*/


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

