#if !defined  HAVE_KSUBSET_TWOCLOSE_LIST_REC_H__
#define       HAVE_KSUBSET_TWOCLOSE_LIST_REC_H__
// This file is part of the FXT library.
// Copyright (C) 2024 Joerg Arndt
// License: GNU General Public License version 3 or later,
// see the file COPYING.txt in the main directory.


#include "comb/comb-print.h"
#include "fxttypes.h"


class ksubset_twoclose_list_rec
// k-subsets (kmin<=k<=kmax) in a two-close order with homogeneous moves.
// Representation as list of elements.
// Recursive algorithm.
{
public:
    ulong *S;   // k-subset (as list of elements)
    ulong n_s;  // length of S[]
    ulong n;    // subsets of the n-element set
    bool w;     // false by default; modifies ordering
    // function to call with each combination:
    void (*visit)(const ksubset_twoclose_list_rec &);

    ksubset_twoclose_list_rec(const ksubset_twoclose_list_rec&) = delete;
    ksubset_twoclose_list_rec & operator = (const ksubset_twoclose_list_rec&) = delete;

public:
    explicit ksubset_twoclose_list_rec(ulong tn, bool tw)
    {
        n = tn;
        S = new ulong[n];
        w = tw;
    }


    ~ksubset_twoclose_list_rec()
    {
        delete [] S;
    }

    const ulong * data()  const  { return S; }
    ulong len()  const  { return n_s; }

    void generate(void (*tvisit)(const ksubset_twoclose_list_rec &),
                  ulong kmin, ulong kmax)
    {
        visit = tvisit;
        const ulong kmax0 = n - kmin;
        next_rec(n, kmax, kmax0, 0, 0);
    }

private:
    void next_rec(ulong d, ulong n1, ulong n0, ulong ns, bool q)
    // d:  remaining depth in recursion
    // n1: remaining ones to fill in
    // n0: remaining zeros to fill in
    // ns: length of S[]
    // q:  direction in recursion
    {
        if ( 0 == d )  { n_s = ns;  visit(*this);  return; }

        d -= 1;  // note

        if ( q )
        {
            if ( n0 != 0 )
            {
                next_rec( d, n1, n0-1, ns, w ^ (d & 1) );
            }
            if ( n1 != 0 )
            {
                S[ns] = n-d-1;
                next_rec( d, n1-1, n0, ns+1, q );
            }
        }
        else
        {
            if ( n1 != 0 )
            {
                S[ns] = n-d-1;
                next_rec( d, n1-1, n0, ns+1, q );
            }
            if ( n0 != 0 )
            {
                next_rec( d, n1, n0-1, ns, w ^ (d & 1) );
            }
        }
    }

public:
    void print( const char * bla )  const
    { print_set( bla, data(), len() ); }

    void print_deltaset( const char * bla )  const
    { print_set_as_deltaset( bla, data(), len(), n ); }
};
// -------------------------


#endif  // !defined HAVE_KSUBSET_TWOCLOSE_LIST_REC_H__
