#if !defined  HAVE_KSUBSET_TWOCLOSE_REC_H__
#define       HAVE_KSUBSET_TWOCLOSE_REC_H__
// This file is part of the FXT library.
// Copyright (C) 2010, 2012, 2014, 2019, 2023, 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_rec
// k-subsets (kmin<=k<=kmax) in a two-close order with homogeneous moves.
// Recursive algorithm.
{
public:
    ulong *S;  // k-subset (as delta set)
    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_rec &);

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

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

    ~ksubset_twoclose_rec()
    {
        delete [] S;
    }

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


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

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

        d -= 1;  // note

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

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

    void print_set( const char * bla )  const
    { print_deltaset_as_set( bla, data(), len() ); }
};
// -------------------------


#endif  // !defined HAVE_KSUBSET_TWOCLOSE_REC_H__
