2D array board rules - java

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() );
}
}
}

Related

Spiral diamond -print pattern

I'm currently try to print below pattern in java,please help me in solving it.
Input: 3, abcdefghijklm
output:
c
bjd
aimke
hlf
g
I build diamond pattern with star, stuck in print values from array in spirally in diamond shape show above.
public static void rhombus() {
int n = 3;
int size = 2 * n - 1;
char[][] sol = new char[size][size];
for (int i = 0; i < size; i++) {
for (int j = 0; j < size; j++) {
sol[i][j] = ' ';
}
}
int i = size / 2;
int j = 0;
String s = "abcdefghijklmnop";
int len = s.length();
int in = 0;
int left = 0, top = 0, right = size - 1;
int bottom = size - 1;
boolean flag = false;
while (i != j) {
while (i >= top && !flag) {
sol[i][j] = s.charAt((in++) % len);
if (i == size / 2 && j == size / 2)
flag = true;
i--;
j++;
}
if (flag == true)
break;
i += 2;
top++;
left++;
while (j <= right && !flag) {
sol[i][j] = s.charAt((in++) % len);
i++;
j++;
}
j -= 2;
right--;
while (i <= bottom && !flag) {
sol[i][j] = s.charAt((in++) % len);
i++;
j--;
}
bottom--;
i -= 2;
while (j >= left && !flag) {
sol[i][j] = s.charAt((in++) % len);
i--;
j--;
}
j++;
}
sol[i][j] = s.charAt((in++) % len);
for (int a = 0; a < size; a++) {
for (int b = 0; b < size; b++) {
System.out.print(sol[a][b]);
}
System.out.println();
}
}

Ant colony optimization for TSP not getting the shortest path

I have implemented the algorithm according to this paper it's working well, but for certain tests, it doesn't get the shortest path,
here's the pseudo-code
Initialize
For t=1 to iteration number do
For k=1 to l do
Repeat until ant k has completed a tour
Select the city j to be visited next
With probability pij given by Eq. (1)
Calculate Lk
Update the trail levels according to Eqs. (2-4).
End
here's the code
import java.io.*;
import java.util.*;
import static java.lang.Math.*;
public class test2 {
private InputReader cin;
private PrintWriter cout;
double pheromones[][];
double distances[][];
double visibility[][];
static int n;
City[] city;
Ant[] ant;
int m;
int T;
double alpha = 1; // pheromone importance
double beta = 2; // visibility importance
double evaporation = 0.1;
double Q = 100.0;
static class City {
double x, y;
int id;
public City(double x, double y, int id) {
this.x = x;
this.y = y;
this.id = id;
}
}
static class Ant {
int whereAmI;
boolean[] visited;
double tourDistance;
LinkedList<Integer> citiesVisitedInOrder;
int cityEdges[][];
Ant(int whereAmI) {
this.whereAmI = whereAmI;
visited = new boolean[n + 1];
cityEdges = new int[n + 1][n + 1];
reset();
}
void reset() {
Arrays.fill(visited, false);
visited[whereAmI] = true;
for (int i = 1; i <= n; i++)
Arrays.fill(cityEdges[i], 0);
tourDistance = 0;
citiesVisitedInOrder = new LinkedList<>();
citiesVisitedInOrder.addLast(whereAmI);
}
}
//the actual algorithm iteration
/*
Initialize
For t=1 to iteration number do
For k=1 to l do
Repeat until ant k has completed a tour
Select the city j to be visited next
With probability pij given by Eq. (1)
Calculate Lk
Update the trail levels according to Eqs. (2-4).
End
*/
private void solve() {
n = cin.readInt();
initializeParameter();
//the main loop
for (int t = 0; t < T; t++) {
for (int i = 0; i < m; i++) {//for each ant
Ant current = ant[i];
for (int j = 0; j < n; j++) {//for each city
int currentAntsCity = current.whereAmI;
double highestProbability = 0;
int cityId = 1;
double sumNotiation = calculateSum(current.visited, currentAntsCity);
//traverse all non-visited cities and choose the best
boolean good = false;
for (int c = 1; c <= n; c++) {//remove the equal
if (!current.visited[c]) {
double prop = (pow(pheromones[currentAntsCity][c], alpha) * pow(visibility[currentAntsCity][c], beta))
/ sumNotiation;
if (prop >= highestProbability) {
highestProbability = prop;
cityId = c;
good = true;
}
}
}
if (good) {
current.tourDistance += distances[currentAntsCity][cityId];
current.cityEdges[currentAntsCity][cityId] = current.cityEdges[cityId][currentAntsCity] = 1;
current.citiesVisitedInOrder.addLast(cityId);
current.whereAmI = cityId;
current.visited[cityId] = true;
}
}//after n iteration i ant completes a tour
current.tourDistance += distances[current.citiesVisitedInOrder.getFirst()][current.citiesVisitedInOrder.getLast()];
}//update
for (int i = 1; i <= n; i++) {
for (int j = i + 1; j <= n; j++) {
double deltaPhermons = 0;
for (int a = 0; a < m; a++) {
if (ant[a].cityEdges[i][j] != 0) {
deltaPhermons += Q / ant[a].tourDistance;
}
}
pheromones[i][j] = pheromones[j][i] = pheromones[i][j] * evaporation + deltaPhermons;
pheromones[i][i] = 0;
}
}
if (t == T - 1)
break;
//reset everything
for (int i = 0; i < m; i++) {
ant[i].reset();
}
}
//get the best ant route
double minDistance = Double.MAX_VALUE;
LinkedList<Integer> minRout = new LinkedList<>();
for (Ant ant : ant) {
if (ant.tourDistance < minDistance) {
minDistance = ant.tourDistance;
minRout = ant.citiesVisitedInOrder;
}
}
cout.println(minDistance);
for (int element : minRout)
cout.print(element + " ");
}
private double calculateSum(boolean[] visited, int currentAntsCity) {
//traverse all non-visited cities
double ans = 0.0;
for (int c = 1; c <= n; c++) {
if (!visited[c]) {
ans +=
pow(pheromones[currentAntsCity][c], alpha) *
pow(visibility[currentAntsCity][c], beta);
}
}
return ans;
}
private void initializeParameter() {
m = 2 * n;
T = 4 * m;
city = new City[n + 1];
pheromones = new double[n + 1][n + 1];
distances = new double[n + 1][n + 1];
visibility = new double[n + 1][n + 1];
//read cities coordinates
for (int i = 1; i <= n; i++) {
city[i] = new City(cin.readDouble(), cin.readDouble(), i);
}
//initialize distances
for (int i = 1; i <= n; i++) {
for (int j = i + 1; j <= n; j++) {
distances[i][j] = distances[j][i] = sqrt(pow(city[i].x -
city[j].x, 2.0) + pow(city[i].y -
city[j].y, 2.0));
}
}
//initialize the pheromones
double pheromones0 = 1.0 / (double) n;
for (int i = 1; i <= n; i++) {
Arrays.fill(pheromones[i], pheromones0);
pheromones[i][i] = 0;
}
//initialize the visibility
for (int i = 1; i <= n; i++) {
for (int j = i + 1; j <= n; j++) {
visibility[i][j] = visibility[j][i] = 1.0 / distances[i][j];
}
}
//initialize the ants
ant = new Ant[m];
Random rand = new Random(); //instance of random class for
for (int i = 0; i < m; i++) {
int random_int = rand.nextInt(n) + 1;
ant[i] = new Ant(random_int);
}
}
public static void main(String args[]) {
new test2().run();
}
private void run() {
// cin = new InputReader(System.in);
// cout = new PrintWriter(System.out);
try {
cin = new InputReader(new FileInputStream("input.txt"));
cout = new PrintWriter(new FileOutputStream("output.txt"));
} catch (FileNotFoundException e) {
//System.out.println(e.toString());
}
solve();
cout.close();
}
//just for faster reading from a file
public static class InputReader {
private InputStream stream;
private byte[] buf = new byte[1024];
private int curChar, numChars;
public InputReader(InputStream stream) {
this.stream = stream;
}
public int read() {
if (numChars == -1)
throw new InputMismatchException();
if (curChar >= numChars) {
curChar = 0;
try {
numChars = stream.read(buf);
} catch (IOException e) {
throw new InputMismatchException();
}
if (numChars <= 0)
return -1;
}
return buf[curChar++];
}
public int readInt() {
int c = read();
while (isSpaceChar(c))
c = read();
int sgn = 1;
if (c == '-') {
sgn = -1;
c = read();
}
int res = 0;
do {
if (c < '0' || c > '9')
throw new InputMismatchException();
res *= 10;
res += c - '0';
c = read();
} while (!isSpaceChar(c));
return res * sgn;
}
public double readDouble() {
int c = read();
while (isSpaceChar(c))
c = read();
int sgn = 1;
if (c == '-') {
sgn = -1;
c = read();
}
double res = 0;
while (!isSpaceChar(c) && c != '.') {
if (c == 'e' || c == 'E')
return res * pow(10, readInt());
if (c < '0' || c > '9')
throw new InputMismatchException();
res *= 10;
res += c - '0';
c = read();
}
if (c == '.') {
c = read();
double m = 1;
while (!isSpaceChar(c)) {
if (c == 'e' || c == 'E')
return res * pow(10, readInt());
if (c < '0' || c > '9')
throw new InputMismatchException();
m /= 10;
res += (c - '0') * m;
c = read();
}
}
return res * sgn;
}
private boolean isSpaceChar(int c) {
return c == ' ' || c == '\n' || c == '\r' || c == '\t' || c == -1;
}
}
}
the test case
10
-15 89
-5 -49
-35 -18
7 49
-95 -68
85 -39
53 -1
69 -99
-74 8
-52 -35
the right answer:
615.11811789868988853
1 9 5 10 3 2 8 6 7 4
my coes's output:
685.2134200307595
5 9 10 3 2 8 6 7 4 1
as you can notice I am not getting the shortest path, I believe that the mistake is somewhere in the constant, and the probability comparing!
the formula I have implemented
and the update formulas
how can I improve the algorithm accuracy? or maybe there's something wrong in my implementation!
I found the solution, Changing the Update functions after each complete tour for all ants, fixed the problem:
#part 1
//the elaboration presses after a complete tour for all ants
for (int i = 1; i <= n; i++) {
for (int j = 1; j <= n; j++) {
pheromones[i][j] *= evaporation;
if (pheromones[i][j] < 1.0 / (double) n)//notice it the phermones can't be less than the starting value`
pheromones[i][j] = 1.0 / (double) n;
pheromones[i][i] = 0;
}
}
#part 2
//update the phermonses
for (int i = 0; i < m; i++) {
for (int j = i + 1; j <= n; j++) {
int from = ant[i].rout[0];
int to = ant[i].rout[n - 1];
pheromones[from][to] += Q / ant[i].tourDistance;
pheromones[to][from] = pheromones[from][to];
}
}
source HERE
strangely enough the algorithm can work without the elaboration presses i.e. #part1.
Anyway here's the complete code with little changes
import java.io.*;
import java.util.*;
import static java.lang.Math.*;
public class test2 {
private InputReader cin;
private PrintWriter cout;
double[][] arr;
double[][] pheromones;
double[][] distances;
double[][] visibility;
static int n;
Ant[] ant;
int m;
int T;
double alpha = 1; // pheromone importance
double beta = 3; // visibility importance
double evaporation = 0.9;
double Q = 40.0;
double pheromones0;
static class Ant {
int whereAmI;
boolean[] visited;
double tourDistance;
private int ctr; //counter for the cites thought which the ant pass
private int[] route;
Ant(int whereAmI) {
this.whereAmI = whereAmI;
reset();
}
void reset() {
ctr = 0;
route = new int[n];
visited = new boolean[n + 1];
visited[whereAmI] = true;
tourDistance = 0;
addCityToTheRoute(whereAmI);
}
void addCityToTheRoute(int cityId) {
route[ctr++] = cityId;
}
}
private void solve() {
n = cin.readInt();
initializeParameter();
double mi = Double.MAX_VALUE;
int[] cityRoute = new int[n];
//the main loop
for (int t = 0; t < T; t++) {
for (int i = 0; i < m; i++) {//for each ant
for (int j = 0; j < n; j++) {//for each city
double highestProbability = 0;
int cityId = 1;
double sumNotiation = calculateSum(ant[i].visited, ant[i].whereAmI);
//traverse all non-visited cities and choose the best
boolean good = false;
for (int c = 1; c <= n; c++) {//remove the equal
if (!ant[i].visited[c]) {
double prop = (pow(pheromones[ant[i].whereAmI][c], alpha) * pow(visibility[ant[i].whereAmI][c], beta))
/ sumNotiation;
if (prop >= highestProbability) {
highestProbability = prop;
cityId = c;
good = true;
}
}
}
if (good) {
ant[i].tourDistance += distances[ant[i].whereAmI][cityId];
ant[i].addCityToTheRoute(cityId);
ant[i].whereAmI = cityId;
ant[i].visited[cityId] = true;
}
}//after n iteration i ant completes a tour
ant[i].tourDistance += distances[ant[i].route[0]][ant[i].route[n - 1]];//add the distance from the last city to the first city
//while k ant finishes its tour take the best ant's route so far
if (ant[i].tourDistance < mi) {
mi = ant[i].tourDistance;
cityRoute = ant[i].route;
}
}
//update
//evaporatePheromones
for (int i = 1; i <= n; i++) {
for (int j = 1; j <= n; j++) {
pheromones[i][j] *= evaporation;
if (pheromones[i][j] < pheromones0)
pheromones[i][j] = pheromones0;
pheromones[i][i] = 0;
}
}
//updatePheromones
for (int i = 0; i < m; i++) {
for (int j = i + 1; j <= n; j++) {
int from = ant[i].route[0];
int to = ant[i].route[n - 1];
pheromones[from][to] += Q / ant[i].tourDistance;
pheromones[to][from] = pheromones[from][to];
}
}
if (t == T - 1)
break;
//reset everything
for (int i = 0; i < m; i++) {
ant[i].reset();
}
}
//print the route with the distance
cout.println(mi);
for (int element : cityRoute)
cout.print(element + " ");
}
private double calculateSum(boolean[] visited, int currentAntsCity) {
//traverse all non-visited cities
double ans = 0.0;
for (int c = 1; c <= n; c++) {
if (!visited[c]) {
ans +=
pow(pheromones[currentAntsCity][c], alpha) *
pow(visibility[currentAntsCity][c], beta);
}
}
return ans;
}
private void initializeParameter() {
m = 20 * n;
T = 20;
pheromones = new double[n + 1][n + 1];
distances = new double[n + 1][n + 1];
visibility = new double[n + 1][n + 1];
//read cities coordinates
arr = new double[n + 1][2];
for (int i = 1; i <= n; i++) {
double x = cin.readDouble();
double y = cin.readDouble();
arr[i][0] = x;
arr[i][1] = y;
}
//initialize distances
for (int i = 1; i <= n; i++) {
for (int j = i + 1; j <= n; j++) {
distances[i][j] = distances[j][i] = sqrt(pow(arr[i][0] -
arr[j][0], 2.0) + pow(arr[i][1] -
arr[j][1], 2.0));
}
}
//initialize the pheromones
pheromones0 = 1.0 / (double) n;
for (int i = 1; i <= n; i++) {
Arrays.fill(pheromones[i], pheromones0);
pheromones[i][i] = 0;
}
//initialize the visibility
for (int i = 1; i <= n; i++) {
for (int j = i + 1; j <= n; j++) {
visibility[i][j] = visibility[j][i] = 1.0 / distances[i][j];
}
}
//initialize the ants
ant = new Ant[m];
Random rand = new Random(); //instance of random class for
for (int i = 0; i < m; i++) {
int random_int = rand.nextInt(n) + 1;
ant[i] = new Ant(random_int);
}
}
public static void main(String args[]) {
new test2().run();
}
private void run() {
// cin = new InputReader(System.in);
// cout = new PrintWriter(System.out);
try {
cin = new InputReader(new FileInputStream("input.txt"));
cout = new PrintWriter(new FileOutputStream("output.txt"));
} catch (FileNotFoundException e) {
//System.out.println(e.toString());
}
solve();
cout.close();
}
//just for faster reading from a file
public static class InputReader {
private InputStream stream;
private byte[] buf = new byte[1024];
private int curChar, numChars;
public InputReader(InputStream stream) {
this.stream = stream;
}
public int read() {
if (numChars == -1)
throw new InputMismatchException();
if (curChar >= numChars) {
curChar = 0;
try {
numChars = stream.read(buf);
} catch (IOException e) {
throw new InputMismatchException();
}
if (numChars <= 0)
return -1;
}
return buf[curChar++];
}
public int readInt() {
int c = read();
while (isSpaceChar(c))
c = read();
int sgn = 1;
if (c == '-') {
sgn = -1;
c = read();
}
int res = 0;
do {
if (c < '0' || c > '9')
throw new InputMismatchException();
res *= 10;
res += c - '0';
c = read();
} while (!isSpaceChar(c));
return res * sgn;
}
public double readDouble() {
int c = read();
while (isSpaceChar(c))
c = read();
int sgn = 1;
if (c == '-') {
sgn = -1;
c = read();
}
double res = 0;
while (!isSpaceChar(c) && c != '.') {
if (c == 'e' || c == 'E')
return res * pow(10, readInt());
if (c < '0' || c > '9')
throw new InputMismatchException();
res *= 10;
res += c - '0';
c = read();
}
if (c == '.') {
c = read();
double m = 1;
while (!isSpaceChar(c)) {
if (c == 'e' || c == 'E')
return res * pow(10, readInt());
if (c < '0' || c > '9')
throw new InputMismatchException();
m /= 10;
res += (c - '0') * m;
c = read();
}
}
return res * sgn;
}
private boolean isSpaceChar(int c) {
return c == ' ' || c == '\n' || c == '\r' || c == '\t' || c == -1;
}
}
}

How to fix "Index 5 out of bounds for length 5" error in Java

I am working on solution for the CCC 2018 Robo Thieves Problem, it a simplified version of the original problem. My problem is that it will give me this "Index 5 out of bounds for length 5" when I executed my code and I'm not sure why it is happening. Half of my program executes and then this error occurs.
import java.util.*;
public class RoboThieves {
public static void main(String args[]) {
Scanner sc = new Scanner(System.in);
ArrayList<Integer> rowPos = new ArrayList<Integer>();
ArrayList<Integer> colPos = new ArrayList<Integer>();
int sRow = -1; // robot pos
int sCol = -1;
int dotCounter = 0;
int stepCounter = 0;
int rowSize = sc.nextInt();
int colSize = sc.nextInt();
char[][] factoryGrid = new char[rowSize][colSize];
for (int i = 0; i < rowSize; i++) {
String rowChars = sc.next().toUpperCase();
for (int j = 0; j < colSize; j++) {
factoryGrid[i][j] = rowChars.charAt(j);
}
}
// check to see if the grid was inputted properly (with square brackets)
/*
* for (char [] row: factoryGrid) { System.out.println(Arrays.toString(row)); }
*/
// check to see if the grid was inputted properly (as inputted)
for (int i = 0; i < rowSize; i++) {
for (int j = 0; j < colSize; j++) {
System.out.print(factoryGrid[i][j]);
}
System.out.println();
}
// locate dots and store their row and col in arraylists
for (int i = 0; i < rowSize; i++) {
for (int j = 0; j < colSize; j++) {
if (factoryGrid[i][j] == '.') {
rowPos.add(i);
colPos.add(j);
dotCounter++;
}
}
}
// print dot location to check
for (int i = 0; i < rowPos.size(); i++) {
System.out.println("Dot Position = " + "(" + rowPos.get(i) + "," + colPos.get(i) + ")");
}
// locate robot position
for (int i = 0; i < rowSize; i++) {
for (int j = 0; j < colSize; j++) {
if (factoryGrid[i][j] == 'S')
sRow = i;
sCol = j;
}
}
// print camera location to check
System.out.println("Camera Position = " + "(" + sRow + "," + sCol + ")");
//System.out.println(dotCounter); // test to see if counter works
char above = getAbove(factoryGrid, sRow, sCol);
char right = getRight(factoryGrid, sRow, sCol);
char below = getBelow(factoryGrid, sRow, sCol);
char left = getLeft(factoryGrid, sRow, sCol);
if (above == '.') {
boolean canMove = check360(factoryGrid, sRow, sCol);
// check if camera is around dot
if (canMove == true) {
// set robot position to dot position and old position to W
sRow = sRow - 1;
// sCol = sCol;
factoryGrid[sRow][sCol] = 'W';
dotCounter--;
stepCounter++;
} else {
// this is if there is a camera in the 360 radius of the open space
System.out.println("You cannot move to the space beside because there is a camera in your sightline!");
}
} else if (right == '.') {
boolean canMove = check360(factoryGrid, sRow, sCol);
// check if camera is around dot
if (canMove == true) {
// set robot position to dot position and old position to W
// sRow = sRow;
sCol = sCol + 1;
factoryGrid[sRow][sCol] = 'W';
dotCounter--;
stepCounter++;
} else {
// this is if there is a camera in the 360 radius of the open space
System.out.println("You cannot move to the space beside because there is a camera in your sightline!");
}
} else if (below == '.') {
boolean canMove = check360(factoryGrid, sRow, sCol);
// check if camera is around dot
if (canMove == true) {
// set robot position to dot position and old position to W
sRow = sRow + 1;
// sCol = sCol;
factoryGrid[sRow][sCol] = 'W';
dotCounter--;
stepCounter++;
} else {
// this is if there is a camera in the 360 radius of the open space
System.out.println("You cannot move to the space beside because there is a camera in your sightline!");
}
} else if (left == '.') {
boolean canMove = check360(factoryGrid, sRow, sCol);
// check if camera is around dot
if (canMove == true) {
// set robot position to dot position and old position to W
// sRow = sRow;
sCol = sCol - 1;
factoryGrid[sRow][sCol] = 'W';
dotCounter--;
stepCounter++;
} else {
// this is if there is a camera in the 360 radius of the open space
System.out.println("You cannot move to the space beside because there is a camera in your sightline!");
}
} else {
System.out.println(
"The robot cannot move to any spaces try inputting a factory layout that can produce an answer.");
} // end if above dot (yes)
System.out.println(stepCounter);
for (int i = 0; i < rowSize; i++) {
for (int j = 0; j < colSize; j++) {
System.out.print(factoryGrid[i][j]);
}
System.out.println();
}
} // end main method
public static char getLeft(char[][] factGrid, int cRow, int cCol) {
return factGrid[cRow][(cCol - 1)];
}
public static char getAbove(char[][] factGrid, int cRow, int cCol) {
return factGrid[(cRow - 1)][(cCol)];
}
public static char getBelow(char[][] factGrid, int cRow, int cCol) {
return factGrid[cRow + 1][cCol];
}
public static char getRight(char[][] factGrid, int cRow, int cCol) {
return factGrid[cRow][(cCol + 1)];
}
public static boolean check360(char[][] factGrid, int cRow, int cCol) {
boolean canMove = true;
char left = getLeft(factGrid, cRow, cCol);
char above = getAbove(factGrid, cRow, cCol);
char right = getRight(factGrid, cRow, cCol);
char below = getBelow(factGrid, cRow, cCol);
if (left == 'C' || above == 'C' || right == 'C' || below == 'C') {
canMove = false;
}
return canMove;
}
} // end main program
Upon first look, I expect that the issue may lie in your getLeft(), getAbove(), getRight(), and getBelow() methods.
In these methods, you give it a value for cRow and cCol and add or subtract 1. However, you need to make sure that the index you are querying does not exceed the size of the double array factGrid, or go below 0.
For example, in your getRight() method, you might try:
public static char getRight(char[][] factGrid, int cRow, int cCol) {
if(factGrid[0].length > (cCol + 1)) {
return factGrid[cRow][(cCol + 1)];
} else {
return '';
}
}

search a given word into a letter puzzle diagonally

I have a two-dimensional array filled with random letters. I have words to find in that array.
I have written a toString method that uses:
startX : The start X position of the String to be found
startY : The start Y position of the String to be found
endX : The end X position of the String to be found
endY : The end Y position of the String to be found
The code that I provide works horizontally and vertically but does not work for diagonals. How can I print words which are placed in the array diagonally?
#Override
public String toString() {
StringBuilder sb = new StringBuilder();
if (startX == endX) {
if (startY < endY) {
for (int i = startY; i <= endY; i++)
sb.append(i).append("x").append(startY).append(" ");
} else {
for (int i = endY; i <= startY; i++)
sb.append(i).append("x").append(startY).append(" ");
}
}
if (startY == endY) {
if (startX < endX) {
for (int i = startX; i <= endX; i++)
sb.append(i).append("x").append(startY).append(" ");
} else
for (int i = endX; i <= startX; i++)
sb.append(i).append("x").append(startY).append(" ");
}
if (startX > endX && startY > endY) {
int i = startX;
int j = startY;
while (i >= endX)
sb.append(i--).append("x").append(j--).append(" ");
} else if (startX > endX && startY < endY) {
int i = startX;
int j = startY;
while (i >= endX)
sb.append(i--).append("x").append(j++).append(" ");
} else if (startX < endX && startY > endY) {
int i = startX;
int j = startY;
while (i >= endX)
sb.append(i++).append("x").append(j--).append(" ");
} else if (startX < endX && startY < endY) {
int i = startX;
int j = startY;
while (i >= endX)
sb.append(i++).append("x").append(j++).append(" ");
}
return sb.toString();
}
I assume that what you are looking for is a way to find a word in a letter puzzle.
In such a case, I suggest you to store the puzzle on a 2D array and the word to find in a String. Then you need to check all the positions of the array that have the same character than the begining character of the String you are looking for (in the code I provide: findWord). Once you find a match, you need to check the rest of the characters of the string (in the code I provide: checkDirections). If the rest of the characters match then you have found the string, otherwise you need to check for the other directions or for the next appearance of the first letter of the string.
Next I provide the code:
package letterPuzzle;
import java.util.Random;
public class LetterPuzzle {
private static final String ALPHABET = "abcdefghijklmnopqrstuvwxyz";
private static final int[] DIRECTIONS_X = new int[] { 0, 0, 1, -1, 1, 1, -1, -1 };
private static final int[] DIRECTIONS_Y = new int[] { 1, -1, 0, 0, 1, -1, 1, -1 };
private static int N;
private static char[][] puzzle;
private static void initializePuzzle() {
Random r = new Random();
puzzle = new char[N][N];
for (int i = 0; i < N; ++i) {
for (int j = 0; j < N; ++j) {
puzzle[i][j] = ALPHABET.charAt(r.nextInt(ALPHABET.length()));
}
}
// Add the JAVA word in a location
if (N < 6) {
System.out.println("[ERRRO] Example needs N >= 6");
System.exit(1);
}
puzzle[2][3] = 'j';
puzzle[3][3] = 'a';
puzzle[4][3] = 'v';
puzzle[5][3] = 'a';
}
private static void printPuzzle() {
System.out.println("[DEBUG] Puzzle");
for (int i = 0; i < N; ++i) {
for (int j = 0; j < N; ++j) {
System.out.print(puzzle[i][j] + " ");
}
System.out.println("");
}
System.out.println("[DEBUG] End Puzzle");
}
private static boolean findWord(String word) {
for (int i = 0; i < N; ++i) {
for (int j = 0; j < N; ++j) {
// We check all the matrix but only try to match the word if the first letter matches
if (puzzle[i][j] == word.charAt(0)) {
if (checkDirections(i, j, word)) {
return true;
}
}
}
}
return false;
}
private static boolean checkDirections(int initX, int initY, String word) {
System.out.println("Searching " + word + " from (" + initX + ", " + initY + ")");
// Checks the different directions from (initX, initY) position
for (int dirIndex = 0; dirIndex < DIRECTIONS_X.length; ++dirIndex) {
System.out.println(" - Searching direction " + dirIndex);
boolean wordMatches = true;
// Checks all the characters in an specific direction
for (int charIndex = 0; charIndex < word.length() && wordMatches; ++charIndex) {
int x = initX + DIRECTIONS_X[dirIndex] * charIndex;
int y = initY + DIRECTIONS_Y[dirIndex] * charIndex;
System.out.println(" -- Checking position (" + x + ", " + y + ")");
if (x < 0 || y < 0 || x >= N || y >= N || puzzle[x][y] != word.charAt(charIndex)) {
System.out.println(" -- Not match");
wordMatches = false;
} else {
System.out.println(" -- Partial match");
}
}
// If the word matches we stop, otherwise we check other directions
if (wordMatches) {
return true;
}
}
return false;
}
public static void main(String[] args) {
// Check args
if (args.length != 2) {
System.err.println("[ERROR] Invalid usage");
System.err.println("[ERROR] main <puzzleSize> <wordToSearch>");
}
// Get args
N = Integer.valueOf(args[0]);
String word = args[1];
// Initialize puzzle (randomly)
initializePuzzle();
printPuzzle();
// Search word
boolean isPresent = findWord(word);
if (isPresent) {
System.out.println("Word found");
} else {
System.out.println("Word NOT found");
}
}
}
Notice that:
The puzzle matrix is randomly initialized and I hardcoded the word 'java' on the 2,3 -> 5,3 positions (this is just for the example but you should initialize the puzzle from the command line or from a file).
The ALPHABET variable is used only for the random generation.
The directions are stored on two 1D arrays to make the 8 directions programatically but you can unroll for the sake of clarity.
It is probably not best efficient code in terms of performance since you will double check lots of positions if the first character of the string appears several times. However it is still a feasible and easy solution.
If :
each word of yours is in a particular row and doesn't overflows to next row and
all words are consecutive
then you can do something like this:
#Override
public String toString()
{
StringBuilder string = new StringBuilder();
for(int c = startY; c<=endY; c++) {
string.append(startX).append("x").append(c).append(", ");
}
return string.toString();
}

reducing using instance variable to decrease the use of memory

I'm trying to do the Algorithm programming assignment of Princeton , and I met a problem about the memory test. The assignment requires us run the percolation program N times and find the medium of the result, and I write a percolationtest.java and for each time, I create an instance variable, it worked, but use too much memory, and the instructor suggests me to use local variable, but I don't know how. Can some one help me and give me some advice, I really appreciate it.
public class PercolationStats {
private int N, T, totalSum;
private double []fraction;
private int []count;
public PercolationStats(int N, int T) {
if (N <= 0 || T <= 0)
throw new IllegalArgumentException();
else {
this.N = N;
this.T = T;
count = new int [T];
totalSum = N*N;
fraction = new double[T];
int randomX, randomY;
for (int i = 0; i < T; i++) {
Percolation perc = new Percolation(N);
while (true) {
if (perc.percolates()) {
fraction[i] = (double) count[i]/totalSum;
break;
}
randomX = StdRandom.uniform(1, N+1);
randomY = StdRandom.uniform(1, N+1);
if (perc.isOpen(randomX, randomY)) continue;
else {
perc.open(randomX, randomY);
count[i]++;
}
}
}
}
} // perform T independent experiments on an N-by-N grid
public double mean() {
double totalFraction = 0;
for (int i = 0; i < T; i++) {
totalFraction += fraction[i];
}
return totalFraction/T;
} // sample mean of percolation threshold
public double stddev() {
double u = this.mean();
double sum = 0;
for (int i = 0; i < T; i++) {
sum += (fraction[i] - u) * (fraction[i] - u);
}
return Math.sqrt(sum/(T-1));
} // sample standard deviation of percolation threshold
public double confidenceLo() {
double u = this.mean();
double theta = this.stddev();
double sqrtT = Math.sqrt(T);
return u-1.96*theta/sqrtT;
} // low endpoint of 95% confidence interval
public double confidenceHi() {
double u = this.mean();
double theta = this.stddev();
double sqrtT = Math.sqrt(T);
return u+1.96*theta/sqrtT;
} // high endpoint of 95% confidence interval
public static void main(String[] args) {
int N = 200;
int T = 100;
if (args.length == 1) N = Integer.parseInt(args[0]);
else if (args.length == 2) {
N = Integer.parseInt(args[0]);
T = Integer.parseInt(args[1]); }
PercolationStats a = new PercolationStats(N, T);
System.out.print("mean = ");
System.out.println(a.mean());
System.out.print("stddev = ");
System.out.println(a.stddev());
System.out.print("95% confidence interval = ");
System.out.print(a.confidenceLo());
System.out.print(", ");
System.out.println(a.confidenceHi());
}
}
public class Percolation {
private boolean[][] site;
private WeightedQuickUnionUF uf;
private int N;
public Percolation(int N) {
if (N < 1)
throw new IllegalArgumentException();
else {
site = new boolean[N + 2][N + 2];
for (int j = 1; j <= N; j++) {
site[0][j] = true;
site[N + 1][j] = true;
}
uf = new WeightedQuickUnionUF((N + 2) * (N + 2));
for (int i = 1; i <= N; i++) {
uf.union(0, i);
}
this.N = N;
}
}
public void open(int i, int j) {
if (i > N || i < 1 || j > N || j < 1)
throw new IndexOutOfBoundsException();
else {
if (!site[i][j]) {
site[i][j] = true;
if (site[i - 1][j]) {
uf.union((N + 2) * (i - 1) + j, (N + 2) * i + j);
}
if (site[i + 1][j]) {
uf.union((N + 2) * i + j, (N + 2) * (i + 1) + j);
}
if (site[i][j + 1]) {
uf.union((N + 2) * i + (j + 1), (N + 2) * i + j);
}
if (site[i][j - 1]) {
uf.union((N + 2) * i + (j - 1), (N + 2) * i + j);
}
}
}
}
public boolean isOpen(int i, int j) {
if (i > N || i < 1 || j > N || j < 1)
throw new IndexOutOfBoundsException();
else
return site[i][j];
}
public boolean isFull(int i, int j) {
if (i > N || i < 1 || j > N || j < 1)
throw new IndexOutOfBoundsException();
else
return site[i][j] && (i == 1 || uf.connected((N + 2) * i + j, 0));
}
public boolean percolates() {
for (int i = 1; i <= N; i++) {
if (this.isFull(N, i)) {
return true;
}
}
return false;
}
public static void main(String[] args) {
}
}
Added meanValue instance variable to keep mean value and replaced it in multiple places where you used to call mean() method which was over head to calculate again and again. Also modified "int[] count" as local variable which you were not using outside the constructor. post your "Percolation" and "StdRandom" classes for more optimization of code. you can run this code and test, it should reduce the runtime than yours.
public class PercolationStats {
private int N, T, totalSum;
private double []fraction;
private double meanValue;
public PercolationStats(int N, int T) {
if (N <= 0 || T <= 0)
throw new IllegalArgumentException();
else {
this.N = N;
this.T = T;
int [] count = new int [T];
totalSum = N*N;
fraction = new double[T];
int randomX, randomY;
for (int i = 0; i < T; i++) {
Percolation perc = new Percolation(N);
while (true) {
if (perc.percolates()) {
fraction[i] = (double) count[i]/totalSum;
break;
}
randomX = StdRandom.uniform(1, N+1);
randomY = StdRandom.uniform(1, N+1);
if (perc.isOpen(randomX, randomY)) continue;
else {
perc.open(randomX, randomY);
count[i]++;
}
}
}
}
}
// perform T independent experiments on an N-by-N grid
public double mean() {
double totalFraction = 0;
for (int i = 0; i < T; i++) {
totalFraction += fraction[i];
}
meanValue = totalFraction/T;
return meanValue;
} // sample mean of percolation threshold
public double stddev() {
double u = meanValue;
double sum = 0;
for (int i = 0; i < T; i++) {
sum += (fraction[i] - u) * (fraction[i] - u);
}
return Math.sqrt(sum/(T-1));
} // sample standard deviation of percolation threshold
public double confidenceLo() {
double u = meanValue;
double theta = this.stddev();
double sqrtT = Math.sqrt(T);
return u-1.96*theta/sqrtT;
} // low endpoint of 95% confidence interval
public double confidenceHi() {
double u = meanValue;
double theta = this.stddev();
double sqrtT = Math.sqrt(T);
return u+1.96*theta/sqrtT;
} // high endpoint of 95% confidence interval
public static void main(String[] args) {
int N = 200;
int T = 100;
if (args.length == 1) N = Integer.parseInt(args[0]);
else if (args.length == 2) {
N = Integer.parseInt(args[0]);
T = Integer.parseInt(args[1]); }
PercolationStats a = new PercolationStats(N, T);
System.out.print("mean = ");
System.out.println(a.mean());
System.out.print("stddev = ");
System.out.println(a.stddev());
System.out.print("95% confidence interval = ");
System.out.print(a.confidenceLo());
System.out.print(", ");
System.out.println(a.confidenceHi());
}
}

Categories