/*
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
{
    BigInteger prevNumComplete9x9Boards=new BigInteger("0");
    boolean hasEntire9x9Filled=false;
    boolean hasPerformedOnce=false;
    int minimum=362800;
    int maximum=0;

    StringJoiner permutationsSelected;
    int randomNumber;
    StringJoiner summary;
    StringJoiner summary1;
    int numAttempts;

    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])

                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()<10);    // this is getting  <(NUMBER)  x   (3x3 boards)
        //}while (s.size()<2000);    // this is getting  <(NUMBER)  x   (3x3 boards)

        if (!hasPerformedOnce) {
            s.clear();

            //We know this is a valid board configuration...
            //So I am going to extract these out into mini 3x3 grids inline with how my code processes information
        /*
        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,5,6,4,8,9,7
        6,4,5,9,7,8,3,1,2
        9,7,8,3,1,2,6,4,5
        3,1,2,6,4,5,9,7,8
        5,6,4,8,9,7,2,3,1
        8,9,7,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");
            hasPerformedOnce=true;

            //System.out.println("JUST ONCE");
        }
        /*
        //We know this translates as:
        1(0,0) 2(0,1) 3(0,2) 4(1,0) 5(1,1) 6(1,2) 7(2,0) 8(2,1) 9(2,2)
        4(0,3) 5(0,4) 6(0,5) 7(1,3) 8(1,4) 9(1,5) 1(2,3) 2(2,4) 3(2,5)
        7(0,6) 8(0,7) 9(0,8) 1(1,6) 2(1,7) 3(1,8) 4(2,6) 5(2,7) 6(2,8)

        2(3,0) 3(3,1) 1(3,2) 6(4,0) 4(4,1) 5(4,2) 9(5,0) 7(5,1) 8(5,2)
        5(3,3) 6(3,4) 4(3,5) 9(4,3) 7(4,4) 8(4,5) 3(5,3) 1(5,4) 2(5,5)
        8(3,6) 9(3,7) 7(3,8) 3(4,6) 1(4,7) 2(4,8) 6(5,6) 4(5,7) 5(5,8)

        3(6,0) 1(6,1) 2(6,2) 5(7,0) 6(7,1) 4(7,2) 8(8,0) 9(8,1) 7(8,2)

        6(6,3) 4(6,4) 5(6,5) 8(7,3) 9(7,4) 7(7,5) 2(8,3) 3(8,4) 1(8,5)
        9(6,6) 7(6,7) 8(6,8) 2(7,6) 3(7,7) 1(7,8) 5(8,6) 6(8,7) 4(8,8)


        //This would be search String to search for in the screen output
        1(0,0) 2(0,1) 3(0,2) 4(1,0) 5(1,1) 6(1,2) 7(2,0) 8(2,1) 9(2,2) 4(0,3) 5(0,4) 6(0,5) 7(1,3) 8(1,4) 9(1,5) 1(2,3) 2(2,4) 3(2,5) 7(0,6) 8(0,7) 9(0,8) 1(1,6) 2(1,7) 3(1,8) 4(2,6) 5(2,7) 6(2,8) 2(3,0) 3(3,1) 1(3,2) 6(4,0) 4(4,1) 5(4,2) 9(5,0) 7(5,1) 8(5,2) 5(3,3) 6(3,4) 4(3,5) 9(4,3) 7(4,4) 8(4,5) 3(5,3) 1(5,4) 2(5,5) 8(3,6) 9(3,7) 7(3,8) 3(4,6) 1(4,7) 2(4,8) 6(5,6) 4(5,7) 5(5,8) 3(6,0) 1(6,1) 2(6,2) 5(7,0) 6(7,1) 4(7,2) 8(8,0) 9(8,1) 7(8,2) 6(6,3) 4(6,4) 5(6,5) 8(7,3) 9(7,4) 7(7,5) 2(8,3) 3(8,4) 1(8,5) 9(6,6) 7(6,7) 8(6,8) 2(7,6) 3(7,7) 1(7,8) 5(8,6) 6(8,7) 4(8,8)
        */

        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("\n123Current sudoku board: " + numComplete9x9Boards + "  out of " + Permutations3x3into9x9 + "  Attempts: " + numAttempts);

        /*

// 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()]);
            //System.out.println(perm3x3[0] + " ---------------confirming if the same, expect it to be since Set fully populated
            //System.out.println("START NEW BOARD, RESET ALREADY PROCESSED");

            String[] perm3x3Selection = new String[perm3x3.length];

            //I will now create a backup of this. This will be restored once it has performed the board
            //Need to remember that need to create copy data and not share same memory address
            //String[][] perm3x3Backup = s.toArray(new String[s.size()][1]);


            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

            int uniqueEntries=0;
            int[] storeRetrieved3x3Grid=new int[9];



            do
            {
                //We have a random Number
                //it is a number from 0-362800
                randomNumber = rand.nextInt(perm3x3.length);
                if (randomNumber<minimum)
                {
                    minimum=randomNumber;
                }

                if (randomNumber>maximum)
                {
                    maximum=randomNumber;
                }

                if ((perm3x3Selection[randomNumber])=="ALREADY SELECTED")
                {

                    //System.out.println("*********************************GRID ALREADY SELECTED" + "("+randomNumber+") " +"GENERATING ANOTHER");
                    randomNumber = rand.nextInt(perm3x3.length);
                    if (randomNumber<minimum)
                    {
                        minimum=randomNumber;
                    }

                    if (randomNumber>maximum)
                    {
                        maximum=randomNumber;
                    }
                }
                else
                {
                    //System.out.println("*********************************NEW ENTRY: " + randomNumber);
                    storeRetrieved3x3Grid[uniqueEntries]=randomNumber;
                    //System.out.println("This is random Number: " + randomNumber);
                    //System.out.println("This has been chosen: " + perm3x3[storeRetrieved3x3Grid[uniqueEntries]] + " unique: " + uniqueEntries);
                    uniqueEntries++;



                    perm3x3Selection[randomNumber]="ALREADY SELECTED";
                }

            }while (uniqueEntries<9);

            //System.out.println("FINISHED GETTING ALL THE MINI 3x3 GRIDS");
            //for (int)
            permutationsSelected = new StringJoiner(",");

            for (int z: storeRetrieved3x3Grid)
            {
                //System.out.println(z);


                entry3x3=z;
                permutationsSelected.add(String.valueOf(entry3x3));

                //WE NEED TO USE A
                //System.out.println("VALUE OF ENTRY3:" + entry3x3);
                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);

                /*
                System.out.println("String converted: " + temp[0][0]);
                System.out.println("String converted: " + temp[0][1]);
                System.out.println("String converted: " + temp[0][2]);
                System.out.println("String converted: " + temp[1][0]);
                System.out.println("String converted: " + temp[1][1]);
                System.out.println("String converted: " + temp[1][2]);
                System.out.println("String converted: " + temp[2][0]);
                System.out.println("String converted: " + temp[2][1]);
                System.out.println("String converted: " + temp[2][2]);
                */

                //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)
                {
                    //System.out.println("AT TOP IF: " + totalNumbersProcessed);
                    //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...

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


                            //It appears that it is completing a single String from


                            realTime9x9Fill(sj.toString());    //method call, this also checks for uniquerows and uniquecols...
                            //System.out.println("\nPERFORMED REAL TIME: " + sj.toString());

                            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)
                            {
                               // System.out.println("IT HAS FILLED ENTIRE 9x9 BOARD");
                                hasEntire9x9Filled = true;
                                //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..

                                numAttempts++;
                                //System.out.println("\n*********************Current sudoku board: " + numComplete9x9Boards + "  out of " + Permutations3x3into9x9 + "  Attempts: " + numAttempts);


                                //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();
                            }
                            //System.out.println("NUMS PROCESSED: " + totalNumbersProcessed);

                            totalNumbersProcessed++;

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

                    }   //end for loop for each row

                    //System.out.println("*************************************");
                    //System.out.println("CONFIRM: " + totalNumbersProcessed);
                }  //end if (totalnumberprocessed<=81)
            }

            //System.out.println("GOES HERE");

            //System.out.println("RESETTING storeRetrieved3x3Grid, uniquentries and ALL:  " + perm3x3.length + " permutations (3x3 grids) AVAILABLE for selection");
            //we can now re-initialise
            storeRetrieved3x3Grid = new int[9];
            uniqueEntries=0;

            //also restore array
            perm3x3 = s.toArray(new String[s.size()]);


            //System.out.println("OUT LOOP: " + totalNumbersProcessed);



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

            //System.out.println("Number complete boards: " + numComplete9x9Boards);
            //System.out.println("Number possible boards: " + 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;
        //System.out.println("STORING: " + 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.
        prevNumComplete9x9Boards=new BigInteger(String.valueOf(permutationAllBoards.size()));
        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("Previous permutations achieved: " + prevNumComplete9x9Boards + "Current permutations: " + numComplete9x9Boards);
     if((numComplete9x9Boards).compareTo(prevNumComplete9x9Boards)==1)
     {
         System.out.println("This is your board number " + (numComplete9x9Boards) + " summary: " + currentStringJoinerFullGrid + "\tPermutations selected: (" + permutationsSelected+")" + "minimum: "+ minimum + " maximum:" + maximum);
     }


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

            }
            // this will ensure board is only filled once it has completed	
	    //if (totalNumbersProcessed==81)
            //{
            	System.out.println(sj1);
            //}

        }
    }

    public boolean checkUniqueRows(int[][] nineByNine, int rowIndex)
    {
        summary1 = new StringJoiner("| ");
        //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);
            summary1.add("N:" + String.valueOf(possibleNumbers[j]) + "  O:" + String.valueOf(occurenceNumberRow) + "  Row:" + String.valueOf(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
        summary = new StringJoiner("| ");
        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);
            summary.add("N:" + String.valueOf(possibleNumbers[j]) + "  O:" + String.valueOf(occurenceNumberCol) + "  Col:" + String.valueOf(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 + "\tPermutations selected: (" + permutationsSelected+")" + "minimum: "+ minimum + " maximum:" + maximum);
            //System.out.println("N=Number, O=Occurrences Col = Column   "  + summary);
            //System.out.println("N=Number, O=Occurrences Row = Row   "  + summary1);

            display9x9();
            wipe9x9Board(formattedBoard,nineByNine);

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

            //System.out.println("\n\nMoving onto Board Number: " + numComplete9x9Boards);
            permutationsSelected=new StringJoiner(",");

            failedRows=false;
            failedRows=false;

            return false;

        }
        //otherwise success
        else
        {
            //System.out.println("**************************");
            System.out.println("\nCongratulations, sudoku complete on board: " + count + " Permutations selected: (" + permutationsSelected+")");
            System.out.println("Complete solution:" + sj.toString());
            //System.out.println("N=Number, O=Occurrences Col = Column   "  + summary);
            //System.out.println("N=Number, O=Occurrences Row = Row   "  + summary1);
            System.out.println("**************************");
            permutationsSelected=new StringJoiner(",");
            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) }
    }
}