
// demo-is-self-contained

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


//% Run length limited (RLL) Words (at most 2 identical consecutive bits),
//% order with fewer changes, recursive CAT algorithm.

//#define TIMING  // define to disable printing


ulong n;    // number of bits in words
ulong *rv;  // bits of the word
ulong *rvo;  // bits of the last word

ulong ct;   // count objects
ulong rct;  // count recursions (==work)

ulong mxct = 0;
ulong txct = 0;

void visit()
{
    ulong xct = 0;
    if ( ct>1 )  for (ulong j=0; j<n; ++j)  xct += (rv[j] != rvo[j]);
    txct += xct;
    if ( xct > mxct )  mxct = xct;
    for (ulong j=0; j<n; ++j)  rvo[j] = rv[j];

#ifndef TIMING
    cout << setw(4) << ct << ":";
    cout << "   ";
    for (ulong j=0; j<n; ++j)  cout << " " << (rv[j] ? '1' : '.');
    cout << "    " << xct;
    cout << "   ";
    cout << " " << (!rv[0] ? '1' : '.');
    for (ulong j=1; j<n; ++j)  cout << " " << (rv[j]==rv[j-1] ? '1' : '.');
    cout << endl;
#endif
}
// -------------------------

void rll_rec(ulong d, bool z)
{
    if ( d>=n )
    {
        ++ct;  // count objects
        visit();
    }
    else
    {
        ++rct;  // measure computational work
        if ( z==0 )
        {
            rv[d]=0;  rv[d+1]=1;  rll_rec(d+2, 1);
            rv[d]=1;  rll_rec(d+1, 1);
        }
        else  // z==1
        {
            rv[d]=1;  rv[d+1]=0;  rll_rec(d+2, 0);
            rv[d]=0;  rll_rec(d+1, 0);
        }
    }
}
// -------------------------


int
main(int argc, char **argv)
{
    n = 7;
    NXARG(n, "Length of words");
    rv = new ulong[n+5];  // incl. sentinel rv[n]
    rvo = new ulong[n+5];

    ct = 0;
    rct = 0;
    rll_rec(0, 0);

    cout << setprecision(7);
    cout << "ct=" << ct << endl;
    cout << "max xct=" << mxct << endl;
    cout << "sum xct=" << txct << endl;
    cout << "avg #changes per transition = " << (double)txct/(double)ct << endl;
//    cout << "rct=" << rct << endl;  // rct == ct-1
//    cout << "work/object=" << (double)rct/(double)ct << endl;  // ratio <= 1

    delete [] rv;
    delete [] rvo;

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

/*

sum xct:

1, 2, 4, 8, 15, 26, 44, 74, 123, 202, 330, 538, 875, 1420, 2302, 3730, 6041, 9780

? ggf(v)
(x^2 - x + 1)/(-x^6 + x^5 + x^4 - 2*x^3 + 3*x^2 - 3*x + 1)
? factor(ggf(v))
[x^2 - x + 1 1]
[x - 1 -2]
[x^2 + 1 -1]
[x^2 + x - 1 -1]

avg #changes per transition = 1.44721339615302447
? 1+1/sqrt(5)
1.44721359549996

max xct:
 n: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 ...
    1 1 1 2 3 3 3 4 5  5  5  6  7  7  7  8  9  9  9 10 11 11 11 12 13 13 13 14 15 15 ...

*/

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

