
// demo-is-self-contained

#include <cmath>

#include "fxttypes.h"

#include "jjassert.h"
#include "nextarg.h"  // NXARG()

#include "fxtio.h"

//% Generate all maximally refined partitions.
//% See http://oeis.org/A179009 for the definition of a maximally refined partition.

//#define TIMING // uncomment to disable printing




ulong *a;
ulong ct = 0;

bool is_in_part(ulong p, ulong off)
// Return whether p is a part in current partition.
{
    for (ulong k=0; k<off; ++k)  // check against all parts
    {
        if ( p==a[k] )  return true;
    }
    return false;
}
// -------------------------


bool can_refine(ulong off)
// Return whether partition can be refined.
{
    for (ulong k=0; k<off; ++k)  // all parts p
    {
        const ulong p = a[k];
        for (ulong i=1,j=p-1; i<j; ++i,--j)  // all splittings of p
        {
            if ( !is_in_part(i, off) && !is_in_part(j, off) )  return true;
        }
    }
    return false;
}
// -------------------------


void visit(ulong off)
{
    if ( can_refine(off) )  return;
    ++ct;
    cout << setw(4) << ct << ":  ";
//    {ulong n=0; for(ulong k=0; k<off; ++k)  n+=a[k];
//        cout << setw(4) << n << "=";}
    for (ulong k=0; k<off;  ++k)
    {
        cout << a[k];
        if ( k+1<off )  cout << "+";
    }
//    cout << "  [" << off << "]";  // number of parts

    cout << endl;
}
// -------------------------

void part_dist_lex_rec(ulong n, ulong mp, ulong off=0)
{
    if ( n==0 )
    {
#ifndef TIMING
        visit(off);
#else
        ++ct;
#endif
        return;
    }

    for (ulong m=mp+1; m<=n; ++m)
    {
        a[off] = m;
        part_dist_lex_rec(n-m, m, off+1);
    }
}
// -------------------------

int
main(int argc, char **argv)
{
    ulong n = 35;
    NXARG(n, "Partitions of n");
    const ulong na = (ulong)floor( (sqrt(1+8*(double)n) - 1)/2 );  // max number of parts, see A003056
    a = new ulong[na];
//    cout << " na=" << na << endl;

    ulong mp = 0;
    NXARG(mp, "Minimal part > mp,  0 <= mp < n");
//    if ( mp<1 )  mp = 1;
    if ( mp>=n )  mp = n;

    part_dist_lex_rec(n, mp);

    cout << " " << n << ":  ct=" << ct << endl;
    cout << endl;

    delete [] a;

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


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