/*
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
//Difficult to produce..


// 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

// FINISHED - FILLING GRID.. GIVING SCREEN OUTPUT OF NUMBER TIMES NUMBER HAS APPEARED...



//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

//IT FILLED 9x9,


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

//how to process column check

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

interface Fillable   //KEEP
{  //KEEP
    public void fill3x3Manual();  //KEEP: Method failed. Tried to populate list manually with strings to see if a solution can be reached..
    public void fill3x3();  //KEEP:  method to fill 3x3 grids...
    public void fill9x9(Map<Integer, int[][]> mp);  // KEEP: fills the full board...
    public boolean checkUniqueRows(int [][] temp, int rowIndex);  //checks if row is unique..
    public boolean checkUniqueColumns(int[][] nineByNine, int colIndex); //checks if column is unique..
    public boolean sudokuComplete(boolean a, boolean b);  //checks if valid grid based on the above...
    public void get9x9Grid();  //experimental, trying to recover information from collections, but fails....
    public void get3x3Grid();   //largely experimental, but it also has loop to show rows of two dimensional matrix of 
    public void wipe9x9Board(int[][] formattedBoard, int[][] nineByNine);  //wipes board, formattedBoard(derived from strings to ints) and ninebynine getting values from temp array.
    public void print9x9Board(String history, BigInteger numComplete9x9Boards); //keeps log of all completedBoards
    public int convertStringTo3x3(String permutations3x3, int getNumString); //it takes string from set of permutations and puts it into a int[3][3] array 
    public void realTime9x9Fill(String history);  // this shows how the grid is filling and impact on numbers in row and col
    public void display9x9(); // this will show the 9x9 onto the screen.....

}

class nineByNine
{
    
    
    
    
    int test;

    public nineByNine()
    {
        //initial state nineByNine grid

        //int nineByNineCopy[][] = nineByNine.clone();
        // I intened to use this so that it can be restored again once board is complete..
        // but had issues and it never seemed to work...
        //so just manually set 0's back in.....
    }
}

class Sudoku implements Fillable
{
    
    int randomNumber1;
    
    int numRetrieved3x3GridsIn9x9Grid;
    
    BigInteger numberPossibleBoards = new BigInteger("108883584818776183656945007213012309135068193536000");

    Set<String> permutationAllBoards = new HashSet();   //stores all the strings of permutations

    Map<Integer, int[][]> mp = new HashMap();  //this will hold all the indexes....

    int possibleNumbers[] = new int[]{1,2,3,4,5,6,7,8,9};  //all possible numbers

    List<Integer> lst = new ArrayList<Integer>();  // list will be used to hold all numbers above for selection...

    int MiniTest[][] = new int[3][3];  //used for testing, storing values....
    int formattedBoard[][] = new int [9][9];   // this will hold numbers retrieved from string of board summary...

    Map<BigInteger, int[][]> completedBoards = new HashMap<>();  //All completed boards stored here...


    //Need to change this into BigInteger
    BigInteger numComplete9x9Boards = new BigInteger("1");
    //int numComplete9x9Boards=1;   //number completed 9x9 boards....



    StringJoiner sj1 = new StringJoiner(",");  // initialised first time......
    //This will be used to get values from formattedBoard row by row...
    //It is used for screenoutput of the entire 9x9 structure....


    // I was thinking about introducing new nineByNine class, but couldn't see real purpose..
    // This would be ideal if I did evenutally moved onto area of testing partially filled 9 by 9 grid
    // to keep logic separate..

//nineByNine [] nbn = new nineByNine[5000]; // is it best way to create an array on nineByNine classes...
//nbn[0]= new 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} };


    int totalNumbersProcessed=1;   ///ranging from 1-81


    long permutations;   // all permutations retrieved from the driver class....
    String Permutations3x3into9x9;   // holds value of all permutations arranging 9 grids from 362800


    int threeBythree[][] = new int[3][3];   // will pass numbers into the map...
    //Set <Integer[][]> s = new HashSet<>();  // used as part of experimention as documented...


    Set<String> s = new HashSet();   //stores all the strings of permutations


    Set<String> copyPermuations = new HashSet(s);
    //copy of main Set, this was intended to be used if for instance one 3x3 selected, it could not be used
    //again since each 3x3 grid is unique in 9x9... But became highly irrelevant reducing 362800 by 1 each time


    StringJoiner sj;      //used to format the string added into the set...
    int storeMiniGrids[][][];  // used for testing....

    int currentSize;  //gets current size of the set
    int newSize;  //gets new size of the set....
    int[][] miniGrid;     // this is used to get value out of the map....
    int[][][] miniGridContainer;  //used to store the minigrids into 3d array (part of learning)

    List<Integer> copy = new ArrayList<>(lst);  //mantain original list of possibleNumbers...
    //useful once listed has been emptied and restore it back...

    boolean endFirstRow3x3=false;  //used to ascertain if reached end of row for 3x3 grid...
    Random rand = new Random();   // instance for generating random number....

    String[] completedBoardsLogs = new String[10000];
    //This will store boards in the format:
    //8(0,0) 7(0,1) 1(0,2) 5(1,0) 2(1,1) 9(1,2) 4(2,0) 3(2,1) 6(2,2) 5(0,3) 8(0,4) 9(0,5) 6(1,3) 4(1,4) 7(1,5) 2(2,3) 3(2,4) 1(2,5) 5(0,6) 6(0,7) 4(0,8) 3(1,6) 8(1,7) 1(1,8) 7(2,6) 2(2,7) 9(2,8) 1(3,0) 7(3,1) 4(3,2) 3(4,0) 5(4,1) 6(4,2) 9(5,0) 8(5,1) 2(5,2) 5(3,3) 1(3,4) 8(3,5) 7(4,3) 3(4,4) 2(4,5) 9(5,3) 6(5,4) 4(5,5) 9(3,6) 5(3,7) 3(3,8) 7(4,6) 1(4,7) 8(4,8) 2(5,6) 4(5,7) 6(5,8) 3(6,0) 6(6,1) 2(6,2) 1(7,0) 4(7,1) 9(7,2) 7(8,0) 8(8,1) 5(8,2) 4(6,3) 3(6,4) 2(6,5) 7(7,3) 6(7,4) 5(7,5) 9(8,3) 1(8,4) 8(8,5) 4(6,6) 1(6,7) 7(6,8) 6(7,6) 5(7,7) 3(7,8) 2(8,6) 8(8,7) 9(8,8)
    //Java or any platform will not allow an array as large as required for storing successful arrangements of 9x9 grids,
    //let alone the all permutations of 9x9 grids
    // 6,670,903,752,021,072,936,960

    int count=0;   // used in print9x9Board()  for completedBoardsLogs[count]
    int rowIndex=0;  // used for the  row on 9x9 grid
    int colIndex=0;  // used for the  col on 9x9 grid


    int randomNumber1to9List;  //  holds value of  possibleNumbers generated from lst.get(randomNumber)

    boolean failedColumns;  //passed into sudokuComplete
    boolean failedRows;    //passed into sudokuComplete
    boolean sudokuSuccess;  //this was used for ADVANCE pseudocode, 
    //when trying to deal with situation such as getting a success 9x9 grid or failed grid.
    //But it needs too much thought on how to code for high permutations..
    
    

    


    public void wipe9x9Board(int [][]formattedBoard, int nineByNine[][])
    {
        //System.out.println("GET ING HERE !!!!!");
        //System.out.println("before:" + nineByNine[8][8]);
        //formattedBoard = nineByNineCopy.clone(); 
        //nineByNine = nineByNineCopy.clone();

        //fill each index with 0....

        for (int q=0; q<nineByNine.length; q++)    //can use temp here or also the blank 9x9 grid with 0, same size...
        {
            for (int r=0; r<nineByNine[0].length; r++)

            {
                formattedBoard[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)...
            }

        }
        //System.out.println("after" + nineByNine[8][8]);

    }

    //constructor:
    public Sudoku(long permutations, String  Permutations3x3into9x9)
    {
        this.permutations =permutations;
        this.Permutations3x3into9x9=Permutations3x3into9x9;


        fill3x3();

        //if end user wants to fill grids manually, they can attempt this and comment top one...
        //But there are issues at moment..
        //fill3x3Manual();

    }


    //This is passed into method below
    //perm3x3[entry3x3],      getnum: 0
    //perm3x3[entry3x3],    getnum: 2...
    //perm3x3[entry3x3],    getnum: 12

    //perm3x3 is getting information from string array (taking all permutation values in the list)
    //entry3x3  -  this ranges from  0-size of the set
    //it increments each time a set it used..
    //since perm3x3 is formattted as such  1,2,3,4,5,6,7,8,9    getnum has to alterate from index 0,2,4....

    public int convertStringTo3x3(String permutations3x3, int getNum)
    {
        int temp;
        char num;
        String numString;

        num=permutations3x3.charAt(getNum);
        numString= String.valueOf(num);

        temp= Integer.parseInt(numString);

        //System.out.println("****** PRINT VALUE BACK %%%%%: " + temp);

        return temp;


    }


    //Explanations as below...
    public void fill3x3Manual()
    {
        //This is the new set size: 1   1,7,6,3,5,2,4,8,9
        //FULLY FUNCTIONAL PRINTING THE ARRAY TO STRING
        //[1, 7, 6]
        //[3, 5, 2]
        //[4, 8, 9]

        //We know the above is accepted string format for the numbers in the 3x3 grid....
        //I will populate some grids into the set in a similar way...
        //It will be nine  3x3  squares that will get Sudoku
        //I will also at some point try to experiment with order of these.... to try and get a fully working solution...
        // once I can apply this knowledge here, it will be transferrable to the bigger solution...
        // there is also less clutter here....
        //also I can try and pushing this until it hits  P(9,9)
        // But will need to switch off several system.out.println()!!!!!
        
        /*
        1 2 3    4 5 6     7 8 9
        4 5 6    7 8 9     1 2 3
        7 8 9    1 2 3     4 5 6
        
        2 3 1   6 4 5      9 7 8
        5 6 4   9 7 8      3 1 2
        8 9 7   3 1 2      6 4 5
        
        3 1 2   5 6 4      8 9 7
        6 4 5   8 9 7      2 3 1
        9 7 8   2 3 1      5 6 4
        */


        s.add("1,2,3,4,5,6,7,8,9");
        s.add("4,5,6,7,8,9,1,2,3");
        s.add("7,8,9,1,2,3,4,5,6");
        s.add("2,3,1,5,6,4,8,9,7");
        s.add("6,4,5,9,7,8,3,1,2");
        s.add("9,7,8,3,1,2,6,4,5");
        s.add("3,1,2,6,4,5,9,7,8");
        s.add("5,6,4,8,9,7,2,3,1");
        s.add("8,9,7,2,3,1,5,6,4");


        //get3x3Grid();  can not do this....
        //fill9x9(mp);  // having issue running this.... relies on too much logic from filling it randomnly...



    }



    public void fill3x3()
    {

        int row=0;
        int col=0;
        int numbersProcessed;   //it will range from 1-81

        sj = new StringJoiner(",");   //new instance of StringJoiner

        System.out.println("There are : " + permutations + " permutations of arranging  3 x 3 grid" );
        System.out.println("There are : " + Permutations3x3into9x9 + " permutations of arranging  3 x 3 grid into 9 x 9:" + "P(362880,9)" );
        System.out.println("There are : 6,670,903,752,021,072,936,960" + " permutations of completing sudoku (taken from internet)");

        System.out.println("This code will attempt to explore but its impossible to expect much");
        System.out.println("It is used for foundation of experimentation but also it has made serious attempt to complete random process to make a grid");
        System.out.println("I am removing excess code so it is ready future development.");
      
      /*
      //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
      */


        // KEEP:  this is for set.size().. Set size is determined by end user... It is intended to be set maximum permutaton = 362800
        //It might need to be decreased due to memory limitations..

        do
        {
            //Could have also been done in other iterative ways...
            //tidy code found on internet...
            IntStream stream = Arrays.stream(possibleNumbers); //Stream to take numbers from array
            stream.forEach(str -> lst.add(str));  //placing elements stream into a list...


            numbersProcessed=0;  //ranges from, 0-81

            //value decreases once a number chosen for 3x3 grid...
            //System.out.println("*****This is the list size------: " + lst.size());   //list size


            //System.out.println("\n******These are permutations completed:" + s.size());  //set size


            do    //do while list is not empty
            {
                endFirstRow3x3=false;   // used to mark end of row of 3x3 grid  ([X][2])

                int randomNumber = rand.nextInt(lst.size());
                //this will get 0-8   rand(9)...  this range is useful for getting random number from the list

                randomNumber1to9List=lst.get(randomNumber);     //it will get 1-9 based on random index from list...
                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));  //added to StringJoiner
                lst.remove(randomNumber);  //this removes random number from the list....

                //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...
                {

                    row++;  //it has to start a new row    for threebythree[][]
                    col=0;  //the column is reset back to 0
                    endFirstRow3x3 = true;  //flag for reaching end of row...
                }

                if (!endFirstRow3x3)   // 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...

                }

                numbersProcessed++;   //counter of 1-81 increased....
            }while(!lst.isEmpty());   //while list contains a number 1-9......

            currentSize=s.size();
            //System.out.println("This is the current set size: " + currentSize);

            s.add(sj.toString());   // since do while loop has ended, it is now in position to
            //add StringJoiner consiting of for example  1,2,3,4,5,6,7,8,9  into the set...

            newSize=s.size();   //check new set size....
            //System.out.println("This is the new set size: " + newSize + "     Added:   " + sj.toString());

            sj=new StringJoiner(" ");  //the StringJoiner is now used for.....
            //keeping archive of all numbers numbers going into the board...
            //8(0,0) 7(0,1)   format as follows....


            //this will put the matrix version of 3 x 3 if permutation is unique....
            if (newSize>currentSize)
            {
                mp.put(newSize,threeBythree);  //puts the filled threeBythree into a HashMap...
                //again in my code this is used for limited purpose, it only shows
                //minigrid to end user on screen, since it was easiest way before getting content available from Set..
            }

            get3x3Grid();  //method call....

            row=0;     // the process starts again
            col=0;  // the process starts again..


            // was contemplating putting a loop inside, but unsure if it right place..
            // it might be useful future when advancing the code...
            //at moment, it is too premature to execute this....

            //}while (!sudokuComplete(failedRows,failedColumns))


            //the top one is default value from permutation class....362,800
            //}while (s.size()<permutations);
        }while (s.size()<362800);    // this is getting  <(NUMBER)  x   (3x3 boards)
    //}while (s.size()<2000);    // this is getting  <(NUMBER)  x   (3x3 boards)


        fill9x9(mp);   //method call
        get9x9Grid();  //method call
       
/*
*** PSEUDO CODE   ****
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

*/
    }


//I HAVE TO RETHINK THIS METHOD
//WE ARE Justified to remove 3x3 grid once it has filled it into 9x9 grid.
//BUT AT THE END OF THE ENTIRE PROCESS OF FILLING 9x9 grid, we need to restore it back to its original state
//Also need to devise a method of selecting a 3x3 grid.


    public void fill9x9(Map<Integer, int[][]> mp)
    {
        System.out.println("\nCurrent sudoku board: " + numComplete9x9Boards + "  out of " + Permutations3x3into9x9);
        
        /*
        
// AT THIS POINT I DEVELOPED SOME PSEUDO CODE ON HOW I COULD EXPLORE THE 9x9 GRID
//INTO VARIOUS WAYS... BUT I NEED TO BECOME VERY CONFIDENT WITH MY CODE TO TRY THIS..
//IT WILL ALSO HAVE LIMITATIONS...
****PSEUDO CODE ******

        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.
*/

        // this will store all the values.....
        //not used in my code, but I mantained it here since its usefull and tidier than 
        //for each loop  or doing a containsKey and then getting desired item....

        //Collection<int[][]> col = mp.values();

        // This i10 just a quick lambda validation that there is a key and expected entry for number keys
        //note the value will not be as expected since its an array....
        //mp.forEach((key, value) -> System.out.println(key + " : " + value));
        //All values print out [[I@e580929   ,  which emphasising issue with using primitive array
        //or any array in that matter...

        int temp[][]=new int[3][3];
        int successfulInputted3x3=0;



        //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

        //I decided not to use this code, but it offers a simple way to get all map values into different
        //collection
        List <int[][]> lt = new ArrayList<>(mp.values());
        Set <int[][]> st = new HashSet<>(mp.values());

        int rowCount=0;   //used for small 3x3 grid
        int colCount=0;   //used for small 3x3 grid
        boolean ReachEndColMiniGrid=false;


        int offset=0;
        int i=1;
        int numberOf3x3Processed=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;  // used to ensure mutual exclusive nature of conditions later in code and prevent multiple repetitions
        boolean condition2=false;  // used to ensure mutual exclusive nature of conditions later in code and prevent multiple repetitions
        boolean condition3=false;  // used to ensure mutual exclusive nature of conditions later in code and prevent multiple repetitions


        do
        {

            //System.out.println("I VALUE: " + i);


            //for (int i=0; i<mp.size();i++)     // 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


            // ****  FUTURE CODE  ******************
            // taken from internet, there is no other way to acces the set by index
            //so it contains all the strings...

            //note this will get smaller as items removed from set
            String[] perm3x3 = s.toArray(new String[s.size()]);

            String second3x3StringPlacedInGrid;    //planned to be used advancing my code, not used at moment...


            //Note the board is valid sudoku when the first 3x3 is in it.
            // It's the second one that causes issues....


            second3x3StringPlacedInGrid=perm3x3[1]; //each time second is removed..... since this goes into large grid...

            //if (!sudokuSuccess)
            {
                //s.remove(second3x3StringPlacedInGrid);
                //}

                // **********************


                // 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....
                //convertString is taking the String from the set and converting to 3 x 3 grid.
                //each value stored individually....
                
                
                //THIS IS CRITICAL PART IN WHICH I NEED generate a random number
                //We will need to generate a random number between 0 and perm3x3 size
                
                randomNumber1 = rand.nextInt(perm3x3.length);
                
                //need to store the random number and ensure that it is not used previously on the current same board configuration...
                //we also know that one of the random numbers is 0, and that is default array value
                //so need to be mindful number times executed...
                //we know that permutations boards are stored in  String array perm3x3
                
                boolean isFirstEntry=true;
                int increm=0;
                boolean hasRepeat3x3GridIn9x9Grid = false;
                numRetrieved3x3GridsIn9x9Grid++;
                int uniqueEntry=0;
                
                //we know array is limited to 9  of  3x3 grids
                int [] storeRetrieved3x3GridsIn9x9Grid = new int[9];
                
                //we have set up the outer do while loop since the only way the process will work
                //is if we have 9   3x3 unique grid numbers from Perm 3x3
                
                do
                {
                do
                {
                    if (increm==0 && isFirstEntry)
                    {
                         storeRetrieved3x3GridsIn9x9Grid[numRetrieved3x3GridsIn9x9Grid]=randomNumber1;
                         //System.out.println("UNIQUE************************************: " + storeRetrieved3x3GridsIn9x9Grid[numRetrieved3x3GridsIn9x9Grid]);
                         uniqueEntry++;
                         System.out.println("UNIQUE***************: " + uniqueEntry + "   " +storeRetrieved3x3GridsIn9x9Grid[numRetrieved3x3GridsIn9x9Grid]);
                         isFirstEntry=false;
                    }
                    
                //we are going to check against number times that a 3x3 grid has been obtained successfully 
                for (int count: storeRetrieved3x3GridsIn9x9Grid)
                {
                    //this is checking if the randomNumber1 (random from size of perm3x3) has already been drawn from the set
                    //we know that the for loop will not increment if numRetrieved3x3GridsIn9x9Grid==0
                    //so we know that if randomNumber1 (number generated) was actually 0 and that it was checking against
                    //storeRetrieved3x3GridsIn9x9Grid[count], there are no issues
                    
                    if (randomNumber1==count &&uniqueEntry!=0)
                    {
                        hasRepeat3x3GridIn9x9Grid=true;
                        //need generate another random number
                        randomNumber1 = rand.nextInt(perm3x3.length);
                    }
                }
                
                //the for loop will execute again to check
                //isFirstEntry=false;
                }while (!hasRepeat3x3GridIn9x9Grid);
                
                
                //we can confirm that grid number is unique
                
                storeRetrieved3x3GridsIn9x9Grid[numRetrieved3x3GridsIn9x9Grid]=randomNumber1;
                //System.out.println("******************************************");
                
                uniqueEntry++;
                
                System.out.println("UNIQUE***************: " + uniqueEntry + "   " +storeRetrieved3x3GridsIn9x9Grid[numRetrieved3x3GridsIn9x9Grid]);
                
            }while(uniqueEntry<9);
                
                isFirstEntry=true;
                hasRepeat3x3GridIn9x9Grid=false;
                increm=0;
                uniqueEntry=0;
                isFirstEntry=true;
                
                //System.out.println("******************************************");
                //System.out.println("**********YOU ARE GETTING FOLLOWING GRID FROM STORE: " + entry3x3);
                //System.out.println("******************************************");
                //We know before entry3x3 was being incremented by one
                //This time we are interested in the random numbers that are presented in the storeRetrieved3x3GridsIn9x9Grid
                //which are all unique
                
                for (int z: storeRetrieved3x3GridsIn9x9Grid)
                {
                    entry3x3=z;
                    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);
                }
                
                //we can now re-initialise
                storeRetrieved3x3GridsIn9x9Grid = new int[9];
                numRetrieved3x3GridsIn9x9Grid=0;
                
                //This would be the best time to keep back up of temp[0][0] to ensure same one appears here until all permutations complete...


                //***************FUTURE CODING****************

                int first3x3GridSelected[][] = new int[3][3];
                int rollBackRowIndex;

                //this is ensuring that if there was sudoku success in first 9x9 grid..
                //It would retain the previously first 3x3 grid in the same position....
       
       /*
       //QUITE IMPOSSIBLE, TRYING TO DO SITUATON IF SUDOKU FOUND AND RETAINING FIRST GRID....
       if (sudokuSuccess && entry3x3==0)
       {
           //need to figure out when it would not be the case....
       //logic is when all permutations have happened of all the numbers around it...
       // this would be p(8,8) = 40320
       // So once another 40320 boards have been filled in this scenario...
       //the first 3 x 3 will be available again....
       // and also not allowed in first place again....
       
          for (int i=0;  i<  40320)
          {
           temp=first3x3GridSelected.clone();
          }
       }
       */
                //removed carefully
                /*
                if (entry3x3==0)
                {
                    first3x3GridSelected=temp.clone();
                    //Arrays.copyOf(0,0,temp.length);

                    //System.out.println("Check for clone: ");

                }
                */

                ////*******************************


                //entry3x3++;
                


                //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)
                    {

                        rollBackRowIndex=rowIndex;    //part of future work.....

                        rowIndex=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!
            
            /*
             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
             N 0 0 0 0 0 0 0 0    Number 28 on this row marked with N
             0 0 0 0 0 0 0 0 0
             0 0 0 0 0 0 0 0 N
             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
            */



                    if (totalNumbersProcessed<=54 && totalNumbersProcessed>27 && condition1 && condition3)
                    {

                        rollBackRowIndex=rowIndex;  // Future code

                        rowIndex=3;  //[3,0];
                        colIndex=0;
                        condition2=true;
                        condition1=false;
                        condition3=false;
                    }


                    //checkUniqueColumns()  initially decided to check unique columns here... This method has quite a flexible point to be called....


                    //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)
                    {
                        rowIndex=6;  // [6,0]
                        colIndex=0;
                        condition3=false;
                        condition1=true;
                        condition2=false;
                    }

                    System.out.println("*****************************************");

                    ReachEndColMiniGrid=false;     // this mignt not be required since value already false from top.
                    //but it was set again anyhow....



                    //SOME OF THE THOUGHT PROCESSES TO UNDERSTAND HOW THE 3x3 GRID FROM SET FILLS THE BOARD...
// *********************
//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 rowIndex 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
*/

//As explained above, it has processed adding all 9 numbers from the set onto bigger grid
// 

//Could use a switch here, but for

//0 0 0 0 0 0 0 0 0    RowIndex = 0
//0 0 0 0 0 0 0 0 0    RowIndex = 1
//0 0 0 0 0 0 0 0 0    RowIndex = 2
//0 0 0 0 0 0 0 0 0    RowIndex = 3
//0 0 0 0 0 0 0 0 0    RowIndex = 4
//0 0 0 0 0 0 0 0 0    RowIndex = 5
//0 0 0 0 0 0 0 0 0    RowIndex = 6
//0 0 0 0 0 0 0 0 0    RowIndex = 7
//0 0 0 0 0 0 0 0 0   RowIndex =  8


// is is taken to be which grid
//it will be later phased out since it is a very generic variable...

                    if (numberOf3x3Processed==9)    // if it has completed all numbers in the 3 x 3 grid....
                    {

                        switch(i)
                        {
                            case 1:
                                rowIndex=0;
                                break;
                            case 2:
                                rowIndex=0;
                                break;
                            case 3:
                                rowIndex=0;
                                break;
                            case 4:
                                rowIndex=3;
                                break;
                            case 5:
                                rowIndex=3;
                                break;
                            case 6:
                                rowIndex=3;
                                break;
                            case 7:
                                rowIndex=6;
                                break;
                            case 8:
                                rowIndex=6;
                                break;
                            case 9:
                                rowIndex=6;
                                break;
                        }
                    }


                    numberOf3x3Processed=0;

                    for (int n=0; n<temp.length;n++ )    //temp is array [2][2]
                    {

                        if (colCount>=2 && rowCount!=2)  // if it reaches last number of  first row
                        {

                            rowCount++;   // it starts new row of temp[][]
                            colCount=0;   // it starts again at column 0


                            //would also have to start new row on big grid..
                            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 rowIndex
                            //IT SHOULD HIT THIS POINT WHEN numbersprocessed has hit 9...
                            //otherwise it has not finished inputting the last 3x3 grid into
                            //9x9

                            //it has to also start again on big grid
                            //but this time it moves down 3 places (rowIndex) from [0,0]  to [3,0]
                            //no to overwrite any data....

                            if (colIndex==8 && numberOf3x3Processed==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 by exactly 1 place (colIndex)
                            //

                            if (colIndex!=8 && numberOf3x3Processed==9)
                            {
                                colIndex=colIndex+1;
                                rowIndex=0;  //it starts again on top row of 9x9
                            }

                        }

                        //it is uniform array, so can use temp[0] or temp.length

                        for (int k=0; k<temp[0].length;k++)  // this will then go through each column in row....
                        //or each row if temp.length is used....
                        {
                            numberOf3x3Processed++;


                            //this has to keep track of the colIndex (9 by 9 grid)
                            //It is stored in offset..
                            //otherwise when it starts the next row, it will lose position

                            // The offset needs to be considered at commence of each column on temp[][]
                            if (k==0)
                            {
                                offset=colIndex;   //offset becomes the current colIndex on the 9x9 grid....

                            }

                            //*** UNSURE WHERE THIS COMMENT RESIDED.. BUT ITS SORT ISSUES I HAD TO WRITE DOWN ******
                            //PERHAPS THERE ARE EASIER WAYS TO POPULATE THE GRID... BUT I THINK I HAVE AT LEAST GIVEN IT LOTS
                            //FLEXIBILITY POINTS FOR MANIPULATION OF ADDING VALUE....
                            //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...


                            //This is expected based on values inputted under no constraints....


                            System.out.println("Selecting grid (3x3) " + i +" from : "+ s.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("The current coordinate(3x3):  " + "(" +rowCount +","+ colCount +")");
                            System.out.println("Following number chosen: " + temp[rowCount][colCount]);
                            System.out.println("being stored at coordinate(9x9): " + "(" + rowIndex + "," + colIndex +")");


                            System.out.println("currently processing this from 3 x 3:" + "(" + rowCount + "," +colCount+")");


                            //Follwing added into StringJoiner
                            //In this format  8(0,0) 7(0,1)
                            sj.add(temp[rowCount][colCount] + "("+rowIndex+","+colIndex+")");


                            //CRITICAL CODE, WITH ALL OFFSETS ABOVE, THIS FINALLY STORES  3x3 GRID INTO 9x9
                            // FROM LEFT TO RIGHT, ROW BY ROW
                            nineByNine[rowIndex][colIndex]=temp[rowCount][colCount];



                            //** FUTURE CODE ****
                            //BUT THIS TECHNIQUE FOR PERMUTATION WILL BE TOO EXHAUSTIVE...
                            //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....


                            // FURTHER PSEUDO CODE FOR ADVANCED PART OF TRYING TO GET ALL PERMUTATIONS.....
                            // ******** PSEUDO CODE ***********

                            //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 (if it violated with first grid), until the numComplete9x9Boards has incremented.
                   
                   /*
                    if its ok... (this can only be finalised right when numberOf3x3Processed =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...
                   
                   */
                            // ***************************************


                            realTime9x9Fill(sj.toString());    //method call, this also checks for uniquerows and uniquecols...


                            colCount++;  //moves forwad position on 3 x 3

                            colIndex++;  //moves forward position on the main 9 x 9

                            if (numberOf3x3Processed==9)   //if it has done all values 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

                                System.out.println("row: " + failedRows);
                                System.out.println("col: " + failedColumns);
                                System.out.println("Numbers processed in 3x3 grid:" + numberOf3x3Processed);
                                if (numberOf3x3Processed==9)
                                {
                                    if (!failedRows&& !failedColumns)
                                    {
                                        System.out.println("ever here");
                                        successfulInputted3x3++;
                                    }
                                    else
                                    {
                                        successfulInputted3x3=0;
                                    }
                                }

                                System.out.println("Streak of successful 3x3 blocks: " + successfulInputted3x3);



                                i++;    // goes from 1-9.....

                            }

                            //indication that it has filled 9 x 9
                            if (totalNumbersProcessed%81==0)
                            {

                                //adds ninebynine board into map... Again, this is not used in coding... But was initially thought that having
                                //aspect of containsKey, it might trigger a technique to try different 9x9 boards....
                                completedBoards.put(numComplete9x9Boards,nineByNine);



                                print9x9Board(sj.toString(), numComplete9x9Boards);  //method call..

                                System.out.println("\nCurrent sudoku board: " + numComplete9x9Boards + "  out of " + (int) (s.size()/9) );

                                
                                //numComplete9x9Boards++;

                                totalNumbersProcessed=0;  // starting again...... from 0-81

                                i=1; // reset again...

                                sj = new StringJoiner(" ");  //new StringJoiner to wipe contents....


                                //thie will evaluate to true if there are failedRows and failedColumns....
                                if (sudokuComplete(failedRows, failedColumns))
                                {
                                    //this brings original set back....
                                    // It is unlikely if actually reducing set size on selection of 3x3 grids... will increase chance of getting a 9x9 board...
                                    //for the moment it is re-instated anyhow....                                  
                                    s = new HashSet(copyPermuations);

                                    //This variable is for my advanced pseudo, not pursued...
                                    sudokuSuccess=true;
                                }

                                else
                                {


                                }

                                //This was inline with trying to creating new classes of nbn...
                                //But not sure benefit at moment..
                                //it might be useful if techniques are sought to manipulate the 9x9 board further and keep logic separate from implenting interface....

                                //nbn[nineByNineBoardNumber] = new nineByNine();

                            }

                            totalNumbersProcessed++;


                        }  //end for loop  to go through  columns in each row

                    }   //end for loop for each row

                    System.out.println("*************************************");
                }
            }


            //need to know use context of BigInteger. We need to use the set size which stores all the completed 9x9 boards
            //and stop when it reaches the astronomical total!!!
            System.out.println("num complete: " + numComplete9x9Boards);
            System.out.println("num possible: " + numberPossibleBoards);
            
        } while (numComplete9x9Boards.compareTo(numberPossibleBoards)==-1);
        System.out.println("BEYOND HERE");

        //}while((numComplete9x9Boards*9)<=27); //end for loop iterate through Set
        //it will end sensibly since numComplete9x9Boards has incremented already.
        // so if the set has 20 (3x3) and it has processed 2 x numComplete9x9Boards
        //3 x 9 = 27....   which exceeds 20.....


        //we can consider another do while loop here
        //this will be

    }

    // this prints the board on the screen..
    public void print9x9Board(String currentStringJoinerFullGrid, BigInteger numComplete9x9Boards)
    {

        //String currentCompleted9x9Board=completedBoardsLogs[count];     //keeps track of current 9x9 board....

        //it stores value in array on Strings...
        completedBoardsLogs[count]=currentStringJoinerFullGrid;
        //7(0,0) 2(0,1) 8(0,2) 5(1,0) 3(1,1) 4(1,2) 1(2,0) 9(2,1) 6(2,2) 7(0,3) 5(0,4) 8(0,5) 6(1,3) 2(1,4) 3(1,5) 9(2,3) 4(2,4) 1(2,5) 1(0,6) 3(0,7) 5(0,8) 9(1,6) 4(1,7) 6(1,8) 8(2,6)
        //7(2,7) 2(2,8)

        //At this point, need to store the completed board into a Set.
        permutationAllBoards.add(currentStringJoinerFullGrid);
        
        //we can now assign the size of the set of permutationAllBoards into numComplete9x9Boards variable
        
        numComplete9x9Boards = new BigInteger(String. valueOf(permutationAllBoards.size()));
            
        System.out.println("********************************************************************************");
        System.out.println("\nThis is your board number " + (numComplete9x9Boards) + " summary: " + completedBoardsLogs[count]);
        System.out.println("********************************************************************************");
        count=count+1;

    }

public void realTime9x9Fill(String history)
       {
           int row=0;  
           int col=0;  
           int boardValue=0;  
           int startLastNumber;
       
            int rowtoInt=0;
            int coltoInt=0;
            int boardValuetoInt=0;
       
       
       System.out.println(history);
    //data in history similar to as below......
    //7(0,0) 2(0,1) 8(0,2) 5(1,0) 3(1,1) 4(1,2) 1(2,0) 9(2,1) 6(2,2) 7(0,3) 5(0,4) 8(0,5) 6(1,3) 2(1,4) 3(1,5) 9(2,3) 4(2,4) 1(2,5) 1(0,6) 3(0,7) 5(0,8) 9(1,6) 4(1,7) 6(1,8) 8(2,6) 7(2,7) 2(2,8)
   
           
           // this means there is only one value in board since no space introduced by StringJoiner yet...
          if (history.lastIndexOf(" ")==-1)
          {
               row = Character.getNumericValue(history.charAt(2));
               col = Character.getNumericValue(history.charAt(4));
               boardValue= Character.getNumericValue(history.charAt(0));
               
               
              formattedBoard [row][col]=boardValue;  
               
          }
         
           else
           {
               //if history is //7(0,0) 2(0,1) 8(0,2), lastIndex space is before 8
               
               //all values are chars...
               startLastNumber=history.lastIndexOf(" ");
               row = history.charAt((startLastNumber+3));
               col = history.charAt((startLastNumber+5));
               boardValue = history.charAt((startLastNumber+1));
               
               //converting all values to integer...
               rowtoInt = Character.getNumericValue(row);
               coltoInt = Character.getNumericValue(col);
               boardValuetoInt= Character.getNumericValue(boardValue);
               
               //storing into board....
               formattedBoard [rowtoInt][coltoInt]=boardValuetoInt;  
              
           }
           
           System.out.println("FILLING BOARD");
           display9x9();
           
           //implemented, started straight away after 1 number in 9x9
           //if overheads are too high, it can be potentially moved till after entire row is done....
           //since for each number added into 9x9, it has to check for occurences of all possibleNumbers
           checkUniqueRows(formattedBoard, rowIndex); 
           checkUniqueColumns(formattedBoard, colIndex);

        }

    public void display9x9()
    {
        System.out.println("REACH!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!------------------------------");
        for (int i=0; i<formattedBoard.length; i++)   //for each row
        {

            sj1= new StringJoiner(" ");  // StringJoiner erased before start of processing each row only

            for (int j=0; j<formattedBoard[0].length; j++)  // for each column in row above....
            {
                sj1.add(Integer.toString(formattedBoard[i][j]));  //since this prints all 81 values here

            }

            System.out.println(sj1);
        }
    }

    public boolean checkUniqueRows(int[][] nineByNine, int rowIndex)
    {
        System.out.println("**************************************************************************************");

        int occurenceNumberRow=0;  // it will be cleared each time method is called.
        //even if location of checkUniqueRows is moved after the board is populated, it will still function...
        //again all this is possible to conserve memory and let program execute more cycles...

        for (int j=0; j<possibleNumbers.length; j++)
        {
            occurenceNumberRow=0;

            for (int i=0; i<nineByNine[0].length; i++)    //checking column across row
            {

                //here rowIndex will take reference from 9 x 9 grid value... 
                //it will keep rowIndex same, but move across each column

                if (possibleNumbers[j]==nineByNine[rowIndex][i])  // this would check possibleNumbers[j] 
                //against all numbers in the grid...

                {
                    occurenceNumberRow++;    //increase count of occurrence.

                    //default for failedRows is false.. so it doesn't need to be initialised like this..
                    //if more once instance of numbr and failedRows=false... (which would be expected)
                    if (occurenceNumberRow>1 && !failedRows)
                    {
                        failedRows = true;  //there are now failedRows...

                        //This was inline advancing my code.
                        //For instance if a grid is partially filled with a 3x3 and it does not meet criteria
                        //for sudoku, then depending on the number inserted, it might need to move back to offset,
                        //rowIndex and colIndex

                        //RollBackRow()  //future coding......

                    }
                }

            }
            //The output of number(1-9) and frequency has to be here before it moves on to check next from possibleNumbers
            System.out.println("Number: " + possibleNumbers[j] + " has occured: " + occurenceNumberRow +  " times in  row " + rowIndex);

        }//end of main for loop going through all numbers.....


        return failedRows;   //returns flag value...
    }


    public boolean checkUniqueColumns(int[][] nineByNine, int colIndex)
    {
        //this will simply do a compare of the grid in current state against all possible numbers

        int occurenceNumberCol=0;


        for (int j=0; j<possibleNumbers.length; j++)
        {
            occurenceNumberCol=0;

            for (int i=0; i<nineByNine.length; i++)    //checking each row.. this is to allow it to navigate across colIndex
            {
                if (possibleNumbers[j]==nineByNine[i][colIndex])  //here rowIndex will take reference from 9 x 9 grid value..  it wil move down each row but keep col the same....
                {
                    occurenceNumberCol++;

                    if (occurenceNumberCol>1 && !failedColumns)
                    {
                        failedColumns = true;
                    }

                }

            }
            System.out.println("Number: " + possibleNumbers[j] + " has occured: " + occurenceNumberCol +  " times in column " + colIndex);
        }


        //Just need to be careful that default value of failedColumns array will be false...
        // if it set to false on initialisation,  if it finds a false column, it will remain false...
        // Only route to become true is if there are no failed columns at all.
        //Logic has been carried out..

        return failedColumns;

    }

    //duplicateNumbersRow takes values failedRows
    //duplicateNumbersCol takes values failedColumns

    //The board number has been included, since now for maximum execution cycles, all
    //System.out.println() can be turned off except for the below.....
    public boolean sudokuComplete(boolean duplicateNumbersRow, boolean duplicateNumbersCol)
    {
        //if either flags are true.....  the grid has failed....
        if (duplicateNumbersRow || duplicateNumbersCol)   //if both are true, it means that sudoku has failed...
        {
            System.out.println("**************************");
            System.out.println("Better luck next time, failed on board: " + count);

            display9x9();
            wipe9x9Board(formattedBoard,nineByNine);

            System.out.println("**************************");

            System.out.println("\n\nMoving onto Board Number: " + numComplete9x9Boards);

            failedRows=false;
            failedRows=false;

            return false;

        }
        //otherwise success
        else
        {
            System.out.println("**************************");
            System.out.println("\nCongratulations, sudoku complete on board: " + count);
            System.out.println("");
            System.out.println("**************************");
            
            System.exit(0);

            display9x9();
            wipe9x9Board(formattedBoard,nineByNine);

            System.out.println("Moving onto Board Number: " + numComplete9x9Boards);

            return true;
        }

        //two boards are wiped and ready start again....

    }

    public void get9x9Grid()
    {

    }

    //Removing all testing....
    public void get3x3Grid()
    {

        //this will get out all the 3x3 grids from the permutations.....
        int k=0;
        if (mp.containsKey(newSize))
        {
            miniGrid = mp.get(newSize);
            k++;
        }
        /*
        System.out.println("FULLY FUNCTIONAL PRINTING THE ARRAY TO STRING");
        for (int[] g :miniGrid)
        {

            System.out.println(Arrays.toString(g));
        }
        */

    }
}

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+")!");

        String Permutations3x3into9x9="108,883,584,818,776,183,656,945,007,213,012,309,135,068,193,536,000";
        String sudokuSolutions = "6,670,903,752,021,072,936,960";

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

//I attempted this to try and get the value of  P(362800, 9) to try and get value on the screen...
//But it was going to produce stack overflow or similar as expected.....
//Since we known  from  P(81,9) =  362800, this will be the new n......

//(Permutations ((Permutations (n,r,originalNumber, m),Permutations3x3into9x9)     ,r,originalNumber, m),Permutations3x3into9x9);


//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) }
    }
}