Java : Sudoku Game : Checking 3x3 grids for repeated values - java

What this program does :
This program takes values from a class and uses those as the starting values for a Sudoku puzzle. We are to print these out in a typical Sudoku 9x9 grid. The program then prompts the user to give a coordinate point on the grid and a value to put in there. Currently what I am working on is making sure that the values put in by the user are valid to solve this puzzle. Once the puzzle is filled out and there are no longer any repeated values in each column, row, and 3x3 square, the game should end and the output should be "Puzzle Complete".
As of right now, my program checks for repeated values in columns and rows successfully, but I have no idea where to begin for checking each 3x3 square.
The numbers for this puzzle are saved in a 9x9 array.
Basicly : Any tips for how to check for repeated values in each 3x3 part of the array?

What I'd do instead of a big 9x9 array is storing a 3x3 array of 3x3 arrays of numbers. Or do both, for ease of computation (storing 81 more bytes of data (you do use bytes for the fields I hope?) isn't going to cause memory problems in all but the most memory starved devices and I doubt you'd want to play games on such anyway).

It depends on how you are storing the sudoku board. If you are storing it as a 2D array, you could have your logic identify the 3x3 box the user has chosen to enter the new value and use the code you already have to check a row and column sections.
What you could also have would be to have a collection of 9 sets. Each set would correspond to a specific 3x3 block. So, when the user selects the coordinates of where he/she would like to add the value, you would select the given set and perform an add operation in the set.
Since sets do not allow repetition, the add method will return false if the number already exists in the set. This will also allow you to identify any duplicate values (however, unlike the array option, you would also need to update the set should the user opt to remove values from the 3x3 grid).

I wrote the following code about 4 years ago in C to solve the exact same problem, it's as brute-force-y as it looks, though. The int array was a 9x9 grid. The "index" specifies the 0...8th line, 0...8th column, and 0...8th box.
int checkBox(int a[][9], int index)
{
int i, j, isValid = 1;
int m, n;
for(i = 3*(index%3) ; isValid && (i < (3*(index%3) + 3)); i++)
{
for(j = 3*(index/3); isValid && (j < (3*(index/3) + 3)); j++)
{
for(m = (3*(index%3)) ; isValid && (m < (3*(index%3) + 3)); m++)
{
for(n = 3*(index/3); isValid && (n < (3*(index/3) + 3)); n++)
{
if(isValid && (a[m][n] == 0) || ((i != m) || (j != n)) && (a[i][j] == a[m][n])) //select given element and compare others to it
{ //if any element is the same that is not itself then the sudoku is not valid
isValid = 0; //this checks for 3x3 box
}
}
}
}
}
return isValid;
}
Basically what I did was just manipulate the index until it selected a specific box, and in that box I checked all numbers to see if there's any kind of match. If there is a match, the sudoku is invalid.
In the end, I checked the validity like this:
int checkSudoku(int a[][9]) //check every row, column and box
{ //if there is no contradiction then it is valid
int i, isValid = 1;
for(i = 0; isValid && (i < 9); i++)
{
isValid = (checkLine(a, i) && checkColumn(a, i) && checkBox(a, i));
}
return isValid;
}
Of course, the same concept can be applied to Java, considering it's just array management.

Related

Java * Two-Dimensional Array * Plotting Points on Array [duplicate]

This question already has an answer here:
Java - Two-Dimensional Arrays - Plotting Points
(1 answer)
Closed 6 years ago.
I have an assignment for a JAVA class I am taking. We are discussing two-dimensional arrays, however on this particular assignment, I can not figure out how to return back specific points and set those points with a specific value. Here is the assignment:
Write a method called create2DArray that will fill, create, and return a 10 x 10 2d array with random numbers in the range of 1 to 100. Write a method called print2DArray that will print a 10 x 10 2D array in row column fashion. Write a method called createCoords that will search the 2D array looking for any value that is evenly divisible by 3. Once you have found a number you should log the row, column location. This means when your method finishes it should produce a list of coordinates that I can use to plot my graph. This method must also return the number of coordinates that are divisible by 3 so that I know how many points there are to plot. I am not particular as to how the coordinates are returned back as long as I get a list of the row, column locations. So, I will leave it to you to work out a mechanism for returning the values. To test that you have logged the coordinates create another function called fillLocations that will fill the locations in the array you have logged with -1. So, your program should flow in this order 1.create2DArray 2.print2DArray 3.createCoords 4.fillLocations 5.print2DArray
I understand and have completed create2DArray and print2DArray, but I can not figure out createCoords and fillLocations. Here is what I have so far, but it does not work and there are errors present:
public int createCoords(int row1, int col1){
int[][] coords = new int[row1][col1];
int[][] count = new int[0][0];
int co = 0;
for(int row = 0; row < 10; row++)
{
for(int col = 0; col < 10; col++)
{
if(coords[row][col] % 3 == 0)
co++;
return count[row][col];
}
}
return co;}
public int fillLocations(int[][] count){
int x = 0;
int y = 0;
for(int row = 0; row < 10; row++)
{
for(int col = 0; col < 10; col++)
{
if(count[row][col] % 3 == 0)
x = row;
y = col;
break;
}
}
return (x, y);}
I'm not going to write the code, but pretty much how I would go about doing this is:
I would have a separate 2d boolean array the same size as the 2d int array, auto filled with false. This would go in createCoords.
use nested for loop to cycle through all addresses of the 2d int array, and when i find a number that's divisible by three, i mark the corresponding point on the boolean array as 'true'. This would also go in createCoords.
after the for loops finish, I then look at the original 2d int array and boolean array. i would use the nested for loops again, and when i find a true value on the boolean array, i would mark the corresponding location on the int array as -1. This would go in fillLocations. You should also pass the 2d boolean array to fillLocation along with the 2d int array.
Good luck!
EDIT: this is assuming that the FillLocation function REPLACES values in the 10x10 int array with -1. That's what I interpreted your question to be. Please correct me if i'm wrong. I also added a short description at the end of each paragraph where each segment of code would go.
There are couple of problems with your code. Firstly, for the fillLocations method, you are expected to return the NUMBER of cells ([row][column]) where the value is divisible by 3. This means that for each value that passes the test:
if(coords[row][col] %3 === 0)
Then you should increment the counter by 1.
So for this part, your code would look like:
int [][] your2DArray = new int[10][10];
...
private int getNumberOfValuesDivisibleByThree(){
int numberOfValuesDivisibleByThree = 0;
for (int row=0; row < your2DArray.length; row++){
for(int col = 0; col < your2DArray[0].length; col++){
if(your2DArray[row][col] % 3 === 0){
//value at this coordinate or in this cell is divisible by 3
//here you can 'log' the coordinates as required -
System.out.println(row+","+col);
//increment the count
numberOfValuesDivisibleByThree +=1;
}
}
}
//return the final count
return numberOfValuesDivisibleByThree;
}
Please see how to create and manipulate a 2D array in Java. Syntax for creating a two-dimensional array

4 queens algorithm - can't understand code

public boolean canPlaceQueen(int r, int c) {
/**
* Returns TRUE if a queen can be placed in row r and column c.
* Otherwise it returns FALSE. x[] is a global array whose first (r-1)
* values have been set.
*/
// System.out.println("r======"+r);
// System.out.println("c="+c);
for (int i = 0; i < r; i++) {
System.out.println("iiiiiiiiiii="+i);
if (x[i] == c || (i - r) == (x[i] - c) ||(i - r) == (c - x[i]))
{
System.out.println("try c="+c);
System.out.println("try="+r);
return false;
}
}
return true;
}
public void placeNqueens(int r, int n) {
/**
* Using backtracking this method prints all possible placements of n
* queens on an n x n chessboard so that they are non-attacking.
*/
//System.out.println("r="+r);
for (int c = 0; c < n; c++) {
//System.out.println("c=="+c);
if (canPlaceQueen(r, c)) {
x[r] = c;
// System.out.println("2nd==="+r);
if (r == n - 1) {
printQueens(x);
} else {
placeNqueens(r + 1, n);
}
}
}
}
My question is: If c = 0, then c = 1, but then c=0. I cant understand that logic, why not c=2,please describe it or describe how c increment in this program
Okay, I'll take a crack at this. You enter the method placeNqueens with r=0 and n=whatever (let's say 5). We loop through each column and check if we can fit a queen in that column for row . If we CAN place it, we set the x[0] = c (which will probably be 0 for the first attempt) and then recursively call into placeNqueens with r=1 and n=5. At this point we're checking the next row.
Inside this call, we now start again and check all the columns. We won't be able to place it in the first column, because that's where the first queen is, so we loop until we find a column we can place it. Inside this loop, you might check column 0 and fail, and then check column 1 and fail, and then check column 2 and find a spot, so you set x[1] = 2 and then call placeNqueens(6, 5).
Eventually you've placed enough queens that your row == queens -1, so then you print the solution. If you don't ever find a solution, then the call stack ends and falls back to the previous call, which keeps looping until it finds ANOTHER possible place to put the queen in that row. When it does, it then calls placeNqueens to try the next row again. If a solution is present, eventually the algorithm will try all the permutations needed to find it.
So, to summarize, in each execution of placeNqueens, you loop only as long as you need to loop until you find a spot to place your queen, and then you call placeNqueens again, reducing your current row position by 1. If you reach a point where you cannot place any queens, your program will finish the entire for-loop and then return, which takes you to wherever you left off in the loop on the previous call.

Confused about writing a program for placing some modified queen-type pieces on an 8 x 8 board

To this question:
The superqueen is a chess piece that can move like a queen, but also like a knight. What is the maximal number of superqueens on an 8X8 chessboard such that no one can capture an other?
I want to write a brute force algorithm to find the maximum. Here's what I wrote:
public class Main {
public static boolean chess[][];
public static void main(String[] args) throws java.lang.Exception {
chess = new boolean[8][8];
chess[0][0] = true;
for (int i = 0; i < 8; i++) {
for (int j = 0; j < 8; j++) {
/*Loop to check various possibilities*/
if (!checkrow(i) && !checkcolumn(j) && !checkdiagonals(i, j) && !checkknight(i, j)) {
if (i != 0 || j != 0) {
chess[i][j] = true;
}
}
}
}/*printing the array*/
for (int i = 0; i < 8; i++) {
for (int j = 0; j < 8; j++) {
System.out.print(((chess[i][j]) ? "T" : "x") + "|");
}
System.out.println();
}
}
/*All working fine here*/
public static boolean checkrow(int a) {
for (int i = 0; i < 8; i++) {
if (chess[a][i]) {
return true;
}
}
return false;
}
/*All working fine here*/
public static boolean checkcolumn(int a) {
for (int i = 0; i < 8; i++) {
if (chess[i][a]) {
return true;
}
}
return false;
}
/*All working fine here*/
public static boolean checkdiagonals(int pi, int pj) {
int i = pi - Math.min(pi, pj);
int j = pj - Math.min(pi, pj);
for (int k = i, l = j; k < 8 && l < 8; k++, l++) {
if (chess[k][l]) {
return true;
}
}
int i_2 = pi - Math.min(pi, pj);
int j_2 = pj + Math.min(pi, pj);
for (int k = i_2, l = j_2; k < 8 && l > 1; k++, l--) {
if (chess[k][l]) {
return true;
}
}
return false;
}
/*Not All working fine here try commenting out this method above so that that it doesn't run during the check*/
public static boolean checkknight(int pi, int pj) {
for (int i = -1; i <= 1; i++) {
for (int j = -1; j <= 1; j++) {
if (0 <= pi + 2 * i && pi + 2 * i <= 8 && 0 <= pj + j && pj + j <= 8) {
if (chess[pi + 2 * i][pj + j]) {
return true;
}
}
if (0 <= pi + i && pi + i <= 8 && 0 <= pj + 2 * j && pj + 2 * j <= 8) {
if (chess[pi + i][pj + 2 * i]) {
return true;
}
}
}
}
return false;
}
}
I have two questions:
My algorithm for checkknight looks for all knight positions, is it wrong? or there is some coding error.Everything is working fine when I comment out it and I get a nice solution.
Secondly it'll result only in one solution.For other solutions I have to offset(or change position) of other pieces bit by bit after each mega-loop of this, I am confused about implementing it. My instincts guide me that I need to change whole of the code. Is there a modification or a way to do it?
Additional Thoughts: I think we would add to a counter each time we place a piece and add to a long array and output the maximum and array after storing the relevant data.
Code Location: You may view/edit/fork/download it at http://ideone.com/gChD8a
This a rough brute-force method starting from the opposite direction, i.e. from the solved eight-queens puzzle. This will allow us to find a bunch of viable solutions.
The brute-force technique for going from a single superqueen to potentially 8 seems to be especially complex due to the knight's traversal. Based on the runs, about 60% of the viable paths for normal queens are invalid with superqueens. So if we were to instead brute force normal queens, and then work backwards, that is potential time saved for finding a solution, and we can better determine the run-time. Because we know normal queens is easier.
We start off with the 12 fundamental solutions, we would then use these as inputs. Solving normal queens is outside this, but the wiki page has a fantastic article describing everything.
In my case, I stored them as Strings representing the coordinate of the queen (the rows are indices).
So: "17468253" = A1, B7, C4, D6, E8, F2, G5, H3
By brute-forcing the opposite direction from solved queens, we only have to test at most 12 x 8! possible solutions. Because order doesn't matter, additional optimization could occur by eliminating duplicate boards and solutions for processing.
First up, checkKnight, which appears to be your source of confusion. Using absolute values, you can reasonably determine whether or not a piece is within knight's range by checking whether the X offset is 2 and Y offset is 1, or vice versa. You've made a complex checkKnight function to check each individual location and whether or not a piece is on the border. Working the other way by hitscanning each queen to each other queen is logically simpler and less of a nightmare to debug.
Queen class
public class Queen {
int i, j;
public Queen(int i, int j) {
this.i = i;
this.j = j;
}
public boolean checkKnight(Queen queen) { // if any queen meets another
// queen at 2 and 1 offset, we
// eliminate it.
return (Math.abs(i - queen.i) == 2 && Math.abs(j - queen.j) == 1)
|| (Math.abs(i - queen.i) == 1 && Math.abs(j - queen.j) == 2);
}
}
This board has been modified since I originally posted. It takes a String input and converts it to a full chessboard. It has some minor work towards the potential any-size board, but right now it handles child board creation. When a child board is created, the queens are passed by reference rather than making a whole new set of queens. A total of 96 queens are stored in memory, 1 for each one on the original 12-board solution. Not perfectly optimized, but better than 96 -> 672 -> 4032 -> ...
Board class
public class Board {
static int boardSize = 8;
ArrayList<Queen> queens = new ArrayList<Queen>();
public Board(String s) {
for (int i = 0; i < s.length(); i++) {
queens.add(new Queen(i, s.charAt(i) - 49)); // you could implement
// base 16 here, for
// example, for a 15x15
// board
}
}
public Board(Board b) { // duplicates the board, but keeps references to
// queens to conserve memory, only 96 total queens
// in existence through search!
for (Queen q : b.queens) {
queens.add(q);
}
}
public boolean checkForImpact() {
for (int i = 0; i < queens.size(); i++) {
for (int j = i + 1; j < queens.size(); j++) {
if (queens.get(i).checkKnight(queens.get(j))) { // just check
// for any
// queens
// intersecting,
// one hit is
// enough
return true;
}
}
}
return false;
}
public ArrayList<Board> getChildBoards() { // create child boards with a
// single queen removed
ArrayList<Board> boards = new ArrayList<Board>();
for (int i = 0; i < queens.size(); i++) {
boards.add(new Board(this));
}
int i = 0;
for (Board b : boards) {
b.queens.remove(i);
i++;
}
return boards;
}
public String drawBoard() {
String s = "";
char[][] printableBoard = new char[boardSize][boardSize];
for (int i = 0; i < 8; i++) {
for (int j = 0; j < 8; j++) {
printableBoard[i][j] = '_';
}
}
for (Queen q : queens) {
printableBoard[q.i][q.j] = 'Q';
}
s += " A B C D E F G H\n";
for (int i = 0; i < 8; i++) {
s += (8 - i) + "|";
for (int j = 0; j < boardSize; j++) {
s += printableBoard[i][j];
s += "|";
}
s += "\n";
}
return s;
}
}
Test class
import java.util.ArrayList;
public class Test {
static String[] boards = { "24683175", "17468253", "17582463", "41582736",
"51842736", "31758246", "51468273", "71386425", "51863724",
"57142863", "63184275", "53172864" }; // all 12 solutions for the 8
// queens problem
static ArrayList<Board> boardObjects = new ArrayList<Board>();
public static void main(String[] args) {
for (String queens : boards) { // create starter boards
boardObjects.add(new Board(queens));
}
int i;
ArrayList<Board> foundBoards = null;
for (i = 8; i > 0; i--) {
ArrayList<Board> newBoards = new ArrayList<Board>();
foundBoards = new ArrayList<Board>();
for (Board b : boardObjects) {
if (b.checkForImpact()) { // if any queen intercepts we get
// children
ArrayList<Board> boardsToBeAdded = b.getChildBoards(); // pass
// all
// permutations
// of
// queens
// once
// removed
for (Board bo : boardsToBeAdded) {
newBoards.add(bo); // add it in to the next list
}
} else {
foundBoards.add(b); // if we have no impact, we have a
// solution
}
}
if (!foundBoards.isEmpty())
break;
boardObjects.clear();
boardObjects = newBoards;
}
System.out.println("The maximum number of super-queens is: " + i);
ArrayList<String> winningCombinations = new ArrayList<String>();
for (Board board : foundBoards) {
String createdBoard = board.drawBoard();
boolean found = false;
for (String storedBoard : winningCombinations) {
if (storedBoard.equals(createdBoard))
found = true;
}
if (!found)
winningCombinations.add(createdBoard);
}
for (String board : winningCombinations) {
System.out.println(board);
}
}
}
The end output is:
The maximum number of super-queens is: 6
A B C D E F G H
8|Q|_|_|_|_|_|_|_|
7|_|_|_|_|_|_|Q|_|
6|_|_|_|Q|_|_|_|_|
5|_|_|_|_|_|_|_|_|
4|_|_|_|_|_|_|_|Q|
3|_|Q|_|_|_|_|_|_|
2|_|_|_|_|Q|_|_|_|
1|_|_|_|_|_|_|_|_|
A B C D E F G H
8|Q|_|_|_|_|_|_|_|
7|_|_|_|_|_|_|_|_|
6|_|_|_|_|Q|_|_|_|
5|_|_|_|_|_|_|_|Q|
4|_|Q|_|_|_|_|_|_|
3|_|_|_|_|_|_|_|_|
2|_|_|_|_|_|Q|_|_|
1|_|_|Q|_|_|_|_|_|
A B C D E F G H
8|_|_|_|_|Q|_|_|_|
7|Q|_|_|_|_|_|_|_|
6|_|_|_|_|_|_|_|Q|
5|_|_|_|Q|_|_|_|_|
4|_|_|_|_|_|_|_|_|
3|_|_|_|_|_|_|_|_|
2|_|_|Q|_|_|_|_|_|
1|_|_|_|_|_|Q|_|_|
A B C D E F G H
8|_|_|_|_|Q|_|_|_|
7|Q|_|_|_|_|_|_|_|
6|_|_|_|_|_|_|_|Q|
5|_|_|_|Q|_|_|_|_|
4|_|_|_|_|_|_|_|_|
3|_|_|_|_|_|_|Q|_|
2|_|_|Q|_|_|_|_|_|
1|_|_|_|_|_|_|_|_|
A B C D E F G H
8|_|_|_|_|Q|_|_|_|
7|Q|_|_|_|_|_|_|_|
6|_|_|_|_|_|_|_|Q|
5|_|_|_|_|_|_|_|_|
4|_|_|Q|_|_|_|_|_|
3|_|_|_|_|_|_|Q|_|
2|_|_|_|_|_|_|_|_|
1|_|_|_|Q|_|_|_|_|
I've removed the duplicates and made a nice board printing method. don't remember the exact math, but this highlights 40 possible locations. There are others, just by looking, but we've found a fair chunk of them already! From here, we can gently shift individual queens around. From a cursory look, each board has a single piece that can be moved to 3 additional spaces, so now we know there are probably about 160 solutions.
Conclusions
With this application, the run-time on my machine was less than a second, meaning that if we attached this to a standard queens application, the additional knight's brute-forcing would have no impact on that process and have almost the same run-time. In addition, because only 6-piece puzzles are possible, we know that your eventual application run will finish its finding at the 6th piece being placed, as no more solutions are possible, since there are no viable 7-piece and 8-piece solutions.
In other words, finding the maximum super-queen layout is likely actually shorter than the maximum queen layout due to the additional restrictions!
Trying to brute-force such a question is a good way to get a feel for it. So I won't suggest looking up pre-cooked solutions at first.
One little remark though: I don't see the reason for the condition if (i != 0 || j != 0) { that you have there. You are working on Java arrays. Instead of 1 through 8, they go 0 through 7, but the 0 is the first column, you should not eliminate it, otherwise it's only a 7x7 board.
First, let me address your technical question: how to calculate the knight positions.
Take a sheet of quad paper, put a queen somewhere not less than two squares away from the edge. Then mark the end positions of a knight-move from it.
You'll end up with just 8 squares that need to be considered. There is no point in doing a 3x3 loop to find them. A better idea would be to prepare a static array with the relative coordinates of the knight moves - an array of 8 pairs of numbers - and loop on that. So you have only an 8-step loop. In each step of the loop, check for bounds (0 ≤ X + Xoffset < 8, 0 ≤ Y + Yoffset < 8 ), and you have the knight coordinates.
Second, there is no point checking the part of the board that's ahead of you. Since you have not covered the next row and those below it, there is no point in looking for queens there. The implications of this:
You'll never put another queen in the same row where you have just marked a queen position (because you threaten it horizontally). This means that if you mark a queen, you should use continue to break out of the inner loop to the next row.
You don't need checkrow(). When you start a row, there is no queen ahead of you. And if you followed the above bullet point, there is no queen on your back, either.
When you use checkcolumn, you start at row 0, but you can finish at the row before the one you are on (i-1). There are still no queens in the rows below you! The same is true for the diagonal checks.
Earlier I said that you need to prepare and check 8 knight positions. But now you know there is no queen at the knight positions ahead of you. So you only need to prepare an array with four knight positions - the ones above your position.
But most importantly... once you have finished and you have your queens in positions and print the board: you have a single solved board. You have proved that this number of queens is possible. But is it the highest number possible? You have not checked what happens if you don't put a queen on the first square of the first row, but on the second. Perhaps this will allow you to put in an extra queen later. And what about the queen in the second row? Maybe if you moved that, you would be able to put a queen somewhere below where you couldn't before?
So, now you have to actually do the same thing over again, changing one decision every time and working from there. In effect, you have many potential boards. Why? Because there may be more than one valid position on each row where you put that row's queen. So you have decided to put it in the first valid position. But what if you decide to put it in the second valid position? Or leave that row empty? Each such decision is followed by another set of decisions on the next row.
The different boards created by different decisions form a decision tree. The problem for you to consider, therefore, is how to work such a tree out. How to write your decision trail and then backtrack, change, fill another board and count the queens at each level. People here suggested recursion, because it lends itself nicely to such problems. Or you can keep a stack of decisions if you want. You can eliminate some of the potential boards based on symmetries.
I suggest you first make sure you understand your single board well, and then consider how to represent your decision tree and how to traverse it.
There are several questions here.
The first is: how many knight-queens can be placed on an nxn chessboard? Since a k-piece solution can trivially be reduced to a k-1 piece solution, it makes sense to start from the upper bound. That is, look for an n-piece solution, if that fails look for an n-1 piece solution, and so forth.
The second question is: how should I look for a k-piece solution? There are two classic strategies: depth-first and breadth-first. In the former, you consider one vertex of the search tree at a time and use backtracking on failure. In the latter, you consider one complete level of the search tree at a time.
Something that can make a great deal of difference to your search is to account for symmetry (in this case, rotations and reflections).
The third (implicit) question is: what is a good representation here? If your chess-boards are less than 8x8 in size then a 64-bit bit-pattern will do very nicely!
In practical terms, try to separate the three levels of your problem as far as you can. If you don't, you'll find that a choice in one level will severely limit your options at another level.

Stack overflow on recursive method when the counter begins at 1 [closed]

Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 8 years ago.
Improve this question
I've written a program to read in a text file containing a matrix of 1s and 0s that will loop recursively to identify all unique four-connected regions (regions connected by moving up, down, left, right). I then replace the 1s in each region with an identifier number, however when I begin the counter for the replacement values at 1 I get a stack overflow error. I've worked around this while building my recursive method by just starting at 2 and then going back after everything is finished and decrementing all the region values by 1 so that the region counters start at 1 in the output. This works and my output is correct, but this feels like a lazy solution.
I know I need a way to identify if a 1 has already been identified, this would allow me to replace an area with 1s and still be able to properly read through the grid, but I am unsure of any way to see if an element is a member of an object. I've attempted to build a series of if-else statements to identify the very first 1 encountered and to loop from there, but when I hit that region again I either get a stack overflow error or bizarre outputs such as every number in the first region (which should be replaced by new 1s) being a different number. Would it be smarter to write a second recursive method to handle the very first 1 encountered, or does the fact I start at 2 and then later decrement all values really make the program so ugly?
/**
* Scans the grid for 1s, calling the designateRegions method when unique
* 1s are found.
*/
public static void findRegions() {
int region = 2;//the counter variable in question
for (int i = 0; i < nRows; i++) {
for (int j = 0; j < nCols; j++) {
if (grid[i][j] == 1) {
//Ensure the value isn't part of a known region
if (j-1 >= 0 && grid[i][j-1] >= 1) {
grid[i][j] = grid[i][j-1];
} else if (i-1 >= 0 && grid[i-1][j] >= 1) {
grid[i][j] = grid[i-1][j];
} else {//if 1 is unique
Regions regionObject = new Regions(region);//instantiate a Regions object
regionCountList.add(regionObject);//add new Regions object to arraylist
designateRegions(grid, i, j, region, regionObject);//call recursive method designateRegions
region++;
}//end nested if-else block
}//end outer if statement
}//end inner for loop
}//end outer for loop
//this is stupid
for (int i = 0; i < nRows; i++) {
for (int j = 0; j < nCols; j++) {
if (grid[i][j] > 1) {
grid[i][j] = grid[i][j] - 1;//drop the value of each region by 1
}//end if statement
}//end inner for loop
}//end outer for loop
}//end findRegions method
/**
* Loops recursively to identify four-connected regions of 1s and change the
* value of the elements in the newly identified region.
* #param grid the 2d integer array containing the grid to be scanned
* #param r the row position
* #param c the column position
* #param region the identifier value for the region
* #param regionObject the object associated with each region
*/
private static void designateRegions(Integer[][] grid, int r, int c, int region, Regions regionObject) {
if (grid[r][c] == 0) { //base case
} else if (grid[r][c] == 1) {
grid[r][c] = region;//switch value of the 1 with appropriate region identifier
regionObject.regionCount++;
if (r - 1 >= 0) {
designateRegions(grid, r - 1, c, region, regionObject);//move up
}
if ((r + 1) < nRows) {
designateRegions(grid, r + 1, c, region, regionObject);//move down
}
if ((c + 1) < nCols) {
designateRegions(grid, r, c + 1, region, regionObject);//move right
}
if (c - 1 >= 0) {
designateRegions(grid, r, c - 1, region, regionObject);//move left
}
}
}//end findRegions method
You correctly identified the problem: the recursive code needs to mark each grid element that has been visited to prevent the program from chasing its own tail.
Marking the visited cells with a different value (2) is a valid strategy. Another possibility would be passing around a separate grid of boolean[nRows][nCols]s with cells that have a true in them identify the visited cells.
I think that your solution is cleaner, because it does not require allocating any additional memory.

Counting the number of times an element occurs in a given column for a 2D array?

This is a method for a Sudoku game.
Could someone explain their thought processes for this? :( I'm having a lot of difficulty figuring this out. I know for the first method, we're supposed to use a for loop or something.
I know my iteration for my method is wrong...Sorry :(
private int countOccurrencesInCol(int col, int d){
for (int i = 0; i < grid.length; i++;){
for(int j = col; j = col; j++;){
if (grid[i][j] == d){
count++;
}
}
}
return count;
}
This method returns the number of times a digit occurs in a given column in a 9 X 9 matrix.
private int countPossiblePlacementsInCol (int col, int d){
This method is supposed to determine the number of spots in a given column where a given digit can be placed, and returns the number of spots where a digit can be placed in a spot for a given column. If the digit already occurs, then the method returns 0.
Here is some code with explainations to help you understand the approach required:
private int countOccurrencesInCol(int col, int d) {
// counter variable to count the number of occurrences
int counter = 0;
// matrix is the 2D array, the first index is the row, second is the column
// loop through each index of the given column, checking for the digit, d
for(int row = 0; row < matrix.length; row++) {
// if a match is found...
if(matrix[row][col] == d) {
// increment the counter by one
counter++;
}
}
// return the final count
return counter;
}
The next method is a bit trickier, because I am not clear on what is required. Is this method supposed to just return the number of empty cells in the given column? Or should it take into account all the rules of sudoku and check if those empty cells are valid moves for that digit? If it is the former, then the solution is simple:
private int countPossiblePlacementsInCol(int col, int d) {
// I am assuming an empty cell is indicated by 0. In that case,
// we can reuse the previous method to find the number of occurrences of d,
// and the occurences of 0
// first, find out if the digit already occurs in the row, return 0
// if it does:
if(countOccurrencesInCol(col, d) > 0) {
return 0;
}
// next, return the number of times 0 occurs (the number of empty cells):
return countOccurrencesInCol(col, 0);
}
However, if you must count only VALID moves, this gets a lot trickier. The last line in the previous method would turn into something more like this:
private int countPossiblePlacementsInCol(int col, int d) {
//start the same as the previous method:
if(countOccurrencesInCol(col, d) > 0) {
return 0;
}
int counter = 0;
// this time, for each cell in the column, you must check that it is a valid move:
for(int row = 0; row < matrix.length; row++) {
if(countOccurrencesInRow(row, d) == 0 &&
countOccurencesInSquare(row, col, d) == 0) {
counter++
}
}
}
The two methods I used this time, countOccurrencesInRow and countOccurencesInSquare are going to do something similar to countOccurrencesInCol. The Row one is basically the same as the Col one, but it checks a row instead of a column. The Square one is a bit trickier. Assuming you know the rules of sudoku, you should know that a square is a 3x3 section of the 9x9 game board (in which there are 9 3x3 sections). The Square method will use the row and col to figure out which square the given cell is in, and then loop through the rows and columns of just that square, counting occurrences of the given digit. For this, you will need to use two for loops, one nested inside the other. If you have trouble understanding how to properly use for loops, and loop through arrays, then I suggest you talk to your teacher/professor for additional help on the topic.
I hope these explanations and examples help. Good luck.
You do not need a second for loop.
Count of occurrence of number in a column can be found by
private int countOccurrencesInCol(int col, int d){
for (int i = 0; i < grid.length; i++){
if (grid[i][col] == d){
count++;
}
}
return count;
}
Hope this helps!
Good luck!

Categories