Java Knights tour code - java

I am having some issues with the following code. First I cant seem to figure how to stop the piece from going out of bounds. Second when the code does work its not adding the count the steps correctly.
package runknightstour;
public class RunKnightsTour
{
public static void main(String[] args)
{
KnightMoves tour = new KnightMoves();
tour.runTour();
}
}
package runknightstour;
public class ChessBoard
{
public final int ROWS = 8;
public final int COLS = 8;
public final int FRAMESIZE = 12;
private int[][] board = new int[FRAMESIZE][FRAMESIZE];
public ChessBoard()
{
for (int y = 0; y < board.length; y++) {
for (int x = 0; x < board[y].length; x++) {
board[y][x] = -1;
}
for (int r = 2; r < ROWS + 2; r++) {
for (int c = 2; c < COLS + 2; c++) {
board[r][c] = 0;
}
}
}
}
public String toString()
{
String output = "";
for (int r = 0; r < FRAMESIZE; r++) {
for (int c = 0; c < FRAMESIZE; c++) {
output += board[r][c];
output += "\t";
}
output += "\n\n";
}
return output;
}
/**
*
* #param row
* #param col
* #param inStep in the range of 1 - 64
*/
public void setSquare(int row, int col, int inStep)
{
// adjust input to match 2 - 9
row += 1;
col +=1;
if (row > 1 && row < 10 && col > 1 && col < 10)
{
board[row][col] = inStep;
}
}
public int getSquare (int row, int col)
{
return board[row][col];
}
}
package runknightstour;
import java.util.Random;
import java.util.Scanner;
public class KnightMoves
{
public final int COMPLETE_TOUR = 64;
private ChessBoard kBoard = new ChessBoard();
private int[][] moves = new int[8][2];
private int stepNumber;
private int currentRow;
private int currentCol;
private int startRow;
private int startCol;
public KnightMoves()
{
moves[0][0] = -2; // move 0 row offset
moves[0][1] = 1; // move 0 col offset
moves[1][0] = -1; // move 1 row offset
moves[1][1] = 2; // move 1 col offset
moves[2][0] = 1; // move 2 row offset
moves[2][1] = 2; // move 2 col offset
moves[3][0] = 2; // move 3 row offset
moves[3][1] = 1; // move 3 col offset
moves[4][0] = 2; // move 4 row offset
moves[4][1] = -1; // move 4 col offset
moves[5][0] = 1; // move 5 row offset
moves[5][1] = -2; // move 5 col offset
moves[6][0] = -1; // move 6 row offset
moves[6][1] = -2; // move 6 col offset
moves[7][0] = -2; // move 7 row offset
moves[7][1] = -1; // move 7 col offset
stepNumber = 0;
startRow = startCol = 1;
currentRow = currentCol = 1;
}
/**
* Description: Get the starting board Position (row, col) for the
* KNIGHT from program user
*/
public void getStartPosition()
{
Scanner input = new Scanner(System.in);
System.out.print("\n enter a starting location for the knight's row ");
startRow = input.nextInt();
System.out.print("\n enter a starting location for the knight's col ");
startCol = input.nextInt();
kBoard.setSquare(startRow, startCol, 1);
System.out.println(kBoard);
}
/**
* Mutator: runTour()
*/
public void runTour()
{
getStartPosition();
// if stepNumber is equal to COMPLETE_TOUR
// report that the knight made a complete tour
do {
takeStep();
}
while (stepNumber < 64 && takeStep()== true);
System.out.println(kBoard);
System.out.println(toString());
}
private boolean takeStep()
{
boolean stepTaken = true;
int random1;
Random rand = new Random();
random1 = rand.nextInt(8);
int tryStepRow =0;
int tryStepCol=0;
int attempts =0;
do {
tryStepRow = currentRow + moves[random1][0];
tryStepCol = currentCol + moves[random1][1];
if(kBoard.getSquare(tryStepRow,tryStepCol)==0)
{
kBoard.setSquare(tryStepRow,tryStepCol, stepNumber++);
currentRow= tryStepRow;
currentCol = tryStepCol;
}
else
{
attempts++;
}
} while (stepTaken == false && attempts < 200);
return stepTaken;
}
public String toString()
{
String whatHappened = "";
whatHappened += "Starting location: [" + startRow + ", "
+ startCol + "]\n";
whatHappened += " Tour ended after " + stepNumber + " steps\n";
whatHappened += "The knight got stuck in location ["
+ (currentRow ) + ", " + (currentCol ) + "]\n";
return whatHappened;
}
}
Sample message I get.
Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: -1
at runknightstour.ChessBoard.getSquare(ChessBoard.java:68)
at runknightstour.KnightMoves.takeStep(KnightMoves.java:101)
at runknightstour.KnightMoves.runTour(KnightMoves.java:80)
at runknightstour.RunKnightsTour.main(RunKnightsTour.java:22)
I:\CSC122\RunKnightsTour\nbproject\build-impl.xml:1039: The following error occurred while executing this line:
I:\CSC122\RunKnightsTour\nbproject\build-impl.xml:804: Java returned: 1
BUILD FAILED (total time: 2 seconds)

If you carefully see the function setSquare() you'll notice that it is going into an infinite loop as there is no increment conditions given on row or col.
Also, if your board size is not big enough then you can end up getting ArraysOutOfBounds exception.
public void setSquare(int row, int col, int inStep)
{
// adjust input to match 2 - 9
row += 1;
col += 1;
if (row > 1 && row < 10 && col > 1 && col < 10)
{
/* Where are you incrementing row/col? */
board[row][col] = inStep;
}
}

Related

Why the dynamic programming solution only works for squre board?

The problem is:
Given exact k steps, how many ways to move a point from start point to destination? Point can move for eight directions(horizontally, vertically, diagonally, anti-diagonally).
I solved the problem through DP, but it works only for square board, not for rectangle board. I mean if dim[0]!=dim[1] in the code, it will run into an error result.
Here I can provide test case:
Test case 1
dim = {5,6},start = {0,2},end = {2,2},steps = 4;
result is 50(expected: 105)
Test case 2
dim = {5,5},int[] start = {0,2},end = {2,2},steps = 4;
result is 105(expected: 105)
Here is the code:
private static int[][] dir = {{0,1},{1,0},{1,1},{1,-1},{0,-1},{-1,0},{-1,-1},{-1,1}};
//DP
/*
#param dim, a tuple (width, height) of the dimensions of the board
#param start, a tuple (x, y) of the king's starting coordinate
#param target, a tuple (x, y) of the king's destination
*/
public static int countPaths2(int[] dim, int[] start, int[] des, int steps){
if(dim[0] == 0 || dim[1] == 0) return 0;
int[][][] dp = new int[dim[0]*dim[1]][dim[1]*dim[0]][steps+1];
for(int step = 0; step<=steps;step++){
for(int i = 0; i< dim[0]*dim[1];i++){
for(int j = 0; j< dim[0]*dim[1];j++){
if(step == 0 && i == j){
dp[i][j][step] = 1;
}
if(step >= 1){
for(int k =0; k< dir.length;k++){
int row = i / dim[0];
int col = i % dim[1];
if(row + dir[k][0] >= 0 && row + dir[k][0]< dim[0] && col + dir[k][1]>=0 && col + dir[k][1]< dim[1]){
int adj = (row + dir[k][0])*dim[0] + col + dir[k][1];
dp[i][j][step] += dp[adj][j][step-1];
}
}
}
}
}
}
int startPos = start[0]*dim[0] + start[1];
int targetPos = des[0]*dim[0] + des[1];
return dp[startPos][targetPos][steps];
}
public static void main(String[] args){
int[] dim = {5,5}; // can just use to square;
int[] start = {0,2};
int[] end = {2,2};
int steps = 7;
System.out.println(countPaths2(dim, start,end, steps));
}
How could I make it work for any kind of board?
The culprit is:
int row = i / dim[0];
int col = i % dim[1]; // <- this should have been dim[0]
in the div/mod pattern you are supposed to divide and modulo by the same number...

2D array board rules

I'm doing a program , it is about an "object" (element) that move in 8way direction based on input.
My questions are : How can I make this element to visit cells of the board (2D Array) only once? How do I make it stay it current position if it can not move according to rules?
Start is position (0,0)
As input it get n-> number of dimension Matrix n x n , direction and t-> seconds. The other thing I don't get how to implement is input seconds, I get input seconds and directions because based on those I have to move the element into this 2D array list.
I've completed mostly of the program. I can give you my code here if you want to check it and give me advice. I'm stuck in it and I need help.
I want to print number of cells that are not visited. My idea is to give a number 0 to all cells that are not visited and the rest that are visited give number 1 as value. Like cell[x][x]=1; And in the end I count all cells that have number 0 as value and print count.
For a valid move in a particular direction, the object must move to a previously unoccupied cell, or else wait until the next direction.
You have defined cell[row][col] to represent the visited state; 0=unvisited, 1=visited. At the end, the number of unvisited cells will be the number of cell elements equal to zero.
To determine if the object should be moved, two checks must be done:
Make sure the next position is a valid matrix position (you are doing this correctly)
Make sure the next position has not yet been visited (will show below)
// Iterate through all k movements
for (i = 0; i < arrTime.length - 1; i++) {
// Move by 1 second until reach next instruction
for (j = arrTime[i]; j < arrTime[i + 1]; j++) {
// South East
if (arrDirection[i].equals("SE")) {
// Check #1 above (a valid matrix position)
if (nCurrRow < n - 1 && nCurrCol < n - 1) {
// Check #2 above (only move into unvisited position)
if (cell[nCurrRow+1][nCurrCol+1] == 0) {
// Move, and record that cell has been visited
nCurrRow++;
nCurrCol++;
cell[nCurrRow][nCurrCol] = 1;
}
}
}
// Other directions following the template for South East
Now to count unvisited cells:
int unVisited=0;
for (int i=0; i<n; i++)
for (int j=0; j<n; j++)
if (cell[i][j] == 0) unVisited++;
EDIT: To describe the two issues with the code.
1) The first issue relates to the j loop. The current j loop is
for(j = arrTime[i]; j <= arrTime[i + 1]; j++)
But must be:
for(j = arrTime[i]; j < arrTime[i + 1]; j++)
The way it was moves the object one more time than it should
2) The final movement was not being performed. The original code was:
arrTime[k] = arrTime[k - 1];
But must be:
arrTime[k] = arrTime[k - 1] + n;
Once you make these two changes, both test cases will work.
EDIT #2: A way to reduce the j loop
Previously, the j loop would run each iteration to the next i value. Here, we short circuit and leave the j loop as soon the object is unable to move. In the second test case, this reduced the number of j iterations from 50 to 28.
for (i = 0; i < arrTime.length - 1; i++) {
boolean canMove = true;
for (j = arrTime[i]; j < arrTime[i + 1] && canMove; j++) {
if (arrDirection[i].equals("SE")) {
if (nCurrRow < n - 1 && nCurrCol < n - 1 && cell[nCurrRow + 1][nCurrCol + 1] == 0) {
nCurrRow++;
nCurrCol++;
cell[nCurrRow][nCurrCol] = 1;
} else
canMove = false;
} else if (arrDirection[i].equals("NE")) {
if (nCurrRow > 0 && nCurrCol < n - 1 && cell[nCurrRow - 1][nCurrCol + 1] == 0) {
nCurrRow--;
nCurrCol++;
cell[nCurrRow][nCurrCol] = 1;
} else
canMove = false;
} ...
EDIT: Looking for test cases that will fail
Looking at your new comments, it is legal that the wind changes when t=1000000 (the maximum allowed value for t).
Consider this very simple test case:
3 2 (3x3 matrix, two wind changes)
0 E (wind blows east right away; robot moves to 0,2)
1000000 S (wind blows south at 1000000s, robot should move to 2,2)
Result should be: 4, but your current code will give 6 because it doesn't accept t=1000000.
If you change the line:
if(seconds >=0 && seconds<1000000 && k >=2 && k<1000000) {
to
if(seconds >=0 && seconds<=1000000 && k >=2 && k<=1000000) {
Then you get the expected answer of 4. It is very likely that at least one test case will push all the input boundaries, including when t=1000000.
EDIT: Faster algorithm #2
The current algorithm can be improved by reducing the number of if statements. There are two important improvements:
1) The former code had to use if to check both a) Valid matrix location b) If the location had been previously visited. You can use one 1 if for this, if you create a border around the matrix, and pre-populate with the value 1. Because of the border, the starting position is 1,1 and not 0,0.
2) Inside the j loop, the code unnecessarily looked up the direction. Now the direction is determined prior to the j loop, making the code inside the j loop much faster.
Also the number of unvisited cells is dynamic; no need to count them after the i loop completes. I changed the type to long because when n gets large, then the number of unvisited cells can be up to n*n which requires a type long. This might solve some of the incorrect answers.
If you study the new code, compare it to the older one, you will see many less if statements. This should scale better under larger test cases. Lets see if some of the test cases that were timing out improve.
public class Robot {
public static void main(String[] args) {
Scanner in = new Scanner(System.in);
int j = 0;
int i = 0;
int n = in.nextInt();
int k = in.nextInt();
int[] arrTime = new int[k + 1];
String[] arrDirection = new String[k];
for (j = 0; j < k; j++) {
int seconds = in.nextInt();
if (seconds >= 0 && seconds <= 1000000) {
arrTime[j] = seconds;
}
String direction = in.next();
arrDirection[j] = direction;
}
arrTime[k] = arrTime[k - 1] + n;
// Add a border around the matrix with values of 1
int N = n + 2;
int[][] cell = new int[N][N];
for (j = 0; j < cell.length; j++) {
cell[0][j] = 1; // Top border
cell[j][0] = 1; // Left border
cell[j][N - 1] = 1; // Right border
cell[N - 1][j] = 1; // Bottom border
}
int nCurrRow = 1;
int nCurrCol = 1;
cell[nCurrRow][nCurrCol] = 1;
long R = n * n - 1; // Number of remaining unvisited cells
for (i = 0; i < arrTime.length - 1; i++) {
boolean canMove = true;
int xDir = 0;
int yDir = 0;
if (arrDirection[i].equals("SE")) {
xDir = 1;
yDir = 1;
} else if (arrDirection[i].equals("NE")) {
xDir = 1;
yDir = -1;
} else if (arrDirection[i].equals("E")) {
xDir = 1;
} else if (arrDirection[i].equals("N")) {
yDir = -1;
} else if (arrDirection[i].equals("NW")) {
xDir = -1;
yDir = -1;
} else if (arrDirection[i].equals("W")) {
xDir = -1;
} else if (arrDirection[i].equals("SW")) {
xDir = -1;
yDir = 1;
} else if (arrDirection[i].equals("S")) {
yDir = 1;
}
for (j = arrTime[i]; j < arrTime[i + 1] && canMove; j++) {
if (cell[nCurrRow + yDir][nCurrCol + xDir] == 0) {
nCurrRow += yDir;
nCurrCol += xDir;
cell[nCurrRow][nCurrCol] = 1;
R--;
} else
canMove = false;
}
}
//printArray(cell);
System.out.println(R);
in.close();
}
static void printArray(int[][] arr) {
for (int row = 0; row < arr.length; row++) {
for (int col = 0; col < arr.length; col++)
System.out.print(arr[row][col]);
System.out.println();
}
}
}
EDIT #3: More efficient memory usage; using BitSet
I suspect that the higher test cases are failing because the value of n is large in those cases. It is simple to test that when n=100000 that the cell array is too large, causing java memory error. So this code make the cell array very compact by using bitset. Lets see how this code does:
public class Robot {
public static void main(String[] args) {
Scanner in = new Scanner(System.in);
int j = 0;
int i = 0;
int n = in.nextInt();
int k = in.nextInt();
int[] arrTime = new int[k + 1];
String[] arrDirection = new String[k];
for (j = 0; j < k; j++) {
int seconds = in.nextInt();
if (seconds >= 0 && seconds <= 1000000) {
arrTime[j] = seconds;
}
String direction = in.next();
arrDirection[j] = direction;
}
if (k >= 2 && k < 1000000) {
arrTime[k] = arrTime[k - 1] + n;
}
int N = n + 2;
BitSet[] cell = new BitSet[N];
for (j = 0; j < cell.length; j++)
cell[j] = new BitSet(N);
for (j = 0; j < cell.length; j++) {
set(cell, 0, j);
set(cell, j, 0);
set(cell, j, N-1);
set(cell, N-1, j);
}
int nCurrRow = 1;
int nCurrCol = 1;
set(cell,nCurrRow,nCurrCol);
long R = n * n - 1;
for (i = 0; i < arrTime.length - 1; i++) {
boolean canMove = true;
int xDir = 0;
int yDir = 0;
if (arrDirection[i].equals("SE")) {
xDir = 1;
yDir = 1;
} else if (arrDirection[i].equals("NE")) {
xDir = 1;
yDir = -1;
} else if (arrDirection[i].equals("E")) {
xDir = 1;
} else if (arrDirection[i].equals("N")) {
yDir = -1;
} else if (arrDirection[i].equals("NW")) {
xDir = -1;
yDir = -1;
} else if (arrDirection[i].equals("W")) {
xDir = -1;
} else if (arrDirection[i].equals("SW")) {
xDir = -1;
yDir = 1;
} else if (arrDirection[i].equals("S")) {
yDir = 1;
}
for (j = arrTime[i]; j < arrTime[i + 1] && canMove; j++) {
if (!isSet(cell,nCurrRow + yDir, nCurrCol + xDir)) {
nCurrRow += yDir;
nCurrCol += xDir;
set(cell,nCurrRow,nCurrCol);
R--;
} else
canMove = false;
}
}
//System.out.println();
//printArray(cell);
System.out.println(R);
in.close();
}
static boolean isSet(BitSet[] cell, int x, int y) {
BitSet b = cell[x];
return b.get(y);
}
static void set(BitSet[] cell, int x, int y) {
BitSet b = cell[x];
b.set(y);
}
static void printArray(int[][] arr) {
for (int row = 0; row < arr.length; row++) {
for (int col = 0; col < arr.length; col++)
System.out.print(arr[row][col]);
System.out.println();
}
}
}
EDIT: Attempt to read and process at the same time
This technique sometimes helps with large input. Rather than read all the input, then process in a second phase, process it as you read. In this case there is no need to store the data in two arrays (one for arrivalTime and one for direction). Lets see if this helps at all.
public class Robot2 {
static int nCurrRow = 1;
static int nCurrCol = 1;
static long R = 0;
static int[][] cell;
public static void main(String[] args) {
Scanner in = new Scanner(System.in);
int i = 0;
int n = in.nextInt();
int k = in.nextInt();
// Add a border around the matrix with values of 1
int N = n + 2;
cell = new int[N][N];
for (i = 0; i < cell.length; i++) {
cell[0][i] = 1; // Top border
cell[i][0] = 1; // Left border
cell[i][N - 1] = 1; // Right border
cell[N - 1][i] = 1; // Bottom border
}
cell[nCurrRow][nCurrCol] = 1;
R = (long)n * n - 1; // Number of remaining unvisited cells
int sec1 = in.nextInt();
int sec2 = 0;
String dir1 = in.next();
String dir2;
for (i = 0; i < k - 1; i++) {
sec2 = in.nextInt();
dir2 = in.next();
move(sec2-sec1, dir1);
dir1 = dir2;
sec1 = sec2;
}
move(n, dir1);
System.out.println(R);
in.close();
}
static void move(int t, String dir1) {
boolean canMove = true;
int xDir = 0;
int yDir = 0;
if (dir1.equals("SE")) {
xDir = 1;
yDir = 1;
} else if (dir1.equals("NE")) {
xDir = 1;
yDir = -1;
} else if (dir1.equals("E")) {
xDir = 1;
} else if (dir1.equals("N")) {
yDir = -1;
} else if (dir1.equals("NW")) {
xDir = -1;
yDir = -1;
} else if (dir1.equals("W")) {
xDir = -1;
} else if (dir1.equals("SW")) {
xDir = -1;
yDir = 1;
} else if (dir1.equals("S")) {
yDir = 1;
}
for (int j = 0; j < t && canMove; j++) {
if (cell[nCurrRow + yDir][nCurrCol + xDir] == 0) {
nCurrRow += yDir;
nCurrCol += xDir;
cell[nCurrRow][nCurrCol] = 1;
R--;
} else
canMove = false;
}
}
}
EDIT: Combination of BitSet and one phase processing
public class Robot3 {
static int nCurrRow = 1;
static int nCurrCol = 1;
static long R = 0;
static BitSet[] cell;
public static void main(String[] args) {
Scanner in = new Scanner(System.in);
int i = 0;
int n = in.nextInt();
int k = in.nextInt();
// Add a border around the matrix with values of 1
int N = n + 2;
cell = new BitSet[N];
for (i = 0; i < cell.length; i++)
cell[i] = new BitSet(N);
for (i = 0; i < cell.length; i++) {
set(cell, 0, i);
set(cell, i, 0);
set(cell, i, N-1);
set(cell, N-1, i);
}
set(cell, nCurrRow, nCurrCol);
R = (long)n * n - 1; // Number of remaining unvisited cells
int sec1 = in.nextInt();
int sec2 = 0;
String dir1 = in.next();
String dir2;
for (i = 0; i < k - 1; i++) {
sec2 = in.nextInt();
dir2 = in.next();
move(sec2-sec1, dir1);
dir1 = dir2;
sec1 = sec2;
}
move(n, dir1);
System.out.println(R);
in.close();
}
static void move(int t, String dir1) {
boolean canMove = true;
int xDir = 0;
int yDir = 0;
if (dir1.equals("SE")) {
xDir = 1;
yDir = 1;
} else if (dir1.equals("NE")) {
xDir = 1;
yDir = -1;
} else if (dir1.equals("E")) {
xDir = 1;
} else if (dir1.equals("N")) {
yDir = -1;
} else if (dir1.equals("NW")) {
xDir = -1;
yDir = -1;
} else if (dir1.equals("W")) {
xDir = -1;
} else if (dir1.equals("SW")) {
xDir = -1;
yDir = 1;
} else if (dir1.equals("S")) {
yDir = 1;
}
for (int j = 0; j < t && canMove; j++) {
if (!isSet(cell,nCurrRow + yDir, nCurrCol + xDir)) {
nCurrRow += yDir;
nCurrCol += xDir;
set(cell, nCurrRow, nCurrCol);
R--;
} else
canMove = false;
}
}
static boolean isSet(BitSet[] cell, int x, int y) {
return cell[x].get(y);
}
static void set(BitSet[] cell, int x, int y) {
cell[x].set(y);
}
}
EDIT: Replacing Scanner with BufferedReader
There is a chance that Scanner is too slow:
https://www.cpe.ku.ac.th/~jim/java-io.html
This may be worth a try:
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.BitSet;
import java.util.StringTokenizer;
public class Robot3 {
static int nCurrRow = 1;
static int nCurrCol = 1;
static long R = 0;
static BitSet[] cell;
public static void main(String[] args) throws IOException {
Reader.init(System.in);
//Scanner in = new Scanner(System.in);
int i = 0;
int n = Reader.nextInt();
int k = Reader.nextInt();
// Add a border around the matrix with values of 1
int N = n + 2;
cell = new BitSet[N];
for (i = 0; i < cell.length; i++)
cell[i] = new BitSet(N);
for (i = 0; i < cell.length; i++) {
set(cell, 0, i);
set(cell, i, 0);
set(cell, i, N-1);
set(cell, N-1, i);
}
set(cell, nCurrRow, nCurrCol);
R = (long)n * n - 1; // Number of remaining unvisited cells
int sec1 = Reader.nextInt();
int sec2 = 0;
String dir1 = Reader.next();
String dir2 = "";
for (i = 0; i < k - 1; i++) {
sec2 = Reader.nextInt();
dir2 = Reader.next();
move(sec2-sec1, dir1);
dir1 = dir2;
sec1 = sec2;
}
move(n, dir1);
System.out.println(R);
}
static void move(int t, String dir1) {
boolean canMove = true;
int xDir = 0;
int yDir = 0;
if (dir1.equals("SE")) {
xDir = 1;
yDir = 1;
} else if (dir1.equals("NE")) {
xDir = 1;
yDir = -1;
} else if (dir1.equals("E")) {
xDir = 1;
} else if (dir1.equals("N")) {
yDir = -1;
} else if (dir1.equals("NW")) {
xDir = -1;
yDir = -1;
} else if (dir1.equals("W")) {
xDir = -1;
} else if (dir1.equals("SW")) {
xDir = -1;
yDir = 1;
} else if (dir1.equals("S")) {
yDir = 1;
}
for (int j = 0; j < t && canMove; j++) {
if (!isSet(cell,nCurrRow + yDir, nCurrCol + xDir)) {
nCurrRow += yDir;
nCurrCol += xDir;
set(cell, nCurrRow, nCurrCol);
R--;
} else
canMove = false;
}
}
static boolean isSet(BitSet[] cell, int x, int y) {
return cell[x].get(y);
}
static void set(BitSet[] cell, int x, int y) {
cell[x].set(y);
}
static class Reader {
static BufferedReader reader;
static StringTokenizer tokenizer;
/** call this method to initialize reader for InputStream */
static void init(InputStream input) {
reader = new BufferedReader(
new InputStreamReader(input) );
tokenizer = new StringTokenizer("");
}
/** get next word */
static String next() throws IOException {
while ( ! tokenizer.hasMoreTokens() ) {
//TODO add check for eof if necessary
tokenizer = new StringTokenizer(
reader.readLine() );
}
return tokenizer.nextToken();
}
static int nextInt() throws IOException {
return Integer.parseInt( next() );
}
static double nextDouble() throws IOException {
return Double.parseDouble( next() );
}
}
}
EDIT: Using a Set to store visited cells
It turns out that when n is large, creating BitSets is an expensive process. About 1.4s was taken just to create the array of BitSets. So arrays don't work, and BitSet creation is slow. After some thought, I realized that a regular HashSet<Long> should work to store visited cells, and it doesn't have the same cost to create it.
public class Robot4 {
static int nCurrRow = 1;
static int nCurrCol = 1;
static long R = 0;
static Set<Long> cell;
static long N;
public static void main(String[] args) throws IOException {
Reader.init(System.in);
int i = 0;
int n = Reader.nextInt();
int k = Reader.nextInt();
// Add a border around the matrix with values of 1
N = n + 2L;
cell = new HashSet<Long>(1000000);
for (i = 0; i < N; i++) {
set(0, i);
set(i, 0);
set(i, n+1);
set(n+1, i);
}
set(nCurrRow, nCurrCol);
R = (long)n * n - 1; // Number of remaining unvisited cells
int sec1 = Reader.nextInt();
int sec2 = 0;
String dir1 = Reader.next();
String dir2 = "";
for (i = 0; i < k - 1; i++) {
sec2 = Reader.nextInt();
dir2 = Reader.next();
move(sec2-sec1, dir1);
dir1 = dir2;
sec1 = sec2;
}
move(n, dir1);
System.out.println(R);
}
static void move(int t, String dir1) {
boolean canMove = true;
int xDir = 0;
int yDir = 0;
if (dir1.equals("SE")) {
xDir = 1;
yDir = 1;
} else if (dir1.equals("NE")) {
xDir = 1;
yDir = -1;
} else if (dir1.equals("E")) {
xDir = 1;
} else if (dir1.equals("N")) {
yDir = -1;
} else if (dir1.equals("NW")) {
xDir = -1;
yDir = -1;
} else if (dir1.equals("W")) {
xDir = -1;
} else if (dir1.equals("SW")) {
xDir = -1;
yDir = 1;
} else if (dir1.equals("S")) {
yDir = 1;
}
for (int j = 0; j < t && canMove; j++) {
if (!isSet(nCurrRow + yDir, nCurrCol + xDir)) {
nCurrRow += yDir;
nCurrCol += xDir;
set(nCurrRow, nCurrCol);
R--;
} else
canMove = false;
}
}
static boolean isSet(int x, int y) {
return cell.contains(indexId(x,y));
}
static void set(int x, int y) {
cell.add(indexId(x,y));
}
static long indexId(int x, int y) {
return x*N+y;
}
static class Reader {
static BufferedReader reader;
static StringTokenizer tokenizer;
/** call this method to initialize reader for InputStream */
static void init(InputStream input) {
reader = new BufferedReader(
new InputStreamReader(input) );
tokenizer = new StringTokenizer("");
}
/** get next word */
static String next() throws IOException {
while ( ! tokenizer.hasMoreTokens() ) {
tokenizer = new StringTokenizer(
reader.readLine() );
}
return tokenizer.nextToken();
}
static int nextInt() throws IOException {
return Integer.parseInt( next() );
}
static double nextDouble() throws IOException {
return Double.parseDouble( next() );
}
}
}

Printing integer from 2D array using nested FOR Loops

I'm having a bit of a problem with a piece of Java code, part of an AI project. The programm is supposed to take a 11x13 2d array representing a maze. The printed maze we are given uses characters for each cell, but for ease of use I've converted it to integers using a mnemonic code.
My problem is when I try to print the 2d integer array to the screen, to check eveything is OK, I get zeros at every cell, even though I have a check function in place which parses the array cell-by-cell checking for incorrect values.
The project is currently composed of 2 files. The main file - function (AISemesterProject.java) and a file that will implement the UCS algorithm in the future (UCS.java)
AISemesterProject.java
package aisemesterproject;
public class AISemesterProject
{
public static void main(String[] args)
{
UCS a = new UCS();
a.checkArrayInt();
a.printInt();
}
}
UCS.java
package aisemesterproject;
import java.util.Arrays;
public class UCS
{
int row = 11;
int col = 13;
int[][] array_int = new int[row][col];
public UCS()
{
// Lets assume
// x = 0
// e = 1
// d = 2
// s = 8
// g = 9
int[][] array_int = new int[][] {
{0,1,0,1,1,1,1,0,0,1,0,9,0},
{1,1,1,2,0,1,1,0,0,1,2,1,0},
{0,1,0,1,1,1,1,0,0,1,0,0,0},
{8,1,2,0,1,2,0,1,1,2,1,1,1},
{0,0,1,1,0,1,1,1,0,0,0,0,0},
{1,2,1,0,1,0,1,1,0,0,1,1,1},
{0,1,2,0,1,0,0,2,1,1,2,1,9},
{1,0,1,1,2,1,1,1,0,1,1,1,1},
{1,1,2,1,1,0,0,1,0,0,0,0,0},
{0,0,1,1,1,0,0,1,1,1,1,1,2},
{0,0,1,0,0,1,1,1,0,9,0,1,1}
};
}
public void checkArrayInt()
{
int i = 0, j = 0;
boolean checker = false;
for(i = 0; i < row; i++)
{
for(j = 0; j < col; j++)
{
if(!(array_int[i][i] == 0 || array_int[i][j] == 1 || array_int[i][j] == 2 || array_int[i][j] == 8 || array_int[i][j] == 9))
{
checker = true;
System.out.print("Error at Row:" + i + " Column:" + j + "\n");
}
}
}
if(checker == false)
{
System.out.print("Array OK... \n");
}
}
public void printInt()
{
int i = 0, j = 0;
//System.out.println(Arrays.deepToString(array_int));
for(i = 0; i < row; i++)
{
System.out.print("Row " + (i + 1) + ":");
for(j = 0; j < col; j++)
{
System.out.print(" " + String.valueOf(array_int[i][j]));
//System.out.print(" " + Integer.toString(array_int[i][j]));
//System.out.printf(" %d", array_int[i][j]);
//System.out.print(" " + array_int[i][j]);
}
System.out.print("\n");
}
}
}
Output
As you can see the output is not what I expected and I have tried 4 different methods for the print (1 active, 3 commented) but the result is always the same.
Anyone have an idea what am I missing or doing wrong?
Thanks for your time.
It looks like you have a scope issue...
int[][] array_int = new int[row][col];
public UCS()
{
// Lets assume
// x = 0
// e = 1
// d = 2
// s = 8
// g = 9
array_int = new int[][] {
{0,1,0,1,1,1,1,0,0,1,0,9,0},
{1,1,1,2,0,1,1,0,0,1,2,1,0},
{0,1,0,1,1,1,1,0,0,1,0,0,0},
{8,1,2,0,1,2,0,1,1,2,1,1,1},
{0,0,1,1,0,1,1,1,0,0,0,0,0},
{1,2,1,0,1,0,1,1,0,0,1,1,1},
{0,1,2,0,1,0,0,2,1,1,2,1,9},
{1,0,1,1,2,1,1,1,0,1,1,1,1},
{1,1,2,1,1,0,0,1,0,0,0,0,0},
{0,0,1,1,1,0,0,1,1,1,1,1,2},
{0,0,1,0,0,1,1,1,0,9,0,1,1}
};
you already created the array as a class level variable
Your constructor is setting the local variable array_int. This local variable overshadows the field with the same name, and thus it never sees the array you're assigning to it.
You should make sure that you're assigning to the field, which can most easily be done by removing the int[][] word from your constructor.
Thank you everyone. I moved the declatarion from the constructor to the variable at the beggining and it worked.
package aisemesterproject;
import java.util.Arrays;
public class UCS
{
int row = 11;
int col = 13;
// Lets assume
// x = 0
// e = 1
// d = 2
// s = 8
// g = 9
int[][] array_int = new int[][] {
{0,1,0,1,1,1,1,0,0,1,0,9,0},
{1,1,1,2,0,1,1,0,0,1,2,1,0},
{0,1,0,1,1,1,1,0,0,1,0,0,0},
{8,1,2,0,1,2,0,1,1,2,1,1,1},
{0,0,1,1,0,1,1,1,0,0,0,0,0},
{1,2,1,0,1,0,1,1,0,0,1,1,1},
{0,1,2,0,1,0,0,2,1,1,2,1,9},
{1,0,1,1,2,1,1,1,0,1,1,1,1},
{1,1,2,1,1,0,0,1,0,0,0,0,0},
{0,0,1,1,1,0,0,1,1,1,1,1,2},
{0,0,1,0,0,1,1,1,0,9,0,1,1}
};
public UCS()
{
// Lets assume
// x = 0
// e = 1
// d = 2
// s = 8
// g = 9
// Array initialization outside the constructor scope
}
public void checkArrayInt()
{
int i = 0, j = 0;
boolean checker = false;
for(i = 0; i < row; i++)
{
for(j = 0; j < col; j++)
{
if(array_int[i][j] == 0) //Check for 0 = x
{
checker = false;
}
else if(array_int[i][j] == 1) //Check for 1 = e
{
checker = false;
}
else if(array_int[i][j] == 2) //Check for 2 = d
{
checker = false;
}
else if(array_int[i][j] == 8) //Check for 8 = s
{
checker = false;
}
else if(array_int[i][j] == 9) //Check for 9 = g
{
checker = false;
}
else //All other integers, which are false
{
checker = true;
System.out.print("Error at Row:" + i + " Column:" + j + "\n");
}
}
}
if(checker == false)
{
System.out.print("Array OK... \n");
}
}
public void printInt()
{
int i = 0, j = 0;
//System.out.println(Arrays.deepToString(array_int));
for(i = 0; i < row; i++)
{
System.out.print("Row " + (i + 1) + ":");
for(j = 0; j < col; j++)
{
System.out.print(" " + String.valueOf(array_int[i][j]));
//System.out.print(" " + Integer.toString(array_int[i][j]));
//System.out.printf(" %d", array_int[i][j]);
//System.out.print(" " + array_int[i][j]);
}
System.out.print("\n");
}
}
}

I cannot get the write to file part of the code to work

I cannot get my write to file code working the error message- writeFile cannot be resolved. I a trying to write the board positions to a text file so the game can be saved. If the user chooses to save the game then it should call a new subroutine that will write the pieces to the file.
/*
* Skeleton program code for the AQA COMP1 Summer 2016 examination
* This code to be used in conjunction with the Preliminary Material
* written by the AQA Programmer Team
* Developed in the NetBeans 7.3.1. programming environment
* Additional classes AQAConsole2016, AQAReadTextFile2016 and
* AQAWriteTextFile2016 may be used.
*
* A package name may be chosen and private and public modifiers added -
* permission to make these changes to the Skeleton Program does not need
* to be obtained from AQA or the AQA Programmer
*/
import java.util.Random;
public class Aaa {
AQAConsole2016 console = new AQAConsole2016();
Random random = new Random();
int boardSize;
public Aaa() {
char choice;
String playerName;
// int boardSize;
boardSize = 6;
playerName = "";
do {
displayMenu();
choice = getMenuChoice(playerName);
switch (choice) {
case 'p' : playGame(playerName, boardSize);
break;
case 'e' : playerName = getPlayersName();
break;
case 'c' : boardSize = changeBoardSize();
break;
}
} while (choice != 'q');
}
void setUpGameBoard(char[][] board, int boardSize) {
for (int row = 1; row <= boardSize; row++) {
for (int column = 1; column <= boardSize; column++) {
if (row == (boardSize + 1) / 2 && column == (boardSize + 1) / 2 + 1 || column == (boardSize + 1) / 2 && row == (boardSize + 1) / 2 + 1) {
board[row][column] = 'C';
} else {
if (row == (boardSize + 1) / 2 + 1 && column == (boardSize + 1) / 2 + 1 || column == (boardSize + 1) / 2 && row == (boardSize + 1) / 2) {
board[row][column] = 'H';
} else {
board[row][column] = ' ';
}
}
}
}
}
int changeBoardSize() {
int boardSize;
do {
console.print("Enter a board size (between 4 and 9): ");
boardSize = console.readInteger("");
} while (!(boardSize >= 4 && boardSize <= 9));
return boardSize;
}
int getHumanPlayerMove(String playerName) {
int coordinates;
console.print(playerName + " enter the coordinates of the square where you want to place your piece: ");
coordinates = console.readInteger("");
return coordinates;
}
int getComputerPlayerMove(int boardSize) {
return ((random.nextInt(boardSize) + 1) * 10 + (random.nextInt(boardSize) + 1));
}
boolean gameOver(char[][] board, int boardSize) {
for (int row = 1; row <= boardSize; row++) {
for (int column = 1; column <= boardSize; column++) {
if (board[row][column] == ' ')
return false;
}
}
return true;
}
String getPlayersName() {
String playerName;
console.print("What is your name? ");
playerName = console.readLine();
return playerName;
}
boolean checkIfMoveIsValid(char[][] board, int move) {
int row;
int column;
boolean moveIsValid;
row = move % 10;
column = move / 10;
moveIsValid = false;
if (((row<=boardSize) &&(row>0)) && ((column<=boardSize) && (column>0))){
if (board[row][column] == ' ') {
moveIsValid = true;
}
}
return moveIsValid;
}
int getPlayerScore(char[][] board, int boardSize, char piece) {
int score;
score = 0;
for (int row = 1; row <= boardSize; row++) {
for (int column = 1; column <= boardSize; column++) {
if (board[row][column] == piece) {
score = score + 1;
}
}
}
return score;
}
boolean checkIfThereArePiecesToFlip(char[][] board, int boardSize, int startRow, int startColumn, int rowDirection, int columnDirection) {
int rowCount;
int columnCount;
boolean flipStillPossible;
boolean flipFound;
boolean opponentPieceFound;
rowCount = startRow + rowDirection;
columnCount = startColumn + columnDirection;
flipStillPossible = true;
flipFound = false;
opponentPieceFound = false;
while (rowCount <= boardSize && rowCount >= 1 && columnCount >= 1 && columnCount <= boardSize && flipStillPossible && !flipFound ) {
if (board[rowCount][columnCount] == ' ') {
flipStillPossible = false;
} else {
if (board[rowCount][columnCount] != board[startRow][startColumn]) {
opponentPieceFound = true;
} else {
if (board[rowCount][columnCount] == board[startRow][startColumn] && !opponentPieceFound) {
flipStillPossible = false;
} else {
flipFound = true;
}
}
}
rowCount = rowCount + rowDirection;
columnCount = columnCount + columnDirection;
}
return flipFound;
}
void flipOpponentPiecesInOneDirection(char[][] board, int boardSize, int startRow, int startColumn, int rowDirection, int columnDirection) {
int rowCount;
int columnCount;
boolean flipFound;
flipFound = checkIfThereArePiecesToFlip(board, boardSize, startRow, startColumn, rowDirection, columnDirection);
if (flipFound) {
rowCount = startRow + rowDirection;
columnCount = startColumn + columnDirection;
while (board[rowCount][columnCount] != ' ' && board[rowCount][columnCount] != board[startRow][startColumn]) {
if (board[rowCount][columnCount] == 'H') {
board[rowCount][columnCount] = 'C';
} else {
board[rowCount][columnCount] = 'H';
}
rowCount = rowCount + rowDirection;
columnCount = columnCount + columnDirection;
}
}
}
void makeMove(char[][] board, int boardSize, int move, boolean humanPlayersTurn) {
int row;
int column;
row = move % 10;
column = move / 10;
if (humanPlayersTurn) {
board[row][column] = 'H';
} else {
board[row][column] = 'C';
}
flipOpponentPiecesInOneDirection(board, boardSize, row, column, 1, 0);
flipOpponentPiecesInOneDirection(board, boardSize, row, column, -1, 0);
flipOpponentPiecesInOneDirection(board, boardSize, row, column, 0, 1);
flipOpponentPiecesInOneDirection(board, boardSize, row, column, 0, -1);
}
void printLine(int boardSize) {
console.print(" ");
for (int count = 1; count <= boardSize * 2 - 1; count++) {
console.print("_");
}
console.println();
}
void displayGameBoard(char[][] board, int boardSize) {
console.println();
console.print(" ");
for (int column = 1; column <= boardSize; column++)
{
console.print(" ");
console.print(column);
}
console.println();
printLine(boardSize);
for (int row = 1; row <= boardSize; row++) {
console.print(row);
console.print(" ");
for (int column = 1; column <= boardSize; column++) {
console.print("|");
console.print(board[row][column]);
}
console.println("|");
printLine(boardSize);
console.println();
}
}
void displayMenu() {
console.println("(p)lay game");
console.println("(e)nter name");
console.println("(c)hange board size");
console.println("(q)uit");
console.println();
}
char getMenuChoice(String playerName) {
char choice;
console.print(playerName + " enter the letter of your chosen option: ");
choice = console.readChar();
return choice;
}
void playGame(String playerName, int boardSize) {
char[][] board = new char[boardSize + 1][boardSize + 1];
boolean humanPlayersTurn;
int move;
int humanPlayerScore;
int computerPlayerScore;
boolean moveIsValid;
setUpGameBoard(board, boardSize);
humanPlayersTurn = false;
int NoOfMoves=0;
do {
humanPlayersTurn = !humanPlayersTurn;
displayGameBoard(board, boardSize);
moveIsValid = false;
do {
if (humanPlayersTurn) {
move = getHumanPlayerMove(playerName);
} else {
move = getComputerPlayerMove(boardSize);
}
moveIsValid = checkIfMoveIsValid(board, move);
} while (!moveIsValid);
if (!humanPlayersTurn) {
NoOfMoves++;
console.println("The number of moves completed so far: " +NoOfMoves);
console.print("Press the Enter key and the computer will make its move");
console.readLine("");
}
makeMove(board, boardSize, move, humanPlayersTurn);
console.println();
String answer = console.readLine("Do you want to save the board? (y/n)");
if (answer.equalsIgnoreCase("y")){
writeBoard(board, boardSize);
console.println("Saved!");
}
} while (!gameOver(board, boardSize));
displayGameBoard(board, boardSize);
humanPlayerScore = getPlayerScore(board, boardSize, 'H');
computerPlayerScore = getPlayerScore(board, boardSize, 'C');
if (humanPlayerScore > computerPlayerScore) {
console.println("Well done, " + playerName + ", you have won the game!");
}
else {
if (humanPlayerScore == computerPlayerScore) {
console.println("that was a draw!");
} else {
console.println("The computer has won the game!");
}
console.println();
}
}
void writeBoard(char[][] board, int boardSize) {
String filename = "myFile.txt";
String piece = null;
writeFile.openFile(filename);
for(int row=1; row<=boardSize; row++){
for (int column = 1; column <= boardSize; column++) {
piece= Character.toString(board [row][column]);
writeFile.writeToTextFile(piece);
}
}
writeFile.closeFile();
}
public static void main(String[] args) {
new Aaa();
}
}
This Section contains the errors:
void writeBoard(char[][] board, int boardSize) {
String filename = "myFile.txt";
String piece = null;
writeFile.openFile(filename);
for(int row=1; row<=boardSize; row++){
for (int column = 1; column <= boardSize; column++) {
piece= Character.toString(board [row][column]);
writeFile.writeToTextFile(piece);
}
}
writeFile.closeFile();
}
The problematic section contains a variable named writeFile which can not be resolved. No where in the class Aaa that you have shared, neither this variable has been declared nor initialized with an instance of its type. So the method void writeBoard(char[][] board, int boardSize) gives compilation error.
From the usage of this variable it is clear that it belongs to a class which has following instance methods:
1) openFile(String filename)
2) writeToTextFile(String piece)
3) closeFile()
Please search the class which has the above methods and on finding create an instance of that as the first statement inside the method void writeBoard(char[][] board, int boardSize). Hope it helps.

Determining whether or not a matrix is magic or not

I need to determine whether or not a magic square is magic or not. I need to compare the sum for every row and the sum with every column and then compare those with the sum of the diagonal and then with the sum of the other matrix.
I have calculated the sum for every row and for every column including with the two diagonals.
I need it to return true if the square is magic (all rows, cols, and diagonals have same sum false otherwise)
How would i set up this code?
public class MatrixService {
public static boolean isMagicSquare(int[][] arr) {
final int size = arr.length;
final int totalSize = size * size;
final int magicNumber = (size * size * (size * size + 1) / 2) / size;
int sumOfRow = 0, sumOfColoumns = 0, sumOfPrimaryDiagonal = 0, sumOfSecondaryDiagonal = 0;
boolean[] flag= new boolean[size * size];
for (int row = 0; row < size; row++) {
sumOfRow = 0;
sumOfColoumns = 0;
for (int col = 0; col < size; col++) {
if (arr[row][col] < 1 || arr[row][col] > totalSize) {
return false;
}
if (flag[arr[row][col] - 1] == true) {
return false;
}
flag[arr[row][col] - 1] = true;
sumOfRow += arr[row][col];
sumOfColoumns += arr[col][row];
}
sumOfPrimaryDiagonal += arr[row][row];
sumOfSecondaryDiagonal += arr[row][n-row-1];
if (sumOfRow != magicNumber || sumOfColoumns != magicNumber) {
return false;
}
if (sumOfPrimaryDiagonal != magicNumber || sumOfSecondaryDiagonal != magicNumber) {
return false;
}
return true;
}
public static void main(String []args){
int[][] a ={{4,9,2},
{3,5,7},
{8,1,6}};
System.out.println(isMagicSquare(a));
}
}

Categories