//reaches 301962 with one line system.out.println
// TOTAL:  362880
/*
Online Java - IDE, Code Editor, Compiler
Online Java is a quick and easy tool that helps you to build, compile, test your programs
online.
*/
// This has been created to ensure I can utilize any random functions more efficiently.
// It is a creation of the nPr permutation calculator.
// It has used techniques I learnt including recursion and also memoization to speed up execution.
// I will incorporate this into Java applications I created
//TEST CASES
//r=2 n=5 PASS
//r=5 n=5 PASS
//r=1 n=4 PASS
//r=0 n=3 PASS
//r=0 n=0 PASS
// now going to flip the above
//r=5 n=2 PASS
//r=5 n=5 PASS
//r=4 n=1 PASS
//r=3 n=0 PASS
//test to make numerator less than r
// n = 4 r=3 PASS

// With lots trying, there is a major issue in trying to get the numbers back out of an int[][] that
// have been stored in list (copied from Map).
//For some reason, it is able to show values in Map.get (using the key which is simply the pos of 3x3 grid in it).
//I can process all int[] in the value, and see them as Array list...

//I have tried everything in my capacity to make these numbers visible, but it has not worked:
//This includes adding the miniGrid to a 3D array and processing...
//running nested loop to get each number from array and storing in another 2D array.
//simply running  System.out.println miniGrid[0][0]  up to [2][2],  but the output is non-consistent 
//with what is being stored...
// I have also included commented code (for loop initialisation) and also setting temp based on this, but
//its irrelevant given above situation...

//Complete forgot to set temp = mp.get(i)!!!!
//Need to try this first........  (THIS HAS ALSO FAILED!!!!!)

// The only left technique is using the Set<String> s = new HashSet() since the String of unique permutation
//was written here at the time that a unique permutation acquired.

//It will be attempted to extract the numbers from the String using String Tokenizer.  Cast them to Int....
//This will then be added into a  int [][]  and stored into temp, and it will try  fill9x9grid  again....
//This will preserve my hard coded logic of rowIndex, colIndex, colCount, rowCount......
// THIS HAS WORKED....

//also didn't need three if statements for setting offset...
// could have used if totalNumbersProcessed = 0 (offset0) , 9 (offset3), 18(ofset 6), 27 (offset 0), 24, 43,51, 60, 69, 76,83,90 



//I HAVE NOT USED TOKENIZER, ALTHOUGH THIS WAS OPTION...
//SINCE THE , SEPARATED THE VALUES IN 3x3 GRID, I SIMPLY DID INCREMENT i=i+2
//TO MAKE CODE MORE PROFESSIONAL, THIS CAN BE ADDRESSED IN THE FUTURE....


//**** NOT REQUIRED ***
//if it fails, only option is to change the fill9x9 grid to execute via  String.charAt()...... So logic change will
//be required of the code.....
//colIndex and rowIndex  will remain.....
// colCount and rowCount will be affected since 3x3 grids no longer on [3][3], but logic can be twisted!

//*** UP TO HERE ***
//NOW NEED TO CHECK BEST POINT TO CHECK FOR UNIQUE ROWS AND UNIQUE COLUMNS....
//EASIEST WAY IS TO CHECK BY DUPLICATION OF A NUMBER IN EACH DIRECTION...
//I CAN THEN FOLLOW MY PSEUDO CODE AS PLANNED TO POPULATE THE GRID!!!!!!
//JUST FUCKING HOPE THE BOARDS ARE BEING STORED CORRECTLY WHEN FINISHED/
//OTHERWISE WILL NEED TO IMPLEMENT A METHOD TO FORMAT THE 81 NUMBERS PROPERLY
//IT SHOULDNT BE TOO DIFFICULT SINCE THE BOARD SUMMARY HAS VALUE AND ALSO CO-ORDINATES... SO JUST PLACE THEM BACK



//how to process rowcheck
//use switch
//case totalNumbersProcessed =9

//how to process column check







import java.math.*;
import java.util.*;
import java.util.stream.*;

interface Fillable
{
    public void fill3x3();
    public void fill9x9(Map<Integer, int[][]> mp);
    public boolean checkUniqueRows(int [][] temp, int rowIndex);
    public boolean checkUniqueColumns();
    public void place3X3Into9x9();
    public boolean SudokuComplete();
    public void get9x9Grid();
    public void get3x3Grid();
    public int[][] wipe9x9Board(int[][] temp);
    public void historyBoards(String history);
    public int convertStringTo3x3(String permutations3x3, int getNumString);
    
}

class nineByNine
{
    
    
    
    int test;
    
    public nineByNine()
    {
         int [][] nineByNine = new int[][]{  {0,0,0,0,0,0,0,0,0},
                                            {0,0,0,0,0,0,0,0,0},
                                            {0,0,0,0,0,0,0,0,0},
                                            {0,0,0,0,0,0,0,0,0},
                                            {0,0,0,0,0,0,0,0,0},
                                            {0,0,0,0,0,0,0,0,0},
                                            {0,0,0,0,0,0,0,0,0},
                                            {0,0,0,0,0,0,0,0,0},
                                            {0,0,0,0,0,0,0,0,0} };
        
    }
}


class Sudoku implements Fillable
{
    Map<Integer, int[][]> mp = new HashMap();
    int possibleNumbers[] = new int[]{1,2,3,4,5,6,7,8,9};
    //List<int> lst = new ArrayList<>(Arrays.asList(possibleNumbers));
    
    List<Integer> lst = new ArrayList<Integer>();
    
    int MiniTest[][] = new int[3][3];
    
  Map<Integer, int[][]> completedBoards = new HashMap<>();
  int numComplete9x9Boards=1;
    
    //nineByNine [] nbn = new nineByNine[5000]; // is it best way to create an array on nineByNine classes...
    //nbn[0]= new nineByNine();
    
    
    
    // it might be sensible since classes won't behave with each other...
    //Also in future... end user could create a class object of the nineByNine to test their
    //partially filled grid..
    
    
    int [][] nineByNine = new int[][]{  {0,0,0,0,0,0,0,0,0},
                                            {0,0,0,0,0,0,0,0,0},
                                            {0,0,0,0,0,0,0,0,0},
                                            {0,0,0,0,0,0,0,0,0},
                                            {0,0,0,0,0,0,0,0,0},
                                            {0,0,0,0,0,0,0,0,0},
                                            {0,0,0,0,0,0,0,0,0},
                                            {0,0,0,0,0,0,0,0,0},
                                            {0,0,0,0,0,0,0,0,0} };
    
    
    
    int nineByNineBoardNumber=0;
    
    
    
    
    
    long permutations;
    
    int threeBythree[][] = new int[3][3];    //0,0 0,1, 0,2  
                                             //1,0, 1,1, 1,2
                                             //2,0, 2,1, 2,2
    //Set <Integer[][]> s = new HashSet<>();
    
    Set<String> s = new HashSet();
    
    
    StringJoiner sj;
    int storeMiniGrids[][][];
    int item=0;
    
    int currentSize;
    int newSize;
    int[][] miniGrid;
    int[][][] miniGridContainer;
    
    List<Integer> copy = new ArrayList<>(lst);
    boolean processedDivisibleTwo=false;
    Random rand = new Random();
    String[] completedBoardsLogs = new String[10000];
    int count=0;
    
    int randomNumber1to9List;
    
    
    public int[][] wipe9x9Board(int [][]temp)
    {
            for (int q=0; q<temp.length; q++)    //can use temp here or also the blank 9x9 grid with 0, same size...
            {
                for (int r=0; r<temp[0].length; r++)
                
                {
                    temp[q][r]=0;     // wipes buffer, getting numbers from set with string permutations
                    nineByNine[q][r]=0;  // clears 9 x 9 grid. (before it is stored)...
                }
                
            }
            
            return temp;
    }
    
    public Sudoku(long permutations)
    {
        this.permutations =permutations;
       
       /* 
        // can also add viable numbers into list this way.
        //But I want to introduce new coding techniques so used stream....
       
        for (int i=0; i<possibleNumbers.length; i++)
    {
        System.out.println("fucking here");
        lst.add(possibleNumbers[i]);
    }
    
    */
   
    fill3x3();
        
    }
    
    
    public int convertStringTo3x3(String permutations3x3, int getNum)
    {
        //boolean newRow=false;
        //int[][] temp=new int[3][3];
        int temp;
        
        int q=0;
        int r=0;
        int z=0;
        System.out.println("String to be processed:" + permutations3x3);
        
        char num;
        String numString;
        
        //do
        //{
            //newRow=false;
            
            //System.out.println("r is: " + r);
            //System.out.println("q is: " + q);
            //System.out.println("z is: " + z);
            
            
            //System.out.println("Value at z: " + permutations3x3.charAt(z));
            //if (q==2)
            //{
                //System.out.println("1:" + r);
                //System.out.println("2" + q);
                //System.out.println("3:" + z);
                
                num=permutations3x3.charAt(getNum);
                numString= String.valueOf(num);
                
                temp= Integer.parseInt(numString);
                
                //System.out.println("****** PRINT VALUE BACK %%%%%: " + temp);
                
                return temp;
                
                //q=0;
                //newRow=true;
                //r++;
            //}
            //if (!newRow)
            //{
              //  q++;
            //}
            
        
            
        //}while (z==permutations3x3.charAt());
        
        //for (int x[]:temp)
        //{
          // System.out.println("&*&*&*&*&*&*&*&*&*&*Conversion string to 3x3 better be ok - FAIL: " + Arrays.asList(x));
        //}
        
        //for (int i=0;i<3;i++)
    //    {
      //      System.out.println("WHYYYYYYYYYYYYYYYY%$£%£%$£%£%£%£%");
        //    System.out.println(temp[i][0] + "  " +  temp[i][1] + " " +    temp[i][1]); 
            
            
        //}
        
        
        
        
        
        
        
        
    }
    
    public void fill3x3()
    {
        //PSEUDO CODE
       
       //might be worth using stream in future
      
      int row=0;
      int col=0;
      int numbersProcessed;
     
      sj = new StringJoiner(",");
      
      System.out.println("There are : " + permutations + " permutations of arranging  3 x 3 grid" );
      
      /*
      //ok so it has completed the full population of a single 3 x 3 grid
      since it has processed   0,0  0,1  0,2
                               1,0  1,1  1,2
                               2,0, 2,1, 2,2
      */
      
      
      do
      {
          //lst=copy;  //restore the original list;
          
          IntStream stream = Arrays.stream(possibleNumbers); 
  
        // Displaying elements in Stream 
        stream.forEach(str -> lst.add(str));
          
          //fucking mistake here
          //why reset this at start of new set entry...
          
          //for a new attempt to add into the set, row continues from next row
          //col=0;  //column will start again from 0 index, however it has already also done this below in modulus check
          //so best to take it out!
          
          
          numbersProcessed=0;
          
          //System.out.println("*****This is the list size------: " + lst.size());
          //System.out.println("******These are permutations completed:" + s.size());
         
         // this is fucking wrong loop..
         //since the loop gets smaller in size... i will process what is left!!!
         //fucking!
         
         //for (int i=0; i<lst.size();i++)  // this will ensure process of random selection from lst
         
         do
         {
             processedDivisibleTwo=false;
             
             //System.out.println("numbers processed:" + numbersProcessed);
             
           int randomNumber = rand.nextInt(lst.size());   //this will get 0-8   rand(9)...  this range is useful for getting random number from the list
      
      //System.out.println("HERE!!!!");
      //System.out.println(row);
      //System.out.println(col);
      
      
      
      randomNumber1to9List=lst.get(randomNumber);
      
      threeBythree[row][col]= randomNumber1to9List;
      
      // since set has failed to work with List<String>, Int[][], Integer[][], String[][]
      //it has proven to work with String....
      //so all the numbers will be concatenated to a String
      //it might be sensible potentially to complete stringjoiner with ,
      //StringTokenizer can be used to perform retrieval....
      //this number here should be exactly stored in threebythree[row][col]
      sj.add(Integer.toString(randomNumber1to9List));
      
      //sudokuMiniGrid = sudokuMiniGrid + Integer.toString(lst.get(randomNumber));
      
      //System.out.println("Following number added into the 3 x 3 grid: " + lst.get(randomNumber));
      lst.remove(randomNumber);
      
      //System.out.println("This is new list size: " + lst.size());
      
      if (col%2==0 && col!=0)    // at this point it has populated row of 3 x 3 grid...
      {
          //System.out.println("divisible");
          row++;  //it has to start a new row
          col=0;  //the column is reset back to 0
          processedDivisibleTwo = true;
      }
      
      if (!processedDivisibleTwo)   // it will only do this condition if it hasn't already been reset to 0 as part of new column above...
      {
      col++;  //otherwise it will increase the column in the given row by 1 until above condition is met...
      //System.out.println("new column: " + col);
      }
      
      numbersProcessed++;
         }while(!lst.isEmpty());
      
      currentSize=s.size();
      //System.out.println("This is the current set size: " + currentSize);
      
      //s.add(Arrays.asList(threeBythree[0][0].toString()));
      s.add(sj.toString());
      
      
      //System.out.println("************This is the first row into String: " + sj.toString());
     
      
      newSize=s.size();
      System.out.println("This is the new set size: " + newSize + "   " + sj.toString());
      
       sj=new StringJoiner(",");
      
      //this will put the matrix version of 3 x 3 if permutation is unique....
      if (newSize>currentSize)
      {
          mp.put(newSize,threeBythree);
      }
      
      get3x3Grid();
      
      row=0;     // the process starts again..
      col=0;  // the process starts again..
      
      //}while (s.size()<permutations);
      }while (s.size()<20);
      
      
      fill9x9(mp);
      get9x9Grid();
       
/*
numbers can be generated via random. and stored in int[row][col] array   (0-2 for rows and col)
get current set size
add int[row][col]  into the set
get new set size
continue until below condition....
}while (set.size()<P(9,9);  // can not do this... since these are permutations if sudoku not met...
// but at same time, it has to explore every single one.....


3 x 3 grids (9 total) filled into   9 x 9 grid    int[this will go from 0-8][value from  0-8]  (need to think about this!!)
                                                                                [between 0-2,  3-5,  6-8] [between 0-2,  3-5,  6-8]

//This will be the natural partitions of the set entries....
0-2
3-5
6-8

Checking at each time that the rows and columns do not contain duplicate numbers.....

Print out the grid to end user......

// this showing that it has placed all small 9 grids inside....
} while (!gridFull)
}  end for

*/
    }
    
    
    public void fill9x9(Map<Integer, int[][]> mp)
    {
      
        
        
        /*
        pseudo
        do
{

                                                                         col=0  col=1 col=2
start any one of the 3x3 grids in position [0,0]       of the      row=0[3x3] [3x3] [3x3]
                                                                   row=1[3x3] [3x3] [3x3]
                                                                   row=2[3x3] [3x3] [3x3]

*remove it from lst (it is removed since it is believed the 3x3 grid can not be replicated)..  and randomnly *pick another 3x3 grid... 
*Check if it can go at [0,1]
*if it can, then remove it from lst (since not possible for the grid to go elsewhere).....
*randomnly pick next one from lst.. check if it can go in position [0,2]
*keep going until gridisFull (9x9)
* store the grid...


*next time around.. item that was [0,1] can not go back in same place....
start process again until grid is full

}while(permutations<UNKNOWN>    // this means that once it has exceeded set number of permutations, it will                                    end.
*/      
        
        Collection<int[][]> col = mp.values();  // this will store all the values.....
        int temp[][]=new int[3][3];
        int totalNumbersProcessed=1;
        
        
        //Since I am so familiar with working with lists and all the entries in HashMap are unique and it 
        //consists of int[][] which is the most workable for exercise, I will put all the map values and add it into
        //a list
        List <int[][]> lt = new ArrayList<>(mp.values());
        Set <int[][]> st = new HashSet<>(mp.values());
        
       
        
        
        
        // This i10 just a quick lambda validation that there is a key and expected entry for number keys
        mp.forEach((key, value) -> System.out.println(key + " : " + value));
        
        
        // we know it has added all map.values() in set and also list...
        
        int rowCount=0;   //used for small 3x3 grid
        int colCount=0;   //used for small 3x3 grid
        boolean ReachEndColMiniGrid=false;
        
        int rowIndex=0;   
        int colIndex=0;
        int offset=0;
        int i=0;
        int numbersProcessed3x3=0;
        int m;
        int entry3x3=0;
        int GridCount3x3=1;
        
        //all values in mini grid to be inserted into top left corner...
            // this now functions for first row in 9 x 9
            //need to introduce logic to start for next!!
            
        //**** need to identify where logic will change ***
        /*
        
        N N N N N N N N N
        N N N N N N N N N
        N N N N N N N N N
        X 0 0 0 0 0 0 0 0
        0 0 0 0 0 0 0 0 0
        0 0 0 0 0 0 0 0 0
        0 0 0 0 0 0 0 0 0
        0 0 0 0 0 0 0 0 0
        0 0 0 0 0 0 0 0 0
        
        The new starting position is no longer [0,0] it is [0,3]  [colIndex, rowIndex]
        Unsure what other logic will change with code?
        */
        
        boolean condition1=false;
        boolean condition2=false;
        boolean condition3=false;
        
        System.out.println("***CHECKING PROPER LIST:");
        //for (int i=0; i<miniGridContainer[0][0].length(); i++)  //using 10 mini grids  for now testing
        //since unsure how to get length of 3d array, will place value manually.
        
        //need to figure out why its not incrementing...
        
        do
        {
            System.out.println("RETURNING HERE^^^^^^^^^^$£^£^£$^£$^$£^£^");
            //System.out.println(i);
            
            
        //for (int i=0; i<mp.size();i++)     // me being a idiot.... since the key stored was newsize, and 
                                           //this started at 1... so mp.get(1) is the first entry...
                                        
        
        //for (int i=0; i<15; i++)  //using 10 mini grids  for now testing
        
        
        
        // taken from internet, there is no other way to acces the set by index
        //so it contains all the strings...
        String[] perm3x3 = s.toArray(new String[s.size()]); 


    // This validates to be from the matrix printed to screen.. But not necessarily same order.. Not critical....
            
            //System.out.println("Expect this to be same as string earlier: " + perm3x3[i]);
            
        
        //Not putting in loop to have clear visibility of activity....
        temp[0][0]=convertStringTo3x3(perm3x3[entry3x3],0);
        temp[0][1]=convertStringTo3x3(perm3x3[entry3x3],2);
        temp[0][2]=convertStringTo3x3(perm3x3[entry3x3],4);
        temp[1][0]=convertStringTo3x3(perm3x3[entry3x3],6);
        temp[1][1]=convertStringTo3x3(perm3x3[entry3x3],8);
        temp[1][2]=convertStringTo3x3(perm3x3[entry3x3],10);
        temp[2][0]=convertStringTo3x3(perm3x3[entry3x3],12);
        temp[2][1]=convertStringTo3x3(perm3x3[entry3x3],14);
        temp[2][2]=convertStringTo3x3(perm3x3[entry3x3],16);
        
        entry3x3++;
        
        //temp=convertStringTo3x3(perm3x3[i]);
        
        
        
            //temp=mp.get(i);
            //temp=mp.get(i+1);
            
            
        System.out.println("******************QUICK CHECK INSIDE:");
        System.out.println("Value of i: " + i);
        System.out.println(temp[2][1] + temp[0][1] + temp[0][2]);
        System.out.println(temp[1][0] + temp[1][1] + temp[1][2]);
        System.out.println(temp[2][0] + temp[2][1] + temp[2][2]);
            
            
            
            
            
            
            // use this when accessing map...
             // this is int[][] array containing the first mini grid...
            //temp = miniGridContainer[i];  //hoping this will get the 2d array stored here....
            //temp= temp = lt.get(i);
            
            
             //System.out.println("^^&&^^^^! size 3x3 grid: **********" + temp.length);
            
            
            //board is 9x9 so it will end properly....
            if (totalNumbersProcessed<=81)
            {
            //needs to complete these only once at start to initialise these.
            //not each time otherwise it will affect the entire code..
            //this is a total improvised technique never tried before..
            //but the if statements appear to lock the blocks so that it can only occur once
    
            
            //it will go in once since it locks condition2 and condition 3
            //processing [0,0] => [2,8]    27 items
            
            if (totalNumbersProcessed<=27 && !condition2 && !condition3)
            {
                System.out.println("ONCE!!!! Condition1");
                rowIndex=0;     //[0,0]
                colIndex=0;
                condition1=true;
                condition2=true;
                condition3=true;
                
            }
            
            //once it has has reached number 28, ready start [3,0] => [5,8]  54 items...
            //condition 1 and 3 will be set to false, so it will be locked!
            
            if (totalNumbersProcessed<=54 && totalNumbersProcessed>27 && condition1 && condition3)
            {
                System.out.println("ONCE!!!! Condition2");
                rowIndex=3;  //[3,0];
                colIndex=0;
                condition2=true;
                condition1=false;
                condition3=false;
            }
            
            
            //checkUniqueColumns()
            
            //once it has has reached number 55, ready start [5,0] => [8,8]  81 items....
            //leaving condition3=false and condition2=false will ensure that
            //once totalNumbersProcessed<=27,  it can enter the first if statement.....
            if (totalNumbersProcessed<=81 && totalNumbersProcessed>54 && condition2 && !condition1)
            {
                System.out.println("ONCE!!!! Condition3");
                rowIndex=6;  // [6,0]
                colIndex=0;
                condition3=false;
                condition1=true;
                condition2=false;
                
            }
            
         System.out.println("\n******This is picking list item:" + i+1);
         System.out.println("*****************************************");
         
            ReachEndColMiniGrid=false;
            
            
// *********************
//At moment, once it finishes the first correctly at (2,2)

/*
1 1 1 X 0 0 0 0 0
0 0 0 0 0 0 0 0 0
0 0 X 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0
*/

// The next list item should be stored in  (0,3)  - it should be stored here
// current logic is taking it here... (2,3)  as expected......
//There is no logic in the coding currently telling it to return back here....

//in first last 3 x 3 grid it finished at  (2,2)
//so clearly the rowIndex (of 9x9) has not reset to 0....

//once it has processed 9 numbers, the row index always goes back to  0,3, 6
//it will go to 0 if it is processing first 3 list items (0,1,2 zero index based).
//it will go to 3 if it is processing next 3 list items (3,4,5 zero index based).
//it will go to 6 if it is processing next 3 list items (6,7,8 zero index based).

/*
It now resolves the issue and writes content from (0,3) to (0,5) for the 2nd list item....

1 1 1 X 0 ! 0 0 0
! 0 0 ! 0 0 0 0 0
0 0 X 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0

after(0,5) it needs to go to (1,3)     - since colIndex 3 is the new starting point...
it is currently going into  (1,0)  - this is similar to it starting the 2nd row  for the 1st list item...
//logic is somewhere in the code once it has realised that rowCount has reached 2
*/


if (numbersProcessed3x3==9)
{
    System.out.println("DECISION");
if (i==0 || i==1 || i==2)
{
    System.out.println("DECISION1");
    
    rowIndex=0;
    
}

if (i==3 || i==4 || i==5)
{
    rowIndex=3;
    
}

if (i==6 || i==7 || i==8)
{
    rowIndex=6;
    
}

}


numbersProcessed3x3=0;
nineByNineBoardNumber=1;

            System.out.println("MUST HERE FUCKING");
            //for (int n=0; n<temp.length;n++ )  // this will go through each row of the 3 x 3  (0-2)(0-2)
            for (int n=0; n<temp.length;n++ )  // this will go through each row of the 3 x 3  (0-2)(0-2)
            
            
            {
                
               
                System.out.println("value of n: " + n);
                System.out.println("Value colcount993: "  + colCount);
                
                if (colCount>=2 && rowCount!=2)  // if it reaches last number of row mini grid in first row
                {
                    System.out.println("Current colcount 3x3: " + colCount);
                    System.out.println("Current rowcount 3x3: " + rowCount);
                    
                    rowCount++;   // it starts new row of mini grid...
                    colCount=0;   // it starts again at column 0 mini grid
                    
                    
                    //ut would also have to start new row on big grid..
                    // for second row of 3x3
                    
                    rowIndex++;
                    
                    //it would only start colIndex if  offset is also equal to 0
                    //this would be the case for 1st 3x3 grid.... in each row.....
                    if (offset==0)
                    {
                        colIndex=0;
                    }
                    else
                    {
                        colIndex=offset;
                    }
                  
                    //IT HAS REACHED THE LAST COLUMN BIG GRID..  COLINDEX8..
                    //IN THIS CASE, IT HAS TO reset back to start new row
                    //IT SHOULD HIT THIS POINT WHEN numbersprocessed has hit 9...
                    
                    
                        //it has to also start again on big grid
                        //but this time it moves down 3 places from [0,0] no to overwrite any data....
                        
                      
                    if (colIndex==8 && numbersProcessed3x3==9)
                    {
                        colIndex=0;
                        rowIndex=rowIndex+3;
                        ReachEndColMiniGrid=true;  //sets flag
                        
                    }
                    
                    //if it hasn't reached the last column on 9x9
                    //and it has processed entire 3 x 3 mini grid...
                    //The next grid is adjacent....
                    // There is no bearing on 
                    
                    
                    if (colIndex!=8 && numbersProcessed3x3==9)
                    {
                        System.out.println("**********************BACK HERE!");
                        colIndex=colIndex+1;
                        rowIndex=0;
                        
                    }
                    
                    
                }
                    //it is uniform array, so can use temp[0]
                for (int k=0; k<temp[0].length;k++)  // this will then go through each column in row....
                {
                    
                    numbersProcessed3x3++;
                    
                    
                    //this has to keep track of the offset in the colIndex (9 by 9 grid)
                    //otherwise when it starts the next row, it will take the colIn
                    if (k==0)
                    {
                        offset=colIndex;
                        
                    }
                    System.out.println("\nSelecting grid " + i +" from : "+ mp.size());
                    System.out.println("Total numbers processed so far: " + totalNumbersProcessed + " out of 81");        
                    System.out.println("$$$$$$$$$$$$$$Current offset in 9x9 grid: " + offset);
                    System.out.println("*****Starting in this col in 9 x 9: " + colIndex);
                    System.out.println("numbersProcessed: " + numbersProcessed3x3);
                    System.out.println("Total numbers processed: " + totalNumbersProcessed);
                    
                    System.out.println("The current coordinate:" + rowCount);
                    System.out.println("The current coordinate:" + colCount);
                    
                    //colindex is wrong for the second list item....
                    //in first row, its fine since it is set to +1 pos from last grid.
                    //when the row has increased, the column has gone to 0, need to change this logic...
                    
                    System.out.println("Following number: " + temp[rowCount][colCount]);
                    
                    System.out.println("being stored at index: " + rowIndex + " " + colIndex);
                    
                    sj.add(temp[rowCount][colCount] + "("+rowIndex+","+colIndex+")");
                    
                    System.out.println("currently processing this from 3 x 3:" + "(" + rowCount + "," +colCount+")");
                    
                    //System.out.println(nineByNineBoardNumber);
                    
                    //nineByNine[rowIndex][colIndex]=miniGridContainer[i][rowCount][colCount];
                    //nineByNine[rowIndex][colIndex]=miniGridContainer[i][rowCount][colCount];
                    
                    nineByNine[rowIndex][colIndex]=temp[rowCount][colCount];
                    
                    //this can potentially be done after the first 3x3 grid is filled in each row..
                    //since one expects the row to be unique at this point...
                    //but no harm anyhow doing it now...
                    //unfortunately due to nature of code, it has to check after a single number is added on the board...
                    //massive overhead...
                    
                    ensure copy of the existing set.......
                    select 1st 3x3 grid..
                    Populate it into 9x9 grid.....
                    remove it from the Set with permutations....
                    
                    checkUniqueRows(nineByNine, rowIndex)   (implemented, started straight away after 1 number in 9x9)
                    //need to work out what to do if its no good the grid...
                    // it needs to prevent this minigrid to be selected again in this position until the numComplete9x9Boards has incremented.
                    // if it violated with first grid, then  this grid can not appear until  1st grid has changed position  (i.e all perms complete with first grid....)
                    
                    
                    if its ok... (this can only be finalised right when numbersProcessed3x3 =9)
                    remove this 3x3 from the  set....
                    
                    When numComplete9x9Boards increases, restore copied set back as original.
                    The board that was in column offset 0  [0,0] of 9x9 has to stay there
                    until it has exhausted all permutations of 3x3 grids around it...
                    
                    
                    
                    
                    
                    
                    //System.out.println(nineByNine[nineByNineBoardNumber][rowIndex][colIndex] + " at " +  "("+rowIndex+","+colIndex+")");
                    
                    
                    //System.out.println("Final ready column: " + colIndex);
                    
                    
                    colCount++;  //moves forwad position on 3 x 3
                    
                    colIndex++;  //moves forward position on the main 9 x 9
                    
                    if (numbersProcessed3x3==9)   //if it has done all avlues in 3x3
                    {
                        colCount=0;   //starts again in 3x3
                        rowCount=0; //starts again in 3x3
                        
                        
                    }
                    
                    if (totalNumbersProcessed!=0 && totalNumbersProcessed%9==0)
                        {
                            //this is indication that it has finished a 3 x 3 grid....
                            //it has to be done before the incrementing of totalNumbersProcessed
                            i++;
                            
                        }
                        
                        //indication that it has filled 9 x 9
                         if (totalNumbersProcessed%81==0)
                        {
                            
                            //nineByNineBoardNumber++;
                            
                            // THIS IS MY PROBLEM NOW!!!!
                            // WHERE SHOULD I STORED THE COMPLETED BOARDS.....
                            //DECIDING IN A MAP FOR NOW!!!!
                            
                            completedBoards.put(numComplete9x9Boards,nineByNine);
                            numComplete9x9Boards++;
                            System.out.println("\nonto Board Number: " + numComplete9x9Boards);
                            
                            totalNumbersProcessed=0;  // starting again......
                            i=0;
                            
                            historyBoards(sj.toString());
                            sj = new StringJoiner(",");
                            
                            temp= wipe9x9Board(temp);
                            
                            //nbn[nineByNineBoardNumber] = new nineByNine();
                            
                        }
                        
                        
                        
                    
                    totalNumbersProcessed++;
                    
                    
                }  //end for loop  to go through  columns in each row
                
                        }   //end for loop for each row
                        
                        
                        
                       
                        
                        
                System.out.println("%$£%$£%$£%%%%%%%%%%%%%%%%%%%%%%%%%%%%");
                System.out.println("%$£%$£%$£%%%%%%%%%%%%%%%%%%%%%%%%%%%%");
                System.out.println("%$£%$£%$£%%%%%%%%%%%%%%%%%%%%%%%%%%%%");
                System.out.println("%$£%$£%$£%%%%%%%%%%%%%%%%%%%%%%%%%%%%");
                
            } 
        
        
    
        //this will get more thought later on...
        //but it should allow termination also if there are 3x3 grids insufficient to fill full board...
        
        GridCount3x3++;
            
        }while((numComplete9x9Boards*9)<=mp.size()); //end for loop iterate throug map
        
            // i is incrementing each time it has finished a 3x3 grid....
            //but it also gets reset to 0.. so pointless in here...
    
    historyBoards("*** END HISTORY***");
            
    }
    
    public void historyBoards(String history)
    {
        //this number will grow quite a lot....
        
        completedBoardsLogs[count]=history;
        int processed=0;
        System.out.println("\nThis is your board " + (processed+1) + " summary: " + completedBoardsLogs[count]);
        count=count+1;
        
        
        for (String s: completedBoardsLogs)
        {
            
            processed++;
            
            
            if (processed<count)
            {
                System.out.println(s +"\n");
            }
        }
        
    }
    
    public boolean checkUniqueRows(int[][] nineByNine, int rowIndex)
    {
        //this will simply do a compare of the grid in current state against all possible numbers
        
        int occurenceNumberRow=0;
        System.out.println("££££££££££££££££££££££££££££££££££££££££££3");
        
        for (int j=0; j<possibleNumbers.length; j++)    
        {
            occurenceNumberRow=0;
            
            for (int i=0; i<nineByNine[rowIndex].length; i++)    //checking column across row
            {
                if (possibleNumbers[j]==nineByNine[rowIndex][i])  //here 0 should be set to rowIndex or 9x9 grid.....
                {
                    occurenceNumberRow++;
                }
                
            }
            System.out.println("Number: " + possibleNumbers[j] + " has occured: " + occurenceNumberRow +  " times in a row");
            
            
        }
        return (occurenceNumberRow>1?false:true);
    }
    
    
    public boolean checkUniqueColumns()
    {
        return false;
        
    }
    public void place3X3Into9x9()
    {
        
    }
    public boolean SudokuComplete()
    {
        return false;
        
    }
    
    public void get9x9Grid()
    {
        //All values are stored in here
        //At moment is has just put consecutive 3x3 grids stored in here:
        //nineByNine
        
        System.out.println("*****filled grid****** - Testing original MiniGridContainer - FAIL");
        
        for (int[][]row: miniGridContainer)
        {
            for (int[] h:row)
            {
            System.out.println(Arrays.asList(h));
        }
        
        }
        
        System.out.println("Trying to print first 3x3 grid in 9x9 grid");
        System.out.println(miniGridContainer[0][0][0] + miniGridContainer[0][0][1] + miniGridContainer[0][0][2]);
        System.out.println(miniGridContainer[0][1][0] + miniGridContainer[0][1][1] + miniGridContainer[0][1][2]);
        System.out.println(miniGridContainer[0][2][0] + miniGridContainer[0][2][1] + miniGridContainer[0][2][2]);
        
        
        /*
        System.out.println("*****filled grid****** - Testing 9x9 board -ArrayList FAIL");
        
        for (int i[]:nineByNine)
        {
            System.out.println(Arrays.asList(i));
        }
        */
        
        
        /*
        System.out.println("*****filled grid****** - Testing 9x9 board -EACH NUMBER into string joiner!!!");
        Character convert;
        String convert1;
        
        for (int i=0; i<nineByNine.length;i++)
        {
            sj = new StringJoiner(",");
            
            for (int k=0; k<nineByNine[0].length;i++)
            {
                System.out.println("Numbers in row : " + i + "  " + nineByNine[i][k]);
                
            }
            
            System.out.println(sj.toString());
        }
        */
        
        
        
        
        
        
        
        
    }
    
    //for some fucking reason, the set is not getting bigger..
    
    public void get3x3Grid()
    {
        miniGridContainer = new int[mp.size()][3][3];
        int m=0;
        
        
        //System.out.println("***********");
        
        //this will get out all the 3x3 grids from the permutations.....
        int i=0;
        if (mp.containsKey(newSize))
        {
            miniGrid = mp.get(newSize);    //minigrid is of type int[][]
            
            //it might be worth putting all this in a 3D array...
            //so the first index can act as unique identifier:
            
            i++;
            
            
            
            
            
            //mp.getKey()
            
            //at this point in might be worth calling fall 9x9 grid
            //now it has reached this...  P (362880,9)
            //n will the unique key...
            
        }
        
        //System.out.println("This should be same in map:");
        //this will print out all the rows.....
        
        System.out.println("FULLY FUNCTIONAL PRINTING THE ARRAY TO STRING");
        for (int[] g :miniGrid)
        {
            //System.out.println("!!!!!This is the key: " + mp.getKey(newSize));
            System.out.println(Arrays.toString(g));
        }
        
        System.out.println("&*^%^%$^$%^PRINTNG THE MINIGRID MANUALLY - FAIL");
        
         System.out.println(miniGrid[0][0] + miniGrid[0][1] + miniGrid[0][2]);
        System.out.println(miniGrid[1][0] + miniGrid[1][1] + miniGrid[1][2]);
        System.out.println(miniGrid[2][0] + miniGrid[2][1] + miniGrid[2][2]);
        
        
        
        
        
        int p=0;
        int k=0;
        int pos=0;
        
        //System.out.println("This should be same in map:");
        //this will print out all the rows.....
        
        System.out.println("------------This is now adding each integer manually in 3d array FAILING:");    
        for (int[] g :miniGrid)   //each row
        {
            k=0;
            
            //System.out.println(Arrays.toString(g));
            
            //now need to get each int...
        
            for (int j:g)
            {
                //filling 3d array...
                
                
                miniGridContainer[m][p][k]=j;
                
                if (k==2)
                {
                    k=0;
                    
                }
                else
                {
                k++;
                }
                
            }
            p++;
        
       
        
            
            //System.out.println("!!!!!This is the key: " + mp.getKey(newSize));
            
        }
        
        System.out.println("------------Expecting this to be same as above if stored properly in 3d array:");    
        System.out.println(miniGridContainer[pos][0][0] + miniGridContainer[pos][0][1] + miniGridContainer[pos][0][2]);
        System.out.println(miniGridContainer[pos][1][0] + miniGridContainer[pos][1][1] + miniGridContainer[pos][1][2]);
        System.out.println(miniGridContainer[pos][2][0] + miniGridContainer[pos][2][1] + miniGridContainer[pos][2][2]);
        
        
        pos++;
        
        
        
        System.out.println("-----adding each integer manually in 3d array full loop:");
        
        MiniTest = new int[3][3];
        
        for (i=0;i<miniGrid.length;i++)
        {
            for (int j=0; j<miniGrid[0].length;j++)
            {
                MiniTest[i][j]=miniGrid[i][j];
                
            
        }
        }
        
        System.out.println("PLEASE BE SAME AS ABOVE MATRIX - FAILS");
        System.out.println(MiniTest[0][0] + MiniTest[0][1] + MiniTest[0][2]);
        System.out.println(MiniTest[1][0] + MiniTest[1][1] + MiniTest[1][2]);
        System.out.println(MiniTest[2][0] + MiniTest[2][1] + MiniTest[2][2]);
        
        
        
        //miniGridContainer[][][]=miniGrid;
        
        // since set has got an  int[][] it will need a nested solution to get value back
        // for each row, go through all the columns.....
        
        // this is just to test that it can reach the grid correctly,
        // this is easiest route to allow it traverse the set....
        
        
        // can imagine this being huge problem in future.
        //since there is no get by index.....
        // this will potential mean the amount of screen output will be very limited..
        // since it will have show entirety!!!
        //very similar to StringTokenizer!!!! and no point taking content and storing elsewhere...
        //Perhaps it can be added into Map at future point only once its fully populated with all permutations...
        // This will then allow it to use the containskey method...
        
        
     m++;       
    }
}
    
            
            //System.out.println(t[0][0]);
            //System.out.println(t[0][1]);


public class Permutation
{
public static void main(String[] args) {
System.out.println("Welcome to Online IDE!! Happy Coding :)");
int originalNumber=9;
int n=originalNumber;
int r =9;
Map <Integer, Long> m = new HashMap<>();
System.out.println("***PERMUTATIONS***");
System.out.println("P(n,r) = n! / (n−r)!");
System.out.println("P(" + n+","+r+") = " + n+"!" + " / " + "("+n+"-"+r+")!");

Sudoku sud = new Sudoku (Permutations (n,r,originalNumber, m));


//System.out.println(Permutations (n,r,originalNumber, m));
}
public static long Permutations (int n, int r, int originalNumber, Map factorialResults)
{
// n are objects
// r is sample
/*
***CALCULATION***
P(n,r) = n! / (n−r)!
*/
long result=0;
int temp;
int denominator;
if (originalNumber<r || r<0)
{
System.out.println("please enter n ≥ r ≥ 0");
System.exit(0);
return 0;
}
if (n>=1)
{
// EXAMPLE
// P (5,6) = 5* 4 * 3 * 2 * 1 / (6-5)! = 24 / 2! = 24 / 2 * 1 = 24/2 = 12
result = (n* (Permutations (n-1, r,originalNumber, factorialResults))); // this completes factorial for numerator
factorialResults.put(n,result); //result stored in the Map
//System.out.println("getting result back out numerator " + n+": " + factorialResults.get(n));
if (n==originalNumber) // this will occur once
{
denominator = originalNumber-r; // originalNumber required since n has reduced as part of the recursive calls
//System.out.println("This is denominator: " + denominator);
// this is using the Java Memoization technique to ensure the factorial outcome is not calculated again, to save program execution cycles.
// since the returns are done in reverse order.... n = 1 is processed first and n=6 last...
//Hence in practice there will be entry in Map for all factorials, ready for the denominator..
if (factorialResults.containsKey(denominator))
{
//System.out.println("here");
//System.out.println("This is exact value of factorial denominator " + (denominator) + " : " + factorialResults.get(denominator));
return result / (long)factorialResults.get(denominator); // this is number permutations
}
}
return result; // this will be returning already calculating numerator part
}
return 1; // // it should reach here if this is false: (n>=1) }
}
}
