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

#include "comb/is-catalan-rgs.h"

#include "comb/comb-print.h"

#include "fxttypes.h"


// whether to use arrays instead of pointers:
//#define CATALAN_RGS_FIXARRAYS  // default is off
// slight speedup with GCC 4.9.1


class catalan_rgs
// Catalan restricted growth strings (RGS):
// strings a[0,1,...,n-1] where a[0]=0 and a[k] <= a[k-1] + 1.
// Lexicographic order.
// The number of length-n RGS is (OEIS sequence A000108)
//  1, 1, 2, 5, 14, 42, 132, 429, 1430, 4862, 16796, ...
// Sequence A239903 gives the RGS.
{
private:
#if !defined CATALAN_RGS_FIXARRAYS
    ulong *A;  // digits of the RGS: a[k] <= a[k-1] + 1
#else
    ulong A[64];
#endif
    ulong n;   // Number of digits (paren pairs)

    char *S;  // paren string

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

public:
    explicit catalan_rgs(ulong tn)
    {
        n = tn;
#if !defined CATALAN_RGS_FIXARRAYS
        A = new ulong[n + 1];
#endif
        S = new char[2*n+1];
        S[2*n] = 0;

        first();
    }

    ~catalan_rgs()
    {
#if !defined CATALAN_RGS_FIXARRAYS
        delete [] A;
#endif
        delete [] S;
    }

    const ulong *data()  const  { return A + 1; }
    ulong size()  const  { return n + 1; }

    void first()
    { for (ulong k=0; k<size(); ++k)  A[k] = 0; }


    ulong next()
    // Return position of leftmost change, zero with last.
    {
        ulong j = n;
        while ( j > 1 )
        {
            if ( A[j] <= A[j-1] )
            {
                ++A[j];
                return j - 1;
            }
            A[j] = 0;
            --j;
        }

        return 0;  // current is last
    }


    const char* bit_string()
    {
        for (ulong k=0; k<2*n; ++k)  S[k] = '.';
        const ulong *a = data();
        for (ulong k=0, j=0;  k<n;  ++k, j+=2)  S[ j - a[k] ] = '1';
        return S;
    }

    const char* paren_string()
    {
        for (ulong k=0; k<2*n; ++k)  S[k] = ')';
        const ulong *a = data();
        for (ulong k=0, j=0;  k<n;  ++k, j+=2)  S[ j - a[k] ] = '(';
        return S;
    }

    void print(const char *bla, bool dfz=true)  const
    { print_vec(bla, data(), n, dfz); }

    bool OK()  const
    { return is_catalan_rgs(data(), n); }
};
// -------------------------


#endif  // !defined HAVE_CATALAN_RGS_H__
