I am supposed to count how many # signs are connected to the original predetermined spot in a 2D array matrix. I am getting a stack overflow error and do not know why. Any suggestions are appreciated (Take a provided row and col location and count how many # signs connect to the original location. # signs are connected if they are connected up, down, left, and right of one another.)
Current Code:
import static java.lang.System.*;
public class AtCounter
{
private String[][] atMat;
private int totalCount = 0;
private boolean[][] visited; //used to see if location has been visited before.
public AtCounter(int rows, int cols)
{
//size the matrix
atMat = new String[rows][cols];
//use nested loops to randomly load the matrix
for(int r = 0; r < atMat.length; r++)
{
for(int c = 0; c < atMat[r].length; c++)
{
int num = (int) (Math.random() * 2);
if(num == 0)
atMat[r][c] = "#";
else
atMat[r][c] = "-";
}
}
//you will need to use Math.random()
visited = new boolean[atMat.length][atMat.length];
}
/**
* Used to find out if location is in the 2D Matrix.
*/
public boolean inBounds(int r, int c)
{
return ((r > -1 && r < atMat.length) && (c > -1 && c < atMat.length));
}
public int countAts(int r, int c)
{
//add in recursive code to count up the # of #s connected
//start checking at spot [r,c]
if(atMat[r][c].equals("-") || !inBounds(r,c))
return 0;
if(!visited[r][c])
{
if(atMat[r][c].equals("#"))
{
totalCount+=1;
if(inBounds(r - 1, c))//up
countAts(r - 1, c);
if(inBounds(r + 1, c))//down
countAts(r + 1, c);
if(inBounds(r, c + 1))//right
countAts(r , c + 1);
if(inBounds(r, c - 1))//left
countAts(r, c - 1);
}
}
return totalCount;
}
/*
*this method will return all values in the matrix
*this method should return a view of the matrix
*that looks like a matrix
*/
public String toString()
{
String grid = "";
for(String[] row : atMat)
{
for(String val : row)
{
grid += val + " ";
}
grid += "\n";
}
return grid;
}
}
You have several errors in your code:
You are created the visited arrays using atMat.length which will create an square array even if your original dimensions (rows and cols) aren't equal.
In the inBounds method you the column argument c against the length of the rows, not the length of the columns
In the countAts method:
The checking order of the invalid conditions needs to be reversed, you need to check first if it is valid position and later if the value in that cell is an #.
If the current cell hasn't been visited then the first thing is to marked as visited within the if block, to avoid falling in an endless recursion.
With all that said, a possible solution could be as follows:
import static java.lang.System.*;
public class AtCounter
{
private String[][] atMat;
private int totalCount = 0;
private boolean[][] visited; //used to see if location has been visited before.
private int rows; // To store rows length
private int cols; // To store cols length
public AtCounter(int rows, int cols)
{
//size of the matrix
this.rows = rows;
this.cols = cols;
atMat = new String[rows][cols];
//use nested loops to randomly load the matrix
for(int r = 0; r < rows; r++)
for(int c = 0; c < cols; c++) {
int num = (int) (Math.random() * 2);
if(num == 0)
atMat[r][c] = "#";
else
atMat[r][c] = "-";
}
visited = new boolean[rows][cols];
}
/**
* Used to find out if location is in the 2D Matrix.
*/
public boolean inBounds(int r, int c)
{
return r > -1 && r < rows && c > -1 && c < cols;
}
public int countAts(int r, int c)
{
//add in recursive code to count up the # of #s connected
//start checking at spot [r,c]
if(!inBounds(r,c) || atMat[r][c].equals("-")) // The order here matters
return 0;
if(!visited[r][c])
{
visited[r][c] = true; // Marks the current cell as visited
if(atMat[r][c].equals("#"))
{
totalCount+=1;
if(inBounds(r - 1, c))//up
countAts(r - 1, c);
if(inBounds(r + 1, c))//down
countAts(r + 1, c);
if(inBounds(r, c + 1))//right
countAts(r , c + 1);
if(inBounds(r, c - 1))//left
countAts(r, c - 1);
}
}
return totalCount;
}
}
Related
import java.util.*;
public class PascalFinal
{
public static void main()
{
Scanner f = new Scanner(System.in);
System.out.print("How many rows of Pascal's triangle do you want to print: ");
int row = f.nextInt();
Pascal(row);
showPascal(Pascal(row));
}
public static void showPascal(int[][] Pascal)
{
for(int a = 0; a < Pascal.length; a++)
{
for(int b = 0; b < Pascal[a].length; b++)
{
System.out.print(Pascal[a][b] + " ");
}
System.out.println();
}
}
public static int[][] Pascal(int x)
{
int[][] Pascal = new int[x][];
int rowLength = 1;
for(int a = 0; a < x; a++)
{
Pascal[a] = new int[rowLength];
rowLength++;
}
for(int a = 0; a < Pascal.length; a++)
{
for(int b = 0; b < Pascal[a].length; b++)
{
int Piscal = a-b;
Pascal[a][b] = Factorial(a)/Factorial(b)/Factorial(Piscal);
}
}
return Pascal;
}
public static int Factorial(int n)
{
if (n < 0)
{
int x = -1;
return x;
}
if (n == 0)
{
int x = 1;
return x;
}
else
{
return (n * Factorial(n - 1));
}
}
When I run that code, it works perfectly fine for the first 13 lines, however it then starts putting in weird values for the rest of the rows. My first though was that it could be due to the values getting too big from the factorial method and the int datatype not being able to hold it but I am not sure. No clue why this is getting messed up. Please help.
Edit: I tried using the long datatype instead of int, but the same issue occurs once I get past 20 rows.
If the Pascal's triangle that you have to draw is the one designed here
you do not need to evaluate any factorial.
Each row can be evaluated using the previous row with simple sums...
You can do it using an array. As a suggestion, start with the arrary: [0, 1, 0]
and remember that the next row can be evaluated doing a sum of the adjacent numbers of the previous row.
You need to loop over [0, 1, 0] and create [0,1,1,0] and then [0,1,2,1,0]
As you can see, the first is 0 and remains always 0, the next is the sum of the first two, and so on...
I'm a beginner, and I'm trying to write a working travelling salesman problem using dynamic programming approach.
This is the code for my compute function:
public static int compute(int[] unvisitedSet, int dest) {
if (unvisitedSet.length == 1)
return distMtx[dest][unvisitedSet[0]];
int[] newSet = new int[unvisitedSet.length-1];
int distMin = Integer.MAX_VALUE;
for (int i = 0; i < unvisitedSet.length; i++) {
for (int j = 0; j < newSet.length; j++) {
if (j < i) newSet[j] = unvisitedSet[j];
else newSet[j] = unvisitedSet[j+1];
}
int distCur;
if (distMtx[dest][unvisitedSet[i]] != -1) {
distCur = compute(newSet, unvisitedSet[i]) + distMtx[unvisitedSet[i]][dest];
if (distMin > distCur)
distMin = distCur;
}
else {
System.out.println("No path between " + dest + " and " + unvisitedSet[i]);
}
}
return distMin;
}
The code is not giving me the correct answers, and I'm trying to figure out where the error is occurring. I think my error occurs when I add:
distCur = compute(newSet, unvisitedSet[i]) + distMtx[unvisitedSet[i]][dest];
So I've been messing around with that part, moving the addition to the very end right before I return distMin and so on... But I couldn't figure it out.
Although I'm sure it can be inferred from the code, I will state the following facts to clarify.
distMtx stores all the intercity distances, and distances are symmetric, meaning if distance from city A to city B is 3, then the distance from city B to city A is also 3. Also, if two cities don't have any direct paths, the distance value is -1.
Any help would be very much appreciated!
Thanks!
Edit:
The main function reads the intercity distances from a text file. Because I'm assuming the number of cities will always be less than 100, global int variable distMtx is [100][100].
Once the matrix is filled with the necessary information, an array of all the cities are created. The names of the cities are basically numbers. So if I have 4 cities, set[4] = {0, 1, 2, 3}.
In the main function, after distMtx and set is created, first call to compute() is called:
int optRoute = compute(set, 0);
System.out.println(optRoute);
Sample input:
-1 3 2 7
3 -1 10 1
2 10 -1 4
7 1 4 -1
Expected output:
10
Here's a working iterative solution to the TSP with dynamic programming. What would make your life easier is to store the current state as a bitmask instead of in an array. This has the advantage that the state representation is compact and can be cached easily.
I made a video detailing the solution to this problem on Youtube, please enjoy! Code was taken from my github repo
/**
* An implementation of the traveling salesman problem in Java using dynamic
* programming to improve the time complexity from O(n!) to O(n^2 * 2^n).
*
* Time Complexity: O(n^2 * 2^n)
* Space Complexity: O(n * 2^n)
*
**/
import java.util.List;
import java.util.ArrayList;
import java.util.Collections;
public class TspDynamicProgrammingIterative {
private final int N, start;
private final double[][] distance;
private List<Integer> tour = new ArrayList<>();
private double minTourCost = Double.POSITIVE_INFINITY;
private boolean ranSolver = false;
public TspDynamicProgrammingIterative(double[][] distance) {
this(0, distance);
}
public TspDynamicProgrammingIterative(int start, double[][] distance) {
N = distance.length;
if (N <= 2) throw new IllegalStateException("N <= 2 not yet supported.");
if (N != distance[0].length) throw new IllegalStateException("Matrix must be square (n x n)");
if (start < 0 || start >= N) throw new IllegalArgumentException("Invalid start node.");
this.start = start;
this.distance = distance;
}
// Returns the optimal tour for the traveling salesman problem.
public List<Integer> getTour() {
if (!ranSolver) solve();
return tour;
}
// Returns the minimal tour cost.
public double getTourCost() {
if (!ranSolver) solve();
return minTourCost;
}
// Solves the traveling salesman problem and caches solution.
public void solve() {
if (ranSolver) return;
final int END_STATE = (1 << N) - 1;
Double[][] memo = new Double[N][1 << N];
// Add all outgoing edges from the starting node to memo table.
for (int end = 0; end < N; end++) {
if (end == start) continue;
memo[end][(1 << start) | (1 << end)] = distance[start][end];
}
for (int r = 3; r <= N; r++) {
for (int subset : combinations(r, N)) {
if (notIn(start, subset)) continue;
for (int next = 0; next < N; next++) {
if (next == start || notIn(next, subset)) continue;
int subsetWithoutNext = subset ^ (1 << next);
double minDist = Double.POSITIVE_INFINITY;
for (int end = 0; end < N; end++) {
if (end == start || end == next || notIn(end, subset)) continue;
double newDistance = memo[end][subsetWithoutNext] + distance[end][next];
if (newDistance < minDist) {
minDist = newDistance;
}
}
memo[next][subset] = minDist;
}
}
}
// Connect tour back to starting node and minimize cost.
for (int i = 0; i < N; i++) {
if (i == start) continue;
double tourCost = memo[i][END_STATE] + distance[i][start];
if (tourCost < minTourCost) {
minTourCost = tourCost;
}
}
int lastIndex = start;
int state = END_STATE;
tour.add(start);
// Reconstruct TSP path from memo table.
for (int i = 1; i < N; i++) {
int index = -1;
for (int j = 0; j < N; j++) {
if (j == start || notIn(j, state)) continue;
if (index == -1) index = j;
double prevDist = memo[index][state] + distance[index][lastIndex];
double newDist = memo[j][state] + distance[j][lastIndex];
if (newDist < prevDist) {
index = j;
}
}
tour.add(index);
state = state ^ (1 << index);
lastIndex = index;
}
tour.add(start);
Collections.reverse(tour);
ranSolver = true;
}
private static boolean notIn(int elem, int subset) {
return ((1 << elem) & subset) == 0;
}
// This method generates all bit sets of size n where r bits
// are set to one. The result is returned as a list of integer masks.
public static List<Integer> combinations(int r, int n) {
List<Integer> subsets = new ArrayList<>();
combinations(0, 0, r, n, subsets);
return subsets;
}
// To find all the combinations of size r we need to recurse until we have
// selected r elements (aka r = 0), otherwise if r != 0 then we still need to select
// an element which is found after the position of our last selected element
private static void combinations(int set, int at, int r, int n, List<Integer> subsets) {
// Return early if there are more elements left to select than what is available.
int elementsLeftToPick = n - at;
if (elementsLeftToPick < r) return;
// We selected 'r' elements so we found a valid subset!
if (r == 0) {
subsets.add(set);
} else {
for (int i = at; i < n; i++) {
// Try including this element
set |= 1 << i;
combinations(set, i + 1, r - 1, n, subsets);
// Backtrack and try the instance where we did not include this element
set &= ~(1 << i);
}
}
}
public static void main(String[] args) {
// Create adjacency matrix
int n = 6;
double[][] distanceMatrix = new double[n][n];
for (double[] row : distanceMatrix) java.util.Arrays.fill(row, 10000);
distanceMatrix[5][0] = 10;
distanceMatrix[1][5] = 12;
distanceMatrix[4][1] = 2;
distanceMatrix[2][4] = 4;
distanceMatrix[3][2] = 6;
distanceMatrix[0][3] = 8;
int startNode = 0;
TspDynamicProgrammingIterative solver = new TspDynamicProgrammingIterative(startNode, distanceMatrix);
// Prints: [0, 3, 2, 4, 1, 5, 0]
System.out.println("Tour: " + solver.getTour());
// Print: 42.0
System.out.println("Tour cost: " + solver.getTourCost());
}
}
I know this is pretty old question but it might help somebody in the future.
Here is very well written paper on TSP with dynamic programming approach
https://github.com/evandrix/SPOJ/blob/master/DP_Main112/Solving-Traveling-Salesman-Problem-by-Dynamic-Programming-Approach-in-Java.pdf
I think you have to make some changes in your program.
Here there is an implementation
http://www.sanfoundry.com/java-program-implement-traveling-salesman-problem-using-nearest-neighbour-algorithm/
I have to write a program that will read a picture and then print out the number of blocks inside it.
I have to read the picture as a binary matrix of the size r × c (number of rows times number of
columns).
The blocks are groups of one or more adjacent elements with the value 1.
Blocks are built exclusively of elements with value 1
Each element with value 1 is a part of some block
Adjacent elements with value 1 belong to the same block.
We only take into account the horizontal and vertical adjacency but not diagonal.
INPUT:
In the first line of the input we have the integers r and c, separated with one space.
Then we have the r lines, where each contains s 0's and 1's.
The numbers inside the individual lines are NOT separated by spaces.
The OUTPUT only print the number of blocks in the picture.
For example:
EXAMPLE 1
INPUT:
7 5
01000
00010
00000
10000
01000
00001
00100
OUTPUT:
6
EXAMPLE 2:
INPUT:
25 20
00010000000000000000
00010000000000000000
00010000000000000100
00000000000000000100
00011111111000000100
00000000000000000100
00000000000000000100
00000000000000000100
00000000000000000100
01111111111000000100
00000000000000000100
00000000000000100100
00000000000000100100
00000000000000100100
01000000000000100000
01000000000000100000
01000000000000100000
01000000000000100000
00000000000000100000
00000000000000000000
00000000000000000000
00000000000000000000
00000000000000000000
00011111111111100000
00000000000000000000
OUTPUT:
7
THE PROBLEM:
The problem that I have is that my program only works for inputs such as in example 1.
So pictures that only consist of blocks of size 1. But it doesnt work if there are multiples 1's in a picture, such as EXAMPLE 2.
In example 2 where the output should be 7(Blocks are elements of 1.They can either be vertial or horizontal).... my programs output is 30.
I don't know how to adjust the program in a correct manner so it will give me the correct input.
Thank you for your help in advance, here is my code that I am posting bellow.
import java.util.Scanner;
class Blocks{
public static void main(String[] args){
Scanner sc=new Scanner(System.in);
int rowNum=sc.nextInt();
int columnNum=sc.nextInt();
char[][] matrix = new char[rowNum][columnNum];
int nbrOfBlocks = 0;
for (int a = 0; a < rowNum; a++) {
matrix[a] = sc.next().toCharArray();
int index = 0;
while (index < matrix[a].length) {
if (matrix[a][index] == '1') {
++nbrOfBlocks;
while (index < matrix[a].length && matrix[a][index] == '1') {
++index;
}
}
++index;
}
}
System.out.println(nbrOfBlocks);
}
}
EDIT: Ok, here is a solution that will work for complex shapes
public class BlockCounter {
public static void main(String[] args) {
Board board = null;
try {
board = new Board("in3.txt");
} catch (Exception e) {
e.printStackTrace();
System.exit(0);
}
System.out.println("Block count: " + board.getBlockCount());
}
}
class Board {
ArrayList<String> data = new ArrayList<>();
boolean[][] used;
int colCount = 0;
public Board(String filename) throws FileNotFoundException, IOException {
try (BufferedReader br = new BufferedReader(new FileReader(filename))) {
String line;
while ((line = br.readLine()) != null) {
data.add(line);
colCount = Math.max(colCount, line.length());
}
}
}
public int getBlockCount() {
used = new boolean[data.size()][colCount];
int count = 0;
for (int row = 0; row < data.size(); row++)
for (int col = 0; col < colCount; col++)
used[row][col] = peek(row, col) == '1';
for (int row = 0; row < data.size(); row++)
for (int col = 0; col < colCount; col++)
if (used[row][col]) {
fill(row, col);
count++;
}
used = null;
return count;
}
public char peek(int row, int col) {
if (row < 0 || row >= data.size() || col < 0)
return '0';
String rowData = data.get(row);
if (col >= rowData.length())
return '0';
return rowData.charAt(col);
}
public void fill(int row, int col) {
if (used[row][col]) {
used[row][col] = false;
if (row > 0 && used[row - 1][col])
fill(row - 1, col);
if (col > 0 && used[row][col - 1])
fill(row, col - 1);
if (col < colCount - 1 && used[row][col + 1])
fill(row, col + 1);
if (row < data.size() - 1 && used[row + 1][col])
fill(row + 1, col);
}
}
public int getRowCount() {
return data.size();
}
public int getColCount() {
return colCount;
}
}
Explanation:
When Board.getBlockCount() is called if creates a temporary array of booleans to work with so the original board is not messed up. Then it searches the entire board for "trues" (which correspond to '1's on the board). Every time a "true" is found, a flood fill algorithm clears the entire shape to which it is connected.
If you need more performance and less memory usage (specially stack) for larger boards, you can use another flood fill algorithm like in the example that follows. The big advantage here is that it doesn't use the stack for every pixel like the one above. It is considerably more complex though.
public class BlockCounter2 {
public static void main(String[] args) {
Board2 board = null;
try {
board = new Board2("in4.txt");
} catch (Exception e) {
e.printStackTrace();
System.exit(0);
}
System.out.println("Block count: " + board.getBlockCount());
}
}
class Board2 {
ArrayList<String> data = new ArrayList<>();
boolean[][] used;
Deque<Point> pointStack = new LinkedList<>();
int colCount = 0;
public Board2(String filename) throws FileNotFoundException, IOException {
try (BufferedReader br = new BufferedReader(new FileReader(filename))) {
String line;
while ((line = br.readLine()) != null) {
data.add(line);
colCount = Math.max(colCount, line.length());
}
}
}
public int getBlockCount() {
used = new boolean[data.size()][colCount];
int count = 0;
for (int row = 0; row < data.size(); row++)
for (int col = 0; col < colCount; col++)
used[row][col] = peek(row, col) == '1';
for (int row = 0; row < data.size(); row++)
for (int col = 0; col < colCount; col++)
if (used[row][col]) {
fill(row, col);
count++;
}
used = null;
return count;
}
public char peek(int row, int col) {
if (row < 0 || row >= data.size() || col < 0)
return '0';
String rowData = data.get(row);
if (col >= rowData.length())
return '0';
return rowData.charAt(col);
}
public void fill(int row, int col) {
pointStack.push(new Point(col, row));
Point p;
while (pointStack.size() > 0) {
p = pointStack.pop();
fillRow(p.y, p.x);
}
}
private void checkRow(int row, int col, int minCol, int maxCol) {
boolean uu = false;
for (int x = col; x < maxCol; x++) {
if (!uu && used[row][x])
pointStack.add(new Point(x, row));
uu = used[row][x];
}
uu = true;
for (int x = col; x > minCol; x--) {
if (!uu && used[row][x])
pointStack.add(new Point(x, row));
uu = used[row][x];
}
}
private void fillRow(int row, int col) {
int lx, rx;
if (used[row][col]) {
for (rx = col; rx < colCount; rx++)
if (used[row][rx])
used[row][rx] = false;
else
break;
for (lx = col - 1; lx >= 0; lx--)
if (used[row][lx])
used[row][lx] = false;
else
break;
if (row > 0)
checkRow(row - 1, col, lx, rx);
if (row < data.size() - 1)
checkRow(row + 1, col, lx, rx);
}
}
public int getRowCount() {
return data.size();
}
public int getColCount() {
return colCount;
}
}
EDIT2: Both solutions were made using input from txt files in order to make the debugging and testing easier for larger arrays. If you need them to work with user input (the same you have in your code) as well, just make the following changes:
Change the main method so it will listen from user input (again):
public static void main(String[] args) {
Scanner sc=new Scanner(System.in);
int rowNum=sc.nextInt();
int columnNum=sc.nextInt(); // Note columnNum is not necessary
String[] matrix = new String[rowNum]; // I hope char[][] is not a requirement
for (int a = 0; a < rowNum; a++) // Read array data from user input
matrix[a] = sc.next();
sc.close();
Board2 board = new Board2(matrix); // Call the new constructor
System.out.println("Block count: " + board.getBlockCount());
}
Add a new constructor to Board2, that takes a String[] as input:
public Board2(String[] data) {
for (String line : data) {
this.data.add(line);
colCount = Math.max(colCount, line.length());
}
}
You may remove the previous constructor Board2(String filename) if it is not useful for you but it's not necessary.
Are you searching for this:
import java.util.Scanner;
class Blocks {
public static void removeBlock(char[][] matrix, int posX, int posY) {
if(0 <= posX && posX < matrix.length
&& 0 <= posY && posY < matrix[posX].length) {
if(matrix[posX][posY] == '0') {
return;
}
matrix[posX][posY] = '0';
} else {
return;
}
removeBlock(matrix, posX - 1, posY);
removeBlock(matrix, posX + 1, posY);
removeBlock(matrix, posX, posY - 1);
removeBlock(matrix, posX, posY + 1);
}
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
// read in
char[][] matrix = new char[sc.nextInt()][sc.nextInt()];
for(int a = 0; a < matrix.length; a++) {
matrix[a] = sc.next().toCharArray();
}
// calculate number of blocks
int nrBlocks = 0;
for(int i = 0; i < matrix.length; i++) {
for(int j = 0; j < matrix[i].length; j++) {
if(matrix[i][j] == '1') {
// we have found a block, so increment number of blocks
nrBlocks += 1;
// remove any 1's of the block from the array, so that they each block is not counted multiple times
removeBlock(matrix, i, j);
}
}
}
System.out.println(nrBlocks);
}
}
There's a linear time (in number of cells) solution to this. If I get time, I'll add the code to this answer, but if not the Wikipedia article (see EDIT below) gives pseudo code.
The idea is to scan line-by-line, assigning an incrementing unique run numbers to each runs of 1s we see (and changing the cell content to be that unique number) If in any run, the cells immediately above in the previous line were also 1 (that is, they now have a run number), then we know that their unique-run-number and the current unique-run number form part of a single block. So record that the run-above-run-number, and the current-run-number are equivalent (but don't bother to change anything on the board)
At the end, we have a count of the runs we've seen. and a set of equivalence relationships of unique-run-numbers. For each set of equivalent-numbers (say runs 3, 5, 14 form a block), we subtract from the run count the number of runs, minus 1 (in other words, replacing the multiple runs with a single block count).
I think I have some ideas to mitigate the worst case, but they're probably not worth it.
And that's the number of blocks.
The worst case for the equivalence classes is O(size of board) though (1-wide vertical blocks, with one space between them will do this). Fortunately, the entirely-black board will need only O(height of board) - each row will get one number, which will be marked equivalent with the next row.
EDIT: There's a Stackoverflow question about this already: can counting contiguous regions in a bitmap be improved over O(r * c)?
and it turns out I've just re-invented the two-pass "Connected Component Labelling" algorithm discussed on Wikipedia
(Disclaimer: There are maybe 20 different versions of this question on SO, but a reading through most of them still hasn't solved my issue)
Hello all, (relatively) beginner programmer here. So I've been trying to build a Sudoku backtracker that will fill in an incomplete puzzle. It seems to works perfectly well even when 1-3 rows are completely empty (i.e. filled in with 0's), but when more boxes start emptying (specifically around the 7-8 column in the fourth row, where I stopped writing in numbers) I get a Stack Overflow Error. Here's the code:
import java.util.ArrayList;
import java.util.HashSet;
public class Sudoku
{
public static int[][] puzzle = new int[9][9];
public static int filledIn = 0;
public static ArrayList<Integer> blankBoxes = new ArrayList<Integer>();
public static int currentIndex = 0;
public static int runs = 0;
/**
* Main method.
*/
public static void main(String args[])
{
//Manual input of the numbers
int[] completedNumbers = {0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,3,4,
8,9,1,2,3,4,5,6,7,
3,4,5,6,7,8,9,1,2,
6,7,8,9,1,2,3,4,5,
9,1,2,3,4,5,6,7,8};
//Adds the numbers manually to the puzzle array
ArrayList<Integer> completeArray = new ArrayList<>();
for(Integer number : completedNumbers) {
completeArray.add(number);
}
int counter = 0;
for(int i = 0; i < 9; i++) {
for(int j = 0; j < 9; j++) {
puzzle[i][j] = completeArray.get(counter);
counter++;
}
}
//Adds all the blank boxes to an ArrayList.
//The index is stored as 10*i + j, which can be retrieved
// via modulo and integer division.
boolean containsEmpty = false;
for(int i = 0; i < 9; i++) {
for(int j = 0; j < 9; j++) {
if(puzzle[i][j] == 0) {
blankBoxes.add(10*i + j);
containsEmpty = true;
}
}
}
filler(blankBoxes.get(currentIndex));
}
/**
* A general method for testing whether an array contains a
* duplicate, via a (relatively inefficient) sort.
* #param testArray The int[] that is being tested for duplicates
* #return True if there are NO duplicate, false if there
* are ANY duplicates.
*/
public static boolean checkDupl(int[] testArray) {
for(int i = 0; i < 8; i++) {
int num = testArray[i];
for(int j = i + 1; j < 9; j++) {
if(num == testArray[j] && num != 0) {
return false;
}
}
}
return true;
}
/**
* If the puzzle is not full, the filler will be run. The filler is my attempt at a backtracker.
* It stores every (i,j) for which puzzle[i][j] == 0. It then adds 1 to it's value. If the value
* is already somewhere else, it adds another 1. If it is 9, and that's already there, it loops to
* 0, and the index beforehand is rechecked.
*/
public static void filler(int indexOfBlank) {
//If the current index is equal to the size of blankBoxes, meaning that we
//went through every index of blankBoxes, meaning the puzzle is full and correct.
runs++;
if(currentIndex == blankBoxes.size()) {
System.out.println("The puzzle is full!" + "\n");
for(int i = 0; i < 9; i++) {
System.out.println();
for(int j = 0; j < 9; j++) {
System.out.print(puzzle[i][j]);
}
}
System.out.println("\n" + "The filler method was run " + runs + " times");
return;
}
//Assuming the puzzle isn't full, find the row/column of the blankBoxes index.
int row = blankBoxes.get(currentIndex) / 10;
int column = blankBoxes.get(currentIndex) % 10;
//Adds one to the value of that box.
puzzle[row][column] = (puzzle[row][column] + 1);
//Just used as a breakpoint for a debugger.
if(row == 4 && column == 4){
int x = 0;
}
//If the value is 10, meaning it went through all the possible values:
if(puzzle[row][column] == 10) {
//Do filler() on the previous box
puzzle[row][column] = 0;
currentIndex--;
filler(currentIndex);
}
//If the number is 1-9, but there are duplicates:
else if(!(checkSingleRow(row) && checkSingleColumn(column) && checkSingleBox(row, column))) {
//Do filler() on the same box.
filler(currentIndex);
}
//If the number is 1-9, and there is no duplicate:
else {
currentIndex++;
filler(currentIndex);
}
}
/**
* Used to check if a single row has any duplicates or not. This is called by the
* filler method.
* #param row
* #return
*/
public static boolean checkSingleRow(int row) {
return checkDupl(puzzle[row]);
}
/**
* Used to check if a single column has any duplicates or not.
* filler method, as well as the checkColumns of the checker.
* #param column
* #return
*/
public static boolean checkSingleColumn(int column) {
int[] singleColumn = new int[9];
for(int i = 0; i < 9; i++) {
singleColumn[i] = puzzle[i][column];
}
return checkDupl(singleColumn);
}
public static boolean checkSingleBox(int row, int column) {
//Makes row and column be the first row and the first column of the box in which
//this specific cell appears. So, for example, the box at puzzle[3][7] will iterate
//through a box from rows 3-6 and columns 6-9 (exclusive).
row = (row / 3) * 3;
column = (column / 3) * 3;
//Iterates through the box
int[] newBox = new int[9];
int counter = 0;
for(int i = row; i < row + 3; i++) {
for(int j = row; j < row + 3; j++) {
newBox[counter] = puzzle[i][j];
counter++;
}
}
return checkDupl(newBox);
}
}
Why am I calling it a weird error? A few reasons:
The box that the error occurs on changes randomly (give or take a box).
The actual line of code that the error occurs on changes randomly (it seems to usually happen in the filler method, but that's probably just because that's the biggest one.
Different compilers have different errors in different boxes (probably related to 1)
What I assume is that I just wrote inefficient code, so though it's not an actual infinite recursion, it's bad enough to call a Stack Overflow Error. But if anyone that sees a glaring issue, I'd love to hear it. Thanks!
Your code is not backtracking. Backtracking implies return back on failure:
if(puzzle[row][column] == 10) {
puzzle[row][column] = 0;
currentIndex--;
filler(currentIndex);// but every fail you go deeper
}
There are must be something like:
public boolean backtrack(int currentIndex) {
if (NoBlankBoxes())
return true;
for (int i = 1; i <= 9; ++i) {
if (NoDuplicates()) {
puzzle[row][column] = i;
++currentIndex;
if (backtrack(currentIndex) == true) {
return true;
}
puzzle[row][column] = 0;
}
}
return false;
}
Given k rooks and a n by n chess board, the rooks can safely be placed on the board W different ways, where
W = k!(n C k)^2
written differently W = n!n!/(k!(n-k)!(n-k)!)
PROBLEM STATEMENT:
Write a program that will run over a n by n chessboard and count all the ways that k rooks can safely be placed on the board.
MY RESEARCH:
After searching the internet I finally find a nQueensSolution code on Geekviewpoint and I modify it as below. However my code only works when k = n. Does anyone have an idea how to solve this for k<n?
Here is my code:
static int kRooksPermutations(int[] Q, int col, int k, int kLimit) {
int count = 0;
for (int x = 0; x < Q.length && col < Q.length; x++)
if (safeToAdd(Q, x, col)) {
if (k == kLimit - 1) {
count++;
Q[col] = -1;
} else {
Q[col] = x;
count += kRooksPermutations(Q, col + 1, k + 1, kLimit);
}
}
return count;
}//
static boolean safeToAdd(int[] Q, int r, int c) {
for (int y = 0; y < c; y++)
if (Q[y] == r)
return false;
return true;
}//
Here is a test code
public static void main(String... strings) {
kRooksPermutations(8,5);
}
Got it!
// Empty
static final int MT = -1;
static int kRooksPermutations(int[] Q, int col, int rooksInHand) {
// Are we at the last col?
if (col >= Q.length) {
// If we've placed K rooks then its a good'n.
return rooksInHand == 0 ? 1 : 0;
}
// Count at this level starts at 0
int count = 0;
// Have we run out of rooks?
if (rooksInHand > 0) {
// No! Try putting one in each row in this column.
for (int row = 0; row < Q.length; row++) {
// Can a rook be placed here?
if (safeToAdd(Q, row, col)) {
// Mark this spot occupied.
Q[col] = row;
// Recurse to the next column with one less rook.
count += kRooksPermutations(Q, col + 1, rooksInHand - 1);
// No longer occupied.
Q[col] = MT;
}
}
}
// Also try NOT putting a rook in this column.
count += kRooksPermutations(Q, col + 1, rooksInHand);
return count;
}
static boolean safeToAdd(int[] Q, int row, int col) {
// Unoccupied!
if (Q[col] != MT) {
return false;
}
// Do any columns have a rook in this row?
// Could probably stop at col here rather than Q.length
for (int c = 0; c < Q.length; c++) {
if (Q[c] == row) {
// Yes!
return false;
}
}
// All clear.
return true;
}
// Main entry - Build the array and start it all going.
private static void kRooksPermutations(int N, int K) {
// One for each column of the board.
// Contains the row number in which a rook is placed or -1 (MT) if the column is empty.
final int[] Q = new int[N];
// Start all empty.
Arrays.fill(Q, MT);
// Start at column 0 with no rooks placed.
int perms = kRooksPermutations(Q, 0, K);
// Print it.
System.out.println("Perms for N = " + N + " K = " + K + " = " + perms);
}
public static void main(String[] args) {
kRooksPermutations(8, 1);
kRooksPermutations(8, 2);
kRooksPermutations(8, 3);
kRooksPermutations(8, 4);
kRooksPermutations(8, 5);
kRooksPermutations(8, 6);
kRooksPermutations(8, 7);
kRooksPermutations(8, 8);
}
Prints:
Perms for N = 8 K = 1 = 64
Perms for N = 8 K = 2 = 1568
Perms for N = 8 K = 3 = 18816
Perms for N = 8 K = 4 = 117600
Perms for N = 8 K = 5 = 376320
Perms for N = 8 K = 6 = 564480
Perms for N = 8 K = 7 = 322560
Perms for N = 8 K = 8 = 40320
I'd probably solve the problem a different way:
solutions = 0;
k = number_of_rooks;
recurse(0,k);
print solutions;
...
recurse(row, numberOfRooks) {
if (numberOfRooks == 0) {
++solution;
return;
}
for(i=row; i<n; i++) {
for(j=0; j<n; j++) {
if (rook_is_ok_at(i, j)) {
place rook at i, j
recurse(i+1, numberOfRooks-1)
remove rook from i, j
}
}
}
}
This solves the problem in the general case. 8 rooks, 5 rooks, doesn't matter. Because all the rooks are unique, note when we place a rook we don't have to start over at (0,0)
Edit here are some results:
Here's are results I get for 1 to 8 rooks:
For 1 rooks, there are 64 unique positions
For 2 rooks, there are 1568 unique positions
For 3 rooks, there are 18816 unique positions
For 4 rooks, there are 117600 unique positions
For 5 rooks, there are 376320 unique positions
For 6 rooks, there are 564480 unique positions
For 7 rooks, there are 322560 unique positions
For 8 rooks, there are 40320 unique positions