
// GrayCode.h

#ifndef __GRAYCODE_H__
#define __GRAYCODE_H__

using namespace std;
typedef unsigned int uint;

#include <iostream>
#include<vector>
#include<map>

class GrayCode
{
public:
	GrayCode();
	~GrayCode();

	vector<bool> Base2ToGray(vector<bool> vBase2);
	vector<bool> GrayToBase2(vector<bool> vGray);

	map<vector<bool>, vector<uint>> Base2ToGray(map<vector<bool>, vector<uint>> mBase2);
	map<vector<bool>, vector<uint>> GrayToBase2(map<vector<bool>, vector<uint>> mGray);

	uint AbsoluteValue(uint a, uint b);
	uint AbsoluteValue(vector<uint> v1, vector<uint> v2);

	uint RandomClass(uint nTotal);
	vector<bool> RandomVector(uint nBits);
	vector<bool> RandomVector(uint nSum, uint nBits);
	vector<bool> RandomKey(vector<uint>& vData, map<vector<bool>, vector<uint>> m);

	vector<bool> GetKey(uint nIndexPosition, uint nIndex, vector<uint>&vIndexClass, map<vector<bool>, vector<uint>> m);

	bool CheckGrayCode(uint& nFail, map<uint, vector<uint>> m);
	bool CheckGrayCode(uint& nFail, map<vector<bool>, vector<uint>> m);

	uint GraySum(vector<bool> vGray);
	uint Base2Sum(vector<bool> vBase2);

	uint SumVector(vector<uint> v);

	uint Base2MapMaxSum(uint& nMinSum, map<vector<bool>, vector<uint>> mBase2);
	uint GrayMapMaxSum(uint& nMinSum, map<vector<bool>, vector<uint>> mGray);

	vector<uint> GraySums(vector<uint> vGrayStart, vector<uint> vGraySize, vector<bool> vGray);
	vector<uint> Base2MapMaxSums(vector<uint>& vMinSums, vector<uint> vGrayStart, vector<uint> vGraySize, map<vector<bool>, vector<uint>> mBase2);
	vector<uint> GrayMapMaxSums(vector<uint>& vMinSums, vector<uint> vGrayStart, vector<uint> vGraySize, map<vector<bool>, vector<uint>> mGray);

	vector<bool> IncrementBase2(vector<bool> vBase2);
	vector<bool> DecrementBase2(vector<bool> vBase2);

	uint Base2ToBase10(vector<bool> vBase2);

	uint ClassCount(uint nDefault, vector<uint> v);
	uint ClassCount(bool bPrintSumsAndIndexes, uint nDefault, vector<uint> v);
	uint ClassCount(bool bPrintSumsAndIndexes, uint nDefault, uint nSize, vector<uint> v);

	bool InsertIntoCoordinates(vector<bool>& vCoordinates, uint nNthDimension, uint nDimensions, vector<bool> v);
	vector<bool> ExtractFromCoordinates(uint nNthDimension, uint nBitsPerDimension, uint nDimensions, vector<bool> vCoordinates);

	bool FlipsAndRotations(vector<bool> v, uint& nFlips, uint& nRotations);

	vector<bool> GrayToCoordinates2D(uint nBitsPerDimension, uint nDimensions, vector<bool> v);
	vector<bool> CoordinatesToGray2D(uint nBitsPerDimension, uint nDimensions, vector<bool> v);

	vector<bool> GrayCodeToGrayCoordinates(uint nBitsPerDimension, uint nDimensions, vector<bool> v);
	vector<bool> GrayCoordinatesToGrayCode(uint nBitsPerDimension, uint nDimensions, vector<bool> v);

	vector<uint> GrayCoordinatesToBase10Coordinates(uint nBitsPerDimension, uint nDimensions, vector<bool> vGrayCoordinates);

	vector<bool>  IncrementBase2SameGraySumSlowly(bool& bOK, vector<bool> vBase2);
	vector<bool>  DecrementBase2SameGraySumSlowly(bool& bOK, vector<bool> vBase2);

	vector<uint> GetCounts(uint nCountsSize, vector<bool> v);
	
	vector<uint> GrayIntervalCounts(bool& bInitial, vector<bool> vGray);
	map<vector<uint>, vector<uint>> GrayIntervalCounts(map<vector<bool>, vector<uint>> mGray);
	vector<uint> GenerateGrayStart(vector<uint> vIntervalCounts);

	vector<bool> IncrementBase2SameGraySum(bool& bOK, vector<bool> vBase2);
	vector<bool> IncrementBase2SameGraySum(bool& bOK, uint& nReturn, uint nCountsSize, vector<uint>& vBase2Counts, vector<uint>& vGrayCounts, vector<bool> vBase2);
	vector<bool> IncrementBase2SameGraySum(uint nBitsPerSegmentGray, vector<uint> vPrefixSegmentsBase10, bool& bOK, uint& nReturn, vector<bool> vBase2);

	vector<bool> IncrementBase2IncrementGraySum(bool& bOK, vector<bool> v);	// increment bool (minimized), increment gray sum by one
	vector<bool> IncrementBase2IncrementGraySum(bool& bOK, vector<uint> vGrayStart, vector<uint> vGraySize, vector<uint> vTargetSums, vector<bool> vBase2);

	vector<bool> IncrementBase2IncrementGraySumToTarget(uint& nReturn, uint nGraySumTarget, vector<bool> vBase2);		// or Decrement - change the name

	vector<bool> DecrementBase2DecrementSum(bool& bOK, vector<bool> vBase2);	// decrement bool (minimized), decrement gray zero sim by one	// see SimZero.xls

	vector<bool> DecrementBase2SameGraySum(bool& bOK, vector<bool> vBase2);
	vector<bool> DecrementBase2SameGraySum(bool& bOK, uint& nReturn, uint nCountsSize, vector<uint>& vBase2Counts, vector<uint>& vGrayCounts, vector<bool> vBase2);

	vector<bool> ConfigureBase2ToSameSums(bool& bOK, vector<uint> vTargetSumsLower, vector<uint> vTargetSumsUpper, vector<uint> vGrayStart, vector<uint> vGraySize, vector<bool> vBase2);
	map<vector<bool>, vector<uint>> ConfigureMapToSameSums(vector<uint> vTargetSumsLower, vector<uint> vTargetSumsUpper, vector<uint> vGrayStart, vector<uint> vGraySize, map<vector<bool>, vector<uint>> m);

	vector<bool> MaxIterativePointBase2(vector<bool> v1, vector<bool> v2);

	bool IncrementBitCountsGray(vector<bool> vGray, vector<uint>& vBitCounts);
	vector<uint> GetBitCounts(uint nBits, map<vector<bool>, vector<uint> > mGray);
	map<uint, vector<uint>> BitCountOrder(vector<uint> vBitCounts);
	vector<uint> GetFinalBitCountOrder(map<uint, vector<uint>> m);

	vector<bool> ReOrderGray(vector<uint> vOrder, vector<bool> v);
	map<vector<bool>, vector<uint>> ReOrderGray(vector<uint> vOrder, map<vector<bool>, vector<uint>> m);

	map<uint, vector<uint>> HilbertCurve(uint nDimensions, uint nBitsPerDimension);

	uint FindKey(uint nIndex, uint nClass, map<uint, vector<uint>> m);
	vector<bool> FindKey(uint nIndex, uint nClass, map<vector<bool>, vector<uint>> m);
	vector<bool> FindKeyFromIndex(uint nIndexPosition, uint nClassPosition, uint nIndex, uint&nClass, map<vector<bool>, vector<uint>> m);

	vector<bool> Vector28x28To32x32(vector<bool> v28x28);
	map<vector<bool>, vector<uint>>  Map28x28To32x32(map<vector<bool>, vector<uint>> m28x28);

	vector<bool> Gray32x32ToHilbert(vector<bool> vGray32x32);

	map<vector<bool>, vector<uint>> GetFocusSubSet(uint nFocusClass, uint nClassPosition, map<vector<bool>, vector<uint>> m);
	map<vector<bool>, vector<uint>> GetNotFocusSubSet(uint nFocusClass, uint nClassPosition, map<vector<bool>, vector<uint>> m);

	map<vector<bool>, vector<uint>> BinaryClassOutput(uint nFocusClass, uint nClassPosition, map<vector<bool>, vector<uint>> m);
	map<vector<bool>, vector<uint>> BinaryIndexOutput(uint nFocusIndex, uint nIndexPosition, uint nClassPosition, map<vector<bool>, vector<uint>> m);

private:
};
 
#endif // __GRAYCODE_H__

