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

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

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

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

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

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

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

// 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.*;
import java.util.*;
import java.util.stream.*;

interface Fillable
{
    public void fill3x3Manual();
    public void fill3x3();
    public void fill9x9(Map<Integer, int[][]> mp);
    public boolean checkUniqueRows(int [][] temp, int rowIndex);
    public boolean checkUniqueColumns(int[][] nineByNine, int colIndex);
    public void place3X3Into9x9();
    public boolean sudokuComplete(boolean a, boolean b);
    public void get9x9Grid();
    public void get3x3Grid();
    public int[][] wipe9x9Board(int[][] temp);
    public void print9x9Board(String history, int numComplete9x9Boards);
    public int convertStringTo3x3(String permutations3x3, int getNumString);
    public void realTime9x9Fill(String history, int e);
    int formattedBoard[][] = new int [9][9];   // this will hold formattedBoard.... ok here
    
   
    
   
}

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


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


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

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

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

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

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

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

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

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


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

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


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

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

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

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

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

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

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

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


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

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

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

}


numbersProcessed3x3=0;
nineByNineBoardNumber=1;

            System.out.println("MUST HERE FUCKING");
            //for (int n=0; n<temp.length;n++ )  // this will go through each row of the 3 x 3  (0-2)(0-2)
            for (int n=0; n<temp.length;n++ )  // this will go through each row of the 3 x 3  (0-2)(0-2)
           
           
            {
               
               
                System.out.println("value of n: " + n);
                System.out.println("Value colcount993: "  + colCount);
               
                if (colCount>=2 && rowCount!=2)  // if it reaches last number of row mini grid in first row
                {
                    System.out.println("Current colcount 3x3: " + colCount);
                    System.out.println("Current rowcount 3x3: " + rowCount);
                   
                    rowCount++;   // it starts new row of mini grid...
                    colCount=0;   // it starts again at column 0 mini grid
                   
                   
                    //ut would also have to start new row on big grid..
                    // for second row of 3x3
                   
                    rowIndex++;
                   
                    //it would only start colIndex if  offset is also equal to 0
                    //this would be the case for 1st 3x3 grid.... in each row.....
                    if (offset==0)
                    {
                        colIndex=0;
                    }
                    else
                    {
                        colIndex=offset;
                    }
                 
                    //IT HAS REACHED THE LAST COLUMN BIG GRID..  COLINDEX8..
                    //IN THIS CASE, IT HAS TO reset back to start new row
                    //IT SHOULD HIT THIS POINT WHEN numbersprocessed has hit 9...
                   
                   
                        //it has to also start again on big grid
                        //but this time it moves down 3 places from [0,0] no to overwrite any data....
                       
                     
                    if (colIndex==8 && numbersProcessed3x3==9)
                    {
                        colIndex=0;
                        rowIndex=rowIndex+3;
                        ReachEndColMiniGrid=true;  //sets flag
                       
                    }
                   
                    //if it hasn't reached the last column on 9x9
                    //and it has processed entire 3 x 3 mini grid...
                    //The next grid is adjacent....
                    // There is no bearing on
                   
                   
                    if (colIndex!=8 && numbersProcessed3x3==9)
                    {
                        System.out.println("**********************BACK HERE!");
                        colIndex=colIndex+1;
                        rowIndex=0;
                       
                    }
                   
                   
                }
                    //it is uniform array, so can use temp[0]
                for (int k=0; k<temp[0].length;k++)  // this will then go through each column in row....
                {
                   
                    numbersProcessed3x3++;
                   
                   
                    //this has to keep track of the offset in the colIndex (9 by 9 grid)
                    //otherwise when it starts the next row, it will take the colIn
                    if (k==0)
                    {
                        offset=colIndex;
                       
                    }
                    //since zero index, i has been increased..
                    System.out.println("\nSelecting grid " + (i+1) +" 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("numbersProcessed: " + numbersProcessed3x3);
                    System.out.println("Total numbers processed: " + totalNumbersProcessed);
                   
                    System.out.println("The current coordinate:" + rowCount);
                    System.out.println("The current coordinate:" + colCount);
                   
                    //colindex is wrong for the second list item....
                    //in first row, its fine since it is set to +1 pos from last grid.
                    //when the row has increased, the column has gone to 0, need to change this logic...
                   
                    System.out.println("Following number: " + temp[rowCount][colCount]);
                   
                    System.out.println("being stored at index: " + rowIndex + " " + colIndex);
                   
                    sj.add(temp[rowCount][colCount] + "("+rowIndex+","+colIndex+")");
                   
                    System.out.println("currently processing this from 3 x 3:" + "(" + rowCount + "," +colCount+")");
                   
                    //System.out.println(nineByNineBoardNumber);
                   
                    //nineByNine[rowIndex][colIndex]=miniGridContainer[i][rowCount][colCount];
                    //nineByNine[rowIndex][colIndex]=miniGridContainer[i][rowCount][colCount];
                   
                    nineByNine[rowIndex][colIndex]=temp[rowCount][colCount];
                   
                    //this can potentially be done after the first 3x3 grid is filled in each row..
                    //since one expects the row to be unique at this point...
                    //but no harm anyhow doing it now...
                    //unfortunately due to nature of code, it has to check after a single number is added on the board...
                    //massive overhead...
                   
                   /*
                    ensure copy of the existing set.......
                    select 1st 3x3 grid..
                    Populate it into 9x9 grid.....
                    remove it from the Set with permutations....
                   */
                   
                   
                    //checkUniqueRows(nineByNine, rowIndex); //  (implemented, started straight away after 1 number in 9x9)
                    //checkUniqueColumns(nineByNine, colIndex);
                   
                    realTime9x9Fill(sj.toString(), tokenCount);
                   
                   
                   
                    //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 numbersProcessed3x3 =9)
                    remove this 3x3 from the  set....
                   
                    When numComplete9x9Boards increases, restore copied set back as original.
                    The board that was in column offset 0  [0,0] of 9x9 has to stay there
                    until it has exhausted all permutations of 3x3 grids around it...
                   
                   */
                   
                    //System.out.println(nineByNine[nineByNineBoardNumber][rowIndex][colIndex] + " at " +  "("+rowIndex+","+colIndex+")");
                   
                   
                    //System.out.println("Final ready column: " + colIndex);
                   
                   
                    colCount++;  //moves forwad position on 3 x 3
                   
                    colIndex++;  //moves forward position on the main 9 x 9
                   
                    if (numbersProcessed3x3==9)   //if it has done all avlues in 3x3
                    {
                        colCount=0;   //starts again in 3x3
                        rowCount=0; //starts again in 3x3
                       
                       
                    }
                   
                    if (totalNumbersProcessed!=0 && totalNumbersProcessed%9==0)
                        {
                            //this is indication that it has finished a 3 x 3 grid....
                            //it has to be done before the incrementing of totalNumbersProcessed
                            i++;
                           
                        }
                       
                        //indication that it has filled 9 x 9
                         if (totalNumbersProcessed%81==0)
                        {
                           
                            //nineByNineBoardNumber++;
                           
                            // THIS IS MY PROBLEM NOW!!!!
                            // WHERE SHOULD I STORED THE COMPLETED BOARDS.....
                            //DECIDING IN A MAP FOR NOW!!!!
                           
                            completedBoards.put(numComplete9x9Boards,nineByNine);
                            print9x9Board(sj.toString(), numComplete9x9Boards);
                           
                           
                            numComplete9x9Boards++;
                            
                           
                            totalNumbersProcessed=0;  // starting again......
                            i=0;
                           
                           
                            sj = new StringJoiner(" ");
                           
                            temp= wipe9x9Board(temp);
                            
                                if (sudokuComplete(failedRows, failedColumns))
                                {
                                    System.out.println("EXIT!!!!!!!!!!!!");
                                    
                                    // need to force this loop to max out:
                                //}while((numComplete9x9Boards*9)<=s.size());
                                
                                //best way is to set numComplete9x9Boards to something high...
                                System.exit(0);
                                
                                //  int exceedBoardCount =  s.size()/9;
                                // numComplete9x9Boards=exceedBoardCount+1;
                                }
                                
                                System.out.println("\nonto Board Number: " + numComplete9x9Boards);
                           
                            //nbn[nineByNineBoardNumber] = new nineByNine();
                           
                        }
                  
                    totalNumbersProcessed++;
                   
                   
                }  //end for loop  to go through  columns in each row
               
                        }   //end for loop for each row
                       
                System.out.println("%$£%$£%$£%%%%%%%%%%%%%%%%%%%%%%%%%%%%");
                System.out.println("%$£%$£%$£%%%%%%%%%%%%%%%%%%%%%%%%%%%%");
                System.out.println("%$£%$£%$£%%%%%%%%%%%%%%%%%%%%%%%%%%%%");
                System.out.println("%$£%$£%$£%%%%%%%%%%%%%%%%%%%%%%%%%%%%");
               
            }
       
       
   
        //this will get more thought later on...
        //but it should allow termination also if there are 3x3 grids insufficient to fill full board...
       
        GridCount3x3++;
           
        }while((numComplete9x9Boards*9)<=s.size()); //end for loop iterate throug map
       
            // i is incrementing each time it has finished a 3x3 grid....
            //but it also gets reset to 0.. so pointless in here...
   
    //historyBoards("*** END HISTORY***");
           
    }
   
    public void print9x9Board(String history, int numComplete9x9Boards)
    {
       
        //this number will grow quite a lot....
       
       String currentCompleted9x9Board=completedBoardsLogs[count];
       
        completedBoardsLogs[count]=history;
        int processed=0;
        System.out.println("\nThis is your board " + (numComplete9x9Boards) + " summary: " + completedBoardsLogs[count]);
        count=count+1;
       
       }
       
       //for some reason, after 5 fills in grid it erases data, after 6 fills it erases....
       // the unique row and column check is fine....  
       //history is based on sj.toString()
       //and since sj gets reset, it loses its value...
       
       public void realTime9x9Fill(String history, int tokenCount)
       {
           
       int row=0;  //this can be overwritten
       int col=0;  //this can be overwritten
       int boardValue=0;  //this ok here....
       int startLastNumber;
       
       int rowtoInt=0;
       int coltoInt=0;
       int boardValuetoInt=0;
       
       System.out.println(history);
       
       //coding is messy because there is no delimiter in first entry since StringJoiner does not take effect
   
    //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....
          if (history.lastIndexOf(" ")==-1)
          {
              System.out.println("FIRST");
               row = Character.getNumericValue(history.charAt(2));   //all ok
               System.out.println(row);
               //System.out.println("fuck" + row);
               col = Character.getNumericValue(history.charAt(4));   // all ok
               System.out.println(col);
               //.out.println("fuck" + col);
               boardValue= Character.getNumericValue(history.charAt(0));  //all ok
               System.out.println(boardValue);
               
              formattedBoard [row][col]=boardValue;  
               
          }
         
           else
           {
               System.out.println("SECOND");
               startLastNumber=history.lastIndexOf(" ");
               row = history.charAt((startLastNumber+3));
               col = history.charAt((startLastNumber+5));
               boardValue = history.charAt((startLastNumber+1));
               
               rowtoInt = Character.getNumericValue(row);
               System.out.println(rowtoInt);
               coltoInt = Character.getNumericValue(col);
               System.out.println(coltoInt);
               boardValuetoInt= Character.getNumericValue(boardValue);
               System.out.println(boardValuetoInt);
               
               formattedBoard [rowtoInt][coltoInt]=boardValuetoInt;
               
           }
           
           System.out.println("FILLING BOARD");
           for (int i=0; i<formattedBoard.length; i++)   //for each row
           {
               //the stringjoiner can be erased here?
               sj1= new StringJoiner(" ");  // for each row, the stringjoiner has to be erased....
               
               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
                   
                   
               }
               
               //since only once change made when realTime9x9Fill is called, this can be processed here...
               //it will be called for each row....
               
               System.out.println(sj1);
               //now the row string can be erased....
               
           }
           
           checkUniqueRows(formattedBoard, rowIndex); //  (implemented, started straight away after 1 number in 9x9)
           checkUniqueColumns(formattedBoard, colIndex); //implemented, started straight away after 1 number in 9x9)
           
               //This is chosen so that end user gets report of the numbers going into grid and then status if valid..
              
           tokenCount++;  // this will determine how many tokens in string....
           
           if (totalNumbersProcessed==81)    // can look for better logic here later...
           {
              tokenCount=0;
              // no need to wipe board, done separately.....
              
           }
           
           }
       
   
    public boolean checkUniqueRows(int[][] nineByNine, int rowIndex)
    {
        //this will simply do a compare of the grid in current state against all possible numbers
       
        int occurenceNumberRow=0;
        System.out.println("££££££££££££££££££££££££££££££££££££££££££3");
       
        for (int j=0; j<possibleNumbers.length; j++)    
        {
            occurenceNumberRow=0;
           
            for (int i=0; i<nineByNine[0].length; i++)    //checking column across row
            {
                if (possibleNumbers[j]==nineByNine[rowIndex][i])  //here rowIndex will take reference from 9 x 9 grid value... it will keep row same, but move across each column
                {
                    occurenceNumberRow++;
                    
                    if (occurenceNumberRow>1 && !failedRows)
                    {
                    failedRows = true;
                    }
                }
               
            }
            System.out.println("Number: " + possibleNumbers[j] + " has occured: " + occurenceNumberRow +  " times in  row" + rowIndex);
           
        }
        //return (occurenceNumberRow>1?true:false);
        return failedRows;
    }
   
    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;
        System.out.println("££££££££££££££££££££££££££££££££££££££££££3");
       
        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 colIndex the same....
                {
                    occurenceNumberCol++;
                    
                    if (occurenceNumberCol>1 && !failedColumns)
                    {
                    failedColumns = true;
                    }
                    
                }
               
            }
            System.out.println("Number: " + possibleNumbers[j] + " has occured: " + occurenceNumberCol +  " times in column " + colIndex);
        }
        
        return failedColumns;
       
    }
   
    public void place3X3Into9x9()
    {
       
    }
    
    public boolean sudokuComplete(boolean duplicateNumbersRow, boolean duplicateNumbersCol)
    {
        //either failedRow or failedCol  is true....
        
        if (duplicateNumbersRow || duplicateNumbersCol)
        
        {
                        System.out.println("**************************");
                        System.out.println("\n\nBetter luck next time");
                        System.out.println("**************************");
                        return false;
               
                    }
                    else
                    {
                        System.out.println("**************************");
                        System.out.println("Congratulations, sudoku complete");
                        System.out.println("**************************");
                        return true;
                    }
                    
                
       
    }
    
    
   
    public void get9x9Grid()
    {
        //All values are stored in here
        //At moment is has just put consecutive 3x3 grids stored in here:
        //nineByNine
       
    }
   
    //for some fucking reason, the set is not getting bigger..
   
    public void get3x3Grid()
    {
        miniGridContainer = new int[mp.size()][3][3];
        int m=0;
       
       
        //System.out.println("***********");
       
        //this will get out all the 3x3 grids from the permutations.....
        int i=0;
        if (mp.containsKey(newSize))
        {
            miniGrid = mp.get(newSize);    //minigrid is of type int[][]
           
            //it might be worth putting all this in a 3D array...
            //so the first index can act as unique identifier:
           
            i++;
           
            //mp.getKey()
           
            //at this point in might be worth calling fall 9x9 grid
            //now it has reached this...  P (362880,9)
            //n will the unique key...
           
        }
       
        //System.out.println("This should be same in map:");
        //this will print out all the rows.....
       
        System.out.println("FULLY FUNCTIONAL PRINTING THE ARRAY TO STRING");
        for (int[] g :miniGrid)
        {
            //System.out.println("!!!!!This is the key: " + mp.getKey(newSize));
            System.out.println(Arrays.toString(g));
        }
       
        int p=0;
        int k=0;
        int pos=0;
       
        //System.out.println("This should be same in map:");
        //this will print out all the rows.....
       
        System.out.println("------------This is now adding each integer manually in 3d array FAILING:");    
        for (int[] g :miniGrid)   //each row
        {
            k=0;
           
            //now need to get each int...
       
            for (int j:g)
            {
                //filling 3d array...
               
               
                miniGridContainer[m][p][k]=j;
               
                if (k==2)
                {
                    k=0;
                   
                }
                else
                {
                k++;
                }
               
            }
            p++;
       
        }
       
        pos++;
       
        System.out.println("-----adding each integer manually in 3d array full loop:");
       
        MiniTest = new int[3][3];
       
        for (i=0;i<miniGrid.length;i++)
        {
            for (int j=0; j<miniGrid[0].length;j++)
            {
                MiniTest[i][j]=miniGrid[i][j];
           
        }
        }
    
     m++;      
    }
}
   
public class Permutation
{
public static void main(String[] args) {
System.out.println("Welcome to Online IDE!! Happy Coding :)");
int originalNumber=9;
int n=originalNumber;
int r =9;
Map <Integer, Long> m = new HashMap<>();
System.out.println("***PERMUTATIONS***");
System.out.println("P(n,r) = n! / (n−r)!");
System.out.println("P(" + n+","+r+") = " + n+"!" + " / " + "("+n+"-"+r+")!");

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


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