package combinations;

import java.util.Vector;

public class Driver {
	
	int numberOfFields;
	
	int fieldLength;
	
	int bitsConstrained;
	
	int count;
	
	Vector<Integer> fieldLengthCollection;
	
	Vector<Integer> bitsConstrainedCollection;
	
	Vector<Integer> countCollection;
	
	public Driver(){
		
		numberOfFields = 5;
		
		fieldLength = -1;
		
		bitsConstrained = -1;
		
		count = -1;
		
		fieldLengthCollection = new Vector<Integer>();
		
		bitsConstrainedCollection = new Vector<Integer>();
		
		countCollection = new Vector<Integer>();
		
	}

	public Vector<String> getCombo_AllBitsConstrained( int fieldLength ){
		
		Vector<String> combos = new Vector<String>();
		
		String combo = "";
		
		for(int i=0; i<2; i++){
		
			for(int j=0; j<fieldLength; j++){
			
				if( i == 0 )
					combo += "0";
				else
					combo += "1";
			
			}
			
			combos.add( combo );
			combo = new String();
			
		}
		
		return combos;
		
	}
	
	public int getCount_AllBitsConstrained( int fieldLength ){
		
		Vector<String> combos = getCombo_AllBitsConstrained( fieldLength );
	
		return combos.size();
		
	}
	
	public int convertBinaryToInt( String binaryString ){
		
		double sum = 0.0d;
		
		int binaryStringLength = binaryString.length();
		
		int bitIndexStart = -1;
		int bitIndexEnd = -1;
		
		
		for(int i=0; i<binaryStringLength; i++){
			
			bitIndexEnd = binaryStringLength - i;
			bitIndexStart = binaryStringLength - (i+1);
			
			System.out.println( "binaryString.substring( start("+bitIndexStart+"), e("+bitIndexEnd+") ): " + binaryString.substring( i, i+1 ) );
			
			if( new Integer( binaryString.substring( bitIndexStart, bitIndexEnd ) ).intValue() > 0 )
				sum += Math.pow( 2.0, (double)i );
			
			System.out.println( "sum: " + sum );
			
			
		}
		
		return (int)sum;
		
	}
	
	public Vector<String> generateBinaryStrings( int fieldSize ){
		
		Vector<String> binaryStrings = new Vector<String>();
		
		String binaryString = null;
		
		for(int i=0; i<fieldSize; i++){
			
			System.out.println( "unconstrained bit combos: " + Integer.toBinaryString( fieldSize ) );
			
			binaryStrings.add( Integer.toBinaryString( fieldSize ) );

		}
		
		return binaryStrings;
		
	}
	
	public int getCount_SomeBitsConstrained( int fieldLength, int bitsConstrained ){
		
		Vector<String> combos = new Vector<String>();
		
		String combo = "";
		
		int numberRows = fieldLength - bitsConstrained + 1;
		
		//System.out.println( "numberRows: " + numberRows );
		
		int numberCombosPerRow = (int) Math.pow( 2.0, ((double)numberRows) );
		
		// (i.e.: 2 bits constrained, 4 combos
		// (      1nn => 1[00], 1[01], 1[10], 1[11] => 4 = pow(2, bits),
		//        where these "bit combos" will repeat in a row (but only one repeat needed)
		// (i.e.: 0nn => 0[00], 0[01], 0[10], 0[11] is the rest of the row) ..
		int numberUnconstrainedBitCombosPerRow = (int) Math.pow( 2.0, ( (double)( fieldLength - bitsConstrained ) ) );
		
		// generate the portion of the binary strings that are "unconstrained" ..
		int unconstrainedCount = 0;
		Vector<String> unconstrainedStrings = new Vector<String>();
		for(int i=0; i<numberUnconstrainedBitCombosPerRow; i++){
			
			System.out.println( "unconstrained bit combos: " + Integer.toBinaryString( unconstrainedCount ) );
			
			unconstrainedStrings.add( Integer.toBinaryString( unconstrainedCount++ ) );

		}
		
		String constrainedBit = "";
		
		String unconstrainedBitsLeft = "";
		String constrainedBits = null;
		String unconstrainedBitsRight = "";
		
		int unconstrainedBitsIndexStart = -1;
		int unconstrainedBitsIndexEnd = -1;
		int unconstrainedStringIndex = -1;
		
		String unconstrainedStringLeft = "";
		String unconstrainedStringRight = "";
		
		// number of "rows" ..
		for(int i=0; i<numberRows; i++){
		
			// number of combos per "row" ..
			for(int j=0; j<numberCombosPerRow; j++){
				
				// a single combo ..
				
				// 1st row, #left_bits = null, 2nd row, #left_bits = 1, etc ..
				// 1st row, #right_bits = total, 2nd row, #right_bits = total - 1, etc ..
				unconstrainedBitsIndexStart = 0;
				// row i=0 => 00nn => 00[00], 00[01], 00[10], 00[11] ..
				// row i=1 => n00n => 0[00]0, 0[00]1, 1[00]0, 1[00]1 ..
				// row i=2 => nn00 => 00[00], 01[00], 10[00], 11[00] ..
				// leftString = substring(0, i)       => i=0 is 00,   i=1 is 0, i=2 is null
				// rightString = substring(i, length) => i=0 is null, i=1 is 0, i=2 is 00
				unconstrainedBitsIndexEnd = i;
				
				// index repeats after "numberUnconstrainedBitCombosPerRow" times ..
				unconstrainedStringIndex = j % numberUnconstrainedBitCombosPerRow;
				
				//System.out.println( "   unconstrainedStringIndex: " + unconstrainedStringIndex );
				//System.out.println( "unconstrainedBitsIndexStart: " + unconstrainedBitsIndexStart );
				//System.out.println( "  unconstrainedBitsIndexEnd: " + unconstrainedBitsIndexEnd );
				
				unconstrainedStringLeft = unconstrainedStrings.get( unconstrainedStringIndex );
				unconstrainedBitsLeft = unconstrainedStringLeft.substring( unconstrainedBitsIndexStart, unconstrainedBitsIndexEnd );

				unconstrainedStringRight = unconstrainedStrings.get( unconstrainedStringIndex );
				unconstrainedBitsRight = unconstrainedStringRight.substring( unconstrainedBitsIndexEnd, unconstrainedStringRight.length() );
				
				//System.out.println( "unconstrainedStringRight.length(): " + unconstrainedStringRight.length() );
				
				//System.out.println( "unconstrainedBitsLeft: " + unconstrainedBitsLeft +", unconstrainedBitsRight: " + unconstrainedBitsRight );
				
				// generate a combination ..
				// combo = constrained bits + unconstrained bits
				// more specifically,
				// combo = unconstrained bits (left) + constrained bits + unconstrained bits (right)
				// (where "left" and "right" have 0 or more bits) ..
				constrainedBits = new String();
				constrainedBits += unconstrainedBitsLeft;
				
				// 1st half of # of combos, bits = 0, other half bits = 1 ..
				// (i.e.: 0[00], 1[00], 0[11], 1[11] with numberCombosPerRow = 4) ..
				if( j >= (numberCombosPerRow/2) )
					constrainedBit = "1";
				else
					constrainedBit = "0";
				
				// add in the "constrained bits" to the total ..
				for(int k=0; k<bitsConstrained; k++)
					constrainedBits += constrainedBit;
				
				constrainedBits += unconstrainedBitsRight;
				
				//System.out.println( "constrainedBits: " + constrainedBits );
				
				// point "combo" to the constructed bits ..
				combo = constrainedBits;
				
				// only add this combo if it is not a duplicate ..
				if( combos.contains( combo ) == false )
					combos.add( combo );
			
			}
			
		}
		
		return combos.size();
		
	}
	
	public static void main(String[] args){
		
		Driver d = new Driver();
		
		//int value = d.convertBinaryToInt( "10000" );
		//System.out.println( "value: " + value );
		
		int bitsConstrained = 1;
		int fieldLength = 3;

		
		int count = d.getCount_SomeBitsConstrained( fieldLength, bitsConstrained );
		
		System.out.println( "count: " + count );
		
	}

}
