Add to challenge document. I have reached a major milestone. I have got software to generate nine 3x3 grids (generated randomnly) and fill them number by number (from left to right) row by row.. This has been extremely challenging... It has also showed how many times the number has appeared in each row and in each column. Although this is not the solution to problem... It is part of the bigger picture... It shows all relevant comments on the screen to understand exactly what is going on... It also tells end user if its a suduko valid grid... Just to make this interesting, I am going to get randomnly generated 3 x 3 grids and see how long it takes to complete a valid grid. Just this will give an indication of scale problem ahead... I believe this will be within my capacity to code quite quick.... My code is not as flexible as anticipated.. I tried to create alternate version of Place code here... /* 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 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 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 mp); public boolean checkUniqueRows(int [][] temp, int rowIndex); public boolean checkUniqueColumns(int[][] nineByNine, int colIndex); public void place3X3Into9x9(); public void 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 mp = new HashMap(); int possibleNumbers[] = new int[]{1,2,3,4,5,6,7,8,9}; //List lst = new ArrayList<>(Arrays.asList(possibleNumbers)); List lst = new ArrayList(); int MiniTest[][] = new int[3][3]; Map 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 s = new HashSet<>(); Set s = new HashSet(); StringJoiner sj; int storeMiniGrids[][][]; int item=0; int currentSize; int newSize; int[][] miniGrid; int[][][] miniGridContainer; List 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 = new boolean[9]; boolean [] failedRows = new boolean[9]; public int[][] wipe9x9Board(int [][]temp) { for (int q=0; q lst.add(str)); //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 wrong loop.. //since the loop gets smaller in size... i will process what is left!!! // //for (int i=0; i, 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() 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 // this means that once it has exceeded set number of permutations, it will end. */ Collection 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 lt = new ArrayList<>(mp.values()); Set 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 [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"); //for (int n=0; n=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; k1) { failedRows[i]= true; } } } System.out.println("Number: " + possibleNumbers[j] + " has occured: " + occurenceNumberRow + " times in row" + rowIndex); } //Just need to be careful that default value of failedRows array will be false... // if it set to false on initialisation, if it finds a false row, it will remain false... // Only route to become true is if there are no failed rows at all. for (boolean b: failedRows) { if (b) //if there is a single failed row { return false; //checkUniqueRows becomes false } else { return true; } } //return (occurenceNumberRow>1?true:false); return false; } 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; j1) { failedColumns[i]= true; } } } System.out.println("Number: " + possibleNumbers[j] + " has occured: " + occurenceNumberCol + " times in column " + colIndex); } //Just need to be careful that default value of failedColumns array will be false... // if it set to false on initialisation, if it finds a false column, it will remain false... // Only route to become true is if there are no failed columns at all. for (boolean b: failedColumns) { if(b) //if there is a single failed column { return false; //checkUniqueColumns becomes false } else //There are no failed columns { return true; } } //return (occurenceNumberCol>1?true:false); return false; } public void place3X3Into9x9() { } public void sudokuComplete(boolean duplicateNumbersRow, boolean duplicateNumbersCol) { if (duplicateNumbersRow && duplicateNumbersCol) //if both are true, it means that sudoku has failed... { System.out.println("**************************"); System.out.println("\n\nBetter luck next time"); System.out.println("**************************"); } else { System.out.println("**************************"); System.out.println("Congratulations, sudoku complete"); System.out.println("**************************"); } } public void get9x9Grid() { //All values are stored in here //At moment is has just put consecutive 3x3 grids stored in here: //nineByNine System.out.println("*****filled grid****** - Testing original MiniGridContainer - FAIL"); for (int[][]row: miniGridContainer) { for (int[] h:row) { System.out.println(Arrays.asList(h)); } } System.out.println("Trying to print first 3x3 grid in 9x9 grid"); System.out.println(miniGridContainer[0][0][0] + miniGridContainer[0][0][1] + miniGridContainer[0][0][2]); System.out.println(miniGridContainer[0][1][0] + miniGridContainer[0][1][1] + miniGridContainer[0][1][2]); System.out.println(miniGridContainer[0][2][0] + miniGridContainer[0][2][1] + miniGridContainer[0][2][2]); /* System.out.println("*****filled grid****** - Testing 9x9 board -ArrayList FAIL"); for (int i[]:nineByNine) { System.out.println(Arrays.asList(i)); } */ /* System.out.println("*****filled grid****** - Testing 9x9 board -EACH NUMBER into string joiner!!!"); Character convert; String convert1; for (int i=0; i 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=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) } } }