"""BTVN, Python3: quay lui sinh dãy/xâu và đếm nghiệm ở lá.

python3 g11-cs-quay-lui-xau.py co-dinh 2
python3 g11-cs-quay-lui-xau.py them-xoa 2
python3 g11-cs-quay-lui-xau.py nhi-phan 3
python3 g11-cs-quay-lui-xau.py rgb 2
python3 g11-cs-quay-lui-xau.py hex
Hex theo mô hình SGV: đúng 3 kí tự, cho phép 0 đầu, từ 000 đến FFF.
"""
import argparse

count = 0


def genBinary_fixed(A, k, n):
    global count
    if k == n:
        print(A)
        count += 1
    else:
        for value in range(2):
            A[k] = value
            genBinary_fixed(A, k + 1, n)


def genBinary_growing(A, k, n):
    global count
    if k == n:
        print(A)
        count += 1
    else:
        for value in range(2):
            A.append(value)
            genBinary_growing(A, k + 1, n)
            A.pop()


def genWords(A, k, n, alphabet):
    global count
    if k == n:
        print(''.join(A))
        count += 1
    else:
        for value in alphabet:
            A.append(value)
            genWords(A, k + 1, n, alphabet)
            A.pop()


def check_size(n, base):
    if not 0 <= n <= 12 or base ** n > 4096:
        raise ValueError('Bản thực hành nhận n từ 0 đến 12 và tối đa 4096 nghiệm.')


def main():
    global count
    parser = argparse.ArgumentParser(description=__doc__)
    modes = parser.add_subparsers(dest='mode', required=True)
    for mode in ['co-dinh', 'them-xoa', 'nhi-phan', 'rgb']:
        sub = modes.add_parser(mode)
        sub.add_argument('n', type=int)
    modes.add_parser('hex')
    args = parser.parse_args()
    try:
        count = 0
        if args.mode in ['co-dinh', 'them-xoa']:
            check_size(args.n, 2)
            if args.mode == 'co-dinh':
                genBinary_fixed([0] * args.n, 0, args.n)
            else:
                genBinary_growing([], 0, args.n)
        else:
            n = 3 if args.mode == 'hex' else args.n
            alphabet = list('0123456789ABCDEF') if args.mode == 'hex' else (['R','G','B'] if args.mode == 'rgb' else ['0','1'])
            check_size(n, len(alphabet))
            genWords([], 0, n, alphabet)
        print('Tổng số nghiệm:', count)
    except ValueError as error:
        parser.exit(2, f'Dữ liệu không phù hợp: {error}\n')


if __name__ == '__main__':
    main()
