Find elements surrounding an element in an array - java

I have a multidimensional array, I want to get the elements surrounding a particular element in that array.
For example if I have the following:
[[1,2,3,4,5,6]
[8,9,7,5,2,6]
[1,6,8,7,5,8]
[2,7,9,5,4,3]
[9,6,7,5,2,1]
[4,7,5,2,1,3]]
How do I find all the 8 elements around any of the above elements? And how do I take care of elements at the edges?
One way I figured out is, to write a 9 line code for this , which is obvious, but is there a better solution?

You can use 'direction array' in form
[[-1,-1], [-1,0],[1,0]..and so on]
And method which takes point coordinate and iterates through direction array -> add direction numbers to coordinates, check indexes are not out of bounds and collect results.
Something like this:
private static int[][] directions = new int[][]{{-1,-1}, {-1,0}, {-1,1}, {0,1}, {1,1}, {1,0}, {1,-1}, {0, -1}};
static List<Integer> getSurroundings(int[][] matrix, int x, int y){
List<Integer> res = new ArrayList<Integer>();
for (int[] direction : directions) {
int cx = x + direction[0];
int cy = y + direction[1];
if(cy >=0 && cy < matrix.length)
if(cx >= 0 && cx < matrix[cy].length)
res.add(matrix[cy][cx]);
}
return res;
}

For (i, j) ->
(i - 1, j - 1)
(i - 1, j)
(i - 1, j + 1)
(i, j - 1)
(i, j + 1)
(i + 1, j - 1)
(i + 1, j)
(i + 1, j + 1)
Now, at the edges, you can check for num % row == 0, then its at row edge...
and , num % col == 0 then its column edge..
Here's is how you can proceed: -
Given an index (i, j).. You can find elements in a rows adjacent to j for i - 1, then i, and then i + 1. (NOTE : - for index i you just have to access j - 1, and j + 1)
Subsequently you also can check for the row edge and column edge..
Here, you can look at the code below, how it can happen: -
// Array size
int row = 6;
int col = 6;
// Indices of concern
int i = 4;
int j = 5;
// To the left of current Column
int index = i - 1;
for (int k = -1; k < 2; k++) {
if (index % row > 0 && ((j + k) % col) > 0) {
System.out.println(arr[index][j + k]);
}
}
// In the current Column
index = i;
// Increment is 2 as we don't want (i, j)
for (int k = -1; k < 2; k = k + 2) {
if (index % row > 0 && ((j + k) % col) > 0) {
System.out.println(arr[index][j + k]);
}
}
// To the right of current Column
index = i + 1;
for (int k = -1; k < 2; k++) {
if (index % row > 0 && ((j + k) % col) > 0) {
System.out.println(arr[index][j + k]);
}
}
UPDATE : - The above code can further be simplified.. But I leave that task to you..
HINT: - You can reduce one for loop from there..

for (i = 0; i < array.length; i++) {
for (j = 0; j < array[i].length; j++) {
for (x = Math.max(0, i - 1); x <= Math.min(i + 1, array.length); x++) {
for (y = Math.max(0, j - 1); y <= Math.min(j + 1,
array[i].length); y++) {
if (x >= 0 && y >= 0 && x < array.length
&& y < array[i].length) {
if(x!=i || y!=j){
System.out.print(array[x][y] + " ");
}
}
}
}
System.out.println("\n");
}
}
Thanks to all the people who have answered, but i figured it out with the help of this post which i found just now, and above is the solution. thanks again :)

Base case is just to obtain neighbour elements by indexing shifting. For (i,j) it will be (i + 1, j), (i - 1, j), etc.
On the edges I use two approaches:
Modulo % operator to avoid IndexOutOfBounds exception, but it sometimes confuse with wrong elements indexation.
Wrap your matrix with one layer of default elements. It adds some extraspace for holding matrices, but makes your code more readable without catching exception, lot ifs and so on. This trick often used when representation maze as matrix.
Example: your default element is 0.
0 0 0 0 0 0
0 1 2 3 4 0
0 2 6 7 3 0
0 1 3 5 7 0
0 2 4 6 2 0
0 0 0 0 0 0
Note: do not forget iterate through actual array size, not extended.

This is my solution for your problem written in Ruby. Instead of calculating if element is at edge you could access elements "over" the edge and handle "nil" values or exceptions that happen there. Then remove "nil" values from final list. This solution is not as good as calculating if some "point" is over the edge or not.
big_map = [[1,2,3,4,5,6],
[8,9,7,5,2,6],
[1,6,8,7,5,8],
[2,7,9,5,4,3],
[9,6,7,5,2,1],
[4,7,5,2,1,3]]
# monkey patch classes to return nil.
[NilClass, Array].each do |klass|
klass.class_eval do
def [](index)
return nil if index < 0 or index > self.size rescue nil
self.fetch(index) rescue nil
end
end
end
class Array
# calculate near values and remove nils with #compact method.
def near(i,j)
[ self[i - 1][j - 1], self[i - 1][j - 0], self[i - 1][j + 1],
self[i - 0][j - 1], self[i - 0][j + 1],
self[i + 1][j - 1], self[i + 1][j - 0], self[i + 1][j + 1],
].compact
end
end
puts big_map.near(1,1).inspect
# => [1, 2, 3, 8, 7, 1, 6, 8]
puts big_map.near(0,0).inspect
# => [2, 8, 9]
puts big_map.near(5,5).inspect
# => [2, 1, 1]

I was working on he same problem and came up with a small optimized solution to find the surrounding numbers of any point in a 2D matrix, hope this helps, please comment if I can shorten the logic somehow
Code:-
import java.util.ArrayList;
public class test {
public static void main(String[] arg){
int[][] arr = {{1,2,3,4,5},{6,7,8,9,10},{11,12,13,14,15},{16,17,18,19,20},{21,22,23,24,25}};
//int[][] arr = {{width,2,3},{4,5,6},{7,8,9}};
ArrayList<Integer> al = new ArrayList<Integer>();
int x = 2, y = 2;
int width = 2; //change the value of width, according to the requirement
for(int i = 0; i < 5; i++){
for(int j = 0; j < 5; j++){
if( (i == (x-width) && ( (y+width) >= j && j >= (y-width))) || (i == (x+width) && ( (y+width) >= j && j >= (y-width))) || (j == (y-width) && ( (x+width) >= i && i >= (x-width))) || (j == (y+width) && ( (x+width) >= i && i >= (x-width))) ){
//if( x >= 0 && i < (i+width) && y >= 0 && j < (j+width))
{
al.add(arr[i][j]);
}
}
}
}
System.out.println(al);
}
}

You didnt mention if you want cyclical neighbours for edges or ignores cyclical neighbours. Assuming you want cyclical neighbours here is the code,
List<Integer> getNeighbours(int[][] mat, int x, int y){
List<Integer> ret = new ArrayList<Integer>();
int rows = mat.length;
int cols = mat[0].length;
for(int i=-1,i<=1;i++)
for(int j=-1;j<=1;j++)
if(i||j) ret = ret.add(mat[(x+i)%rows][(y+j)%cols]);
return ret;
}

(x-1, y-1) -> upper left
(x-1, y) -> left
(x-1, y+1) -> lower left
(x, y+1) -> up
(x, y) -> current position
(x, y-1) -> down
(x+1, y+1) -> upper right
(x+1, y) -> right
(x+1, y-1) -> lower right
You can use this as guide. Now all you need to do is add them in a try catch.
for( int x=0; x<arr.length; x++ ){
for(int y=0; y<arr[x].length; y++){
if( arr[x][y] == 8 ){
try{
System.out.println("Upper Left is: " + arr[x-1][y-1]);
}catch(ArrayIndexOutOfBoundsException e){
//do something
}
try{
System.out.println("Left is: " + arr[x-1][y]);
}catch(ArrayIndexOutOfBoundsException e){
//do something
}
//.....and others
}
}

Related

How to find specific neighbors in a two-dimensional array

I have an exercise where I have a 2D array in Java. I take user input, a String, that looks something like "F3 F7" and I mark the coordinates given on the array. Please see below picture.
2DArray
My problem is the fact that I need to check the neighbors of the input to make sure that future inputs do not touch (neither vertically, nor horizontally).
I found the below code in a post here, but I simply do not have the inspiration on how to implement it in order to check only for a specific set in the array.
for (i = 0; i < array.length; i++) {
for (j = 0; j < array[i].length; j++) {
for (x = Math.max(0, i - 1); x <= Math.min(i + 1, array.length); x++) {
for (y = Math.max(0, j - 1); y <= Math.min(j + 1,
array[i].length); y++) {
if (x >= 0 && y >= 0 && x < array.length
&& y < array[i].length) {
if(x!=i || y!=j){
System.out.print(array[x][y] + " ");
}
}
}
}
System.out.println("\n");
}
}

Need to smooth an image using matrix - Calculate sum of cells and compute average

I have matrix each cell contain number I need to calculate the cell and its neighbor cells and come out with an average of that cells.
Look at the code that I wrote.
public Matrix imageFilterAverage() {
for (int i=0; i < _array.length;i++)
for (int j=0; i < _array[i].length;j++){
_array[i][j] = (_array[i][j] + _array[i][j+1] + _array[i+1][j] + _array[i+1][j+1]) / 4;
}
return this;
}
My code return error on index issue when j+1 reach 3 it is out of bound because the cells are 0 1 2.
So for example, if I have a matrix like this
10 5 7 3
50 3 2 1
60 2 5 2
The results matrix should be like this.
17 12 3 3
21 16 2 3
28 20 2 2
I have posted the images one matrix source and matrix results
Thank you very much for your time and help.
/**
* Takes the given array and transforms each slot in the array as an average of the slots around it.
* #return an array with each where each slot in the array is "blurred" by the slots around it.
*/
public Matrix imageFilterAverage() {
int avgArray[][] = new int[_twoDiPicture.length][];
int numOfCellsAround = 0;
int cellsSum = 0;
for (int y = 0; y < _twoDiPicture.length; y++) {
avgArray[y] = new int[_twoDiPicture[y].length];
for (int x = 0; x < _twoDiPicture[y].length; x++) {
numOfCellsAround = 0;
cellsSum = 0;
numOfCellsAround += cellsAround(y, x);
cellsSum += cellsSum(y, x);
avgArray[y][x] = cellsSum / numOfCellsAround;
}
}
return new Matrix(avgArray);
}
/* a private method that deals with index out of bound exceptions. */
private boolean isInBounds(int y, int x) {
return y < _twoDiPicture.length && y >= 0 && x < _twoDiPicture[y].length && x >= 0;
}
/* A private methods that uses "isInBounds" to find how many cells are surrounding the target array. */
private int cellsAround(int y, int x) {
int cells = 1;
if (isInBounds(y + 1, x)) {
cells++;
}
if (isInBounds(y - 1, x)) {
cells++;
}
if (isInBounds(y, x + 1)) {
cells++;
}
if (isInBounds(y, x - 1)) {
cells++;
}
if (isInBounds(y - 1, x + 1)) {
cells++;
}
if (isInBounds(y - 1, x - 1)) {
cells++;
}
if (isInBounds(y + 1, x - 1)) {
cells++;
}
if (isInBounds(y + 1, x + 1)) {
cells++;
}
return cells;
}
/*A private method that returns the sum of all the adjacent cells around target cell. */
private int cellsSum(int y, int x) {
int sum = _twoDiPicture[y][x];
if (isInBounds(y + 1, x)) {
sum += _twoDiPicture[y + 1][x];
}
if (isInBounds(y - 1, x)) {
sum += _twoDiPicture[y - 1][x];
}
if (isInBounds(y, x + 1)) {
sum += _twoDiPicture[y][x + 1];
}
if (isInBounds(y, x - 1)) {
sum += _twoDiPicture[y][x - 1];
}
if (isInBounds(y - 1, x + 1)) {
sum += _twoDiPicture[y - 1][x + 1];
}
if (isInBounds(y - 1, x - 1)) {
sum += _twoDiPicture[y - 1][x - 1];
}
if (isInBounds(y + 1, x - 1)) {
sum += _twoDiPicture[y + 1][x - 1];
}
if (isInBounds(y + 1, x + 1)) {
sum += _twoDiPicture[y + 1][x + 1];
}
return sum;
}
I have an ugly solution which can be improved:
public static void main(String[] args) {
int[][] matrix = {{10, 5, 7, 3},
{50, 3, 2, 1},
{60, 2, 5, 2}};
int[][] average = new int[matrix.length][matrix[0].length];
for(int i = 0; i< matrix.length; i++){
for(int j = 0; j< matrix[0].length; j++){
int sum = 0;
int div = ((i==0 && j ==0) ||
(i==0 && j == matrix[0].length-1) ||
(i== matrix.length-1 && j ==0)||
(i== matrix.length-1 && j == matrix[0].length-1)) ? 4 :
((i==0 && j > 0) ||
(i>0 && j == 0) ||
(i== matrix.length-1 && j >0)||
(i> 0 && j == matrix[0].length-1))? 6 : 9;
for(int k = Math.max(i-1, 0); k <= Math.min(i+1, matrix.length-1); k++){
for(int t = Math.max(j-1, 0); t <= Math.min(j+1, matrix[0].length-1); t++){
sum += matrix[k][t];
}
}
average[i][j] = sum / div;
}
}
for(int[] r:average){
System.out.println(Arrays.toString(r));
}
}

Find Path with maximum value where T squares value can be doubled

Given a square matrix of size N*N, where each cell is associated with a specific cost. A path is defined as a specific sequence of cells which starts from top left cell move only right or down and ends on bottom right cell. We want to find the path with maximum value. Now to make things even more interesting: you also have T tokens. You can use the tokens to double the value on the current square. You can only use one token on any given square.
This is how I have solved the first part of the problem.
public static long pathWithMaxCost(int[][] n, int tokens) {
int[][] arr = new int[n.length][n[0].length];
// starting position
arr[arr.length - 1][0] = n[arr.length - 1][0];
// first column
for (int i = arr.length - 2; i >= 0; i--) {
arr[i][0] = arr[i + 1][0] + n[i][0];
}
// last row
for (int i = 1; i < arr[0].length; i++) {
arr[arr.length - 1][i] = arr[arr.length - 1][i - 1] + n[arr.length - 1][i];
}
for (int i = arr.length - 2; i >= 0; i--) {
for (int j = 1; j < arr[0].length; j++) {
arr[i][j] = Math.max(arr[i][j - 1], arr[i + 1][j]) + n[i][j];
}
}
return arr[0][arr[0].length - 1];
}
Now how can I handle the token part, T square values can be doubled?
static long pathWithMaxCostHash(int[][] n, int x, int y, int tokkens) {
if (x < 0 || x >= n.length || y < 0 || y >= n[0].length)
return -1;
String key = x + ":" + y + ":" + tokkens;
if (map.containsKey(key))
return map.get(key);
if(x==n.length-1&&y==0) {
if (tokkens > 0 && n[x][y] > 0) {
map.put(key,(long)n[n.length-1][0]*2);
return 2*n[n.length-1][0];
}
map.put(key,(long)n[n.length-1][0]);
return n[n.length-1][0];
}
//without picking double
long val = n[x][y]
+ Math.max(pathWithMaxCostHash(n, x + 1, y, tokkens), pathWithMaxCostHash(n, x, y - 1, tokkens));
//with picking double
if (tokkens > 0 && n[x][y] > 0) {
long val2 = 2 * n[x][y] + Math.max(pathWithMaxCostHash(n, x + 1, y, tokkens - 1),
pathWithMaxCostHash(n, x, y - 1, tokkens - 1));
val2 = Math.max(val, val2);
map.put(key, val2);
return val2;
}
map.put(key, val);
return val;
}
I'll give you a recursive approach, guess you can figure out dynamic programming based solution with this.
Initialize your dp 2d array with 0's
function: pathWithMaxCost(int x,int y,int tokens, int arr[][],int dp[][])
if(dp[x][y]) return dp[x][y];
few boundary conditions here...
return dp[x][y]=max(arr[x][y]+pathWithMaxCost(x,y+1,tokens,arr), arr[x][y]+pathWithMaxCost(x+1,y,tokens,arr), (arr[x][y]*2)+pathWithMaxCost(x,y+1,tokens-1,arr), (arr[x][y]*2)+pathWithMaxCost(x+1,y,tokens-1,arr))
Add another dimension for T, so the general check for a cell would be:
m[y][x][t] = max(
2 * n[y][x] + m[y-1][x][t-1],
2 * n[y][x] + m[y][x-1][t-1],
n[y][x] + m[y-1][x][t],
n[y][x] + m[y][x-1][t]
)
for all y,x,t
Let's consider the edge cases:
// first element
if x + y == 0:
m[y][x][0] = n[y][x]
m[y][x][1] = 2 * n[y][x]
m[y][x][t] = -Infinity, for t > 1
// first row
if y == 0:
m[y][x][t] = max(
2 * n[y][x] + m[y][x-1][t-1],
n[y][x] + m[y][x-1][t]
)
// first column
if x == 0:
m[y][x][t] = max(
2 * n[y][x] + m[y-1][x][t-1],
n[y][x] + m[y-1][x][t]
)

Recursive function g(n) [duplicate]

This question already has answers here:
Algorithm to efficiently determine the [n][n] element in a matrix
(6 answers)
Closed 7 years ago.
I have a function g(n) which can be given by g(n)=f(n,n) . This is defined recursively by
f(i, j) = 1/3
(f(iāˆ’1, j) + f(iāˆ’1, j āˆ’1) + f(i, j āˆ’1))
with f(0,0) = 0; f(i,0) = 1,i > 0; f(0, j) = 1, j > 0
I have written a java program to compute this for values from 10-15. The first couple of values are processed quickly but towards the end of values the program becomes very slow and takes a long time to process the result. Is there a problem with my code or is it just a lengthy calculation?
public class javaapplication4 {
private static double f(double i, double j) {
if (i == 0.0 && j == 0.0) return 0.0;
if (i == 0.0 || j == 0.0) return 1.0;
return (f(i - 1, j) + f(i - 1, j - 1) + f(i, j - 1));
}
private static double g(double n) {
return f(n, n);
}
public static void main (String[] args) {
for (int n = 10; n < 16; n ++) {
System.out.println("g(" + (int) n + "): " + g(n));
}
}
}
First of all, you seem to have forgotten a 1.0 / 3 in this line:
return (f(i - 1, j) + f(i - 1, j - 1) + f(i, j - 1));
Second, your program is slow because the same values get computed multiple times. For example, f(i - 1, j) will call f(i - 1, j - 1), which is also called from f(i, j).
To solve this, either compute your recurrence relation in a matrix:
f(0,0) = 0; f(i,0) = 1,i > 0; f(0, j) = 1, j > 0
for i = 1 to n:
for j = 1 to n:
f[i, j] = 0.33*(f[i - 1, j] + f[i, j - 1] + f[i - 1, j - 1])
Or keep your recursive implementation, but use memoization to speed it up:
A memoized function "remembers" the results corresponding to some set of specific inputs. Subsequent calls with remembered inputs return the remembered result rather than recalculating it, thus eliminating the primary cost of a call with given parameters from all but the first call made to the function with those parameters.
Basically, you can still use a matrix to store results in, and do something like this:
private static double f(double i, double j) { // make i and j ints, they do not need to be doubles here.
if (i == 0.0 && j == 0.0) return 0.0;
if (i == 0.0 || j == 0.0) return 1.0;
if (storageMatrix[i, j] != -1) {
return storageMatrix[i, j];
}
storageMatrix[i, j] = (1.0 / 3) * (f(i - 1, j) + f(i - 1, j - 1) + f(i, j - 1));
return storageMatrix[i, j];
}
You can optimize things even further by noticing that if you implement the iterative solution I gave pseudocode for above, you only ever use the current and previous rows of your matrix. So you can just use two arrays of length n instead of a square n x n matrix to compute your function.
This is easy to speed up with memoization. Don't throw away the values that you've worked so hard to calculate.
Here's my output:
"C:\Program Files\Java\jdk1.7.0_45\bin\java" -Didea.launcher.port=7534 "-Didea.launcher.bin.path=C:\Program Files (x86)\JetBrains\IntelliJ IDEA 14.0.1\bin" -Dfile.encoding=UTF-8 -classpath "C:\Program Files\Java\jdk1.7.0_45\jre\lib\charsets.jar;C:\Program Files\Java\jdk1.7.0_45\jre\lib\deploy.jar;C:\Program Files\Java\jdk1.7.0_45\jre\lib\javaws.jar;C:\Program Files\Java\jdk1.7.0_45\jre\lib\jce.jar;C:\Program Files\Java\jdk1.7.0_45\jre\lib\jfr.jar;C:\Program Files\Java\jdk1.7.0_45\jre\lib\jfxrt.jar;C:\Program Files\Java\jdk1.7.0_45\jre\lib\jsse.jar;C:\Program Files\Java\jdk1.7.0_45\jre\lib\management-agent.jar;C:\Program Files\Java\jdk1.7.0_45\jre\lib\plugin.jar;C:\Program Files\Java\jdk1.7.0_45\jre\lib\resources.jar;C:\Program Files\Java\jdk1.7.0_45\jre\lib\rt.jar;C:\Program Files\Java\jdk1.7.0_45\jre\lib\ext\access-bridge-64.jar;C:\Program Files\Java\jdk1.7.0_45\jre\lib\ext\dnsns.jar;C:\Program Files\Java\jdk1.7.0_45\jre\lib\ext\jaccess.jar;C:\Program Files\Java\jdk1.7.0_45\jre\lib\ext\localedata.jar;C:\Program Files\Java\jdk1.7.0_45\jre\lib\ext\sunec.jar;C:\Program Files\Java\jdk1.7.0_45\jre\lib\ext\sunjce_provider.jar;C:\Program Files\Java\jdk1.7.0_45\jre\lib\ext\sunmscapi.jar;C:\Program Files\Java\jdk1.7.0_45\jre\lib\ext\zipfs.jar;F:\Projects\Java\stack-overflow\out\production\stack-overflow;F:\Projects\Java\stack-overflow\lib\jxl.jar;F:\Projects\Java\stack-overflow\lib\jdom.jar;F:\Projects\Java\stack-overflow\lib\Jama-1.0.2.jar;F:\Projects\Java\stack-overflow\lib\dom4j-1.6.1.jar;F:\Projects\Java\stack-overflow\lib\commons-io-2.3.jar;F:\Projects\Java\stack-overflow\lib\aopalliance-1.0.jar;F:\Projects\Java\stack-overflow\lib\sqlitejdbc-v056.jar;F:\Projects\Java\stack-overflow\lib\jackson-xc-1.6.2.jar;F:\Projects\Java\stack-overflow\lib\commons-lang3-3.1.jar;F:\Projects\Java\stack-overflow\lib\commons-math3-3.3.jar;F:\Projects\Java\stack-overflow\lib\jackson-all-1.6.2.jar;F:\Projects\Java\stack-overflow\lib\StackWrap4J-1.0.1.jar;F:\Projects\Java\stack-overflow\lib\jackson-jaxrs-1.6.2.jar;F:\Projects\Java\stack-overflow\lib\jackson-smile-1.6.2.jar;F:\Projects\Java\stack-overflow\lib\jackson-mrbean-1.6.2.jar;F:\Projects\Java\stack-overflow\lib\jackson-core-asl-1.6.2.jar;F:\Projects\Java\stack-overflow\lib\jackson-core-lgpl-1.6.2.jar;F:\Projects\Java\stack-overflow\lib\jackson-mapper-asl-1.6.2.jar;F:\Projects\Java\stack-overflow\lib\postgresql-8.1-405.jdbc3.jar;F:\Projects\Java\stack-overflow\lib\jackson-mapper-lgpl-1.6.2.jar;F:\Projects\Java\stack-overflow\lib\mysql-connector-java-5.1.18-bin.jar;F:\Projects\Java\stack-overflow\lib\org.springframework.aop-3.1.0.RC2.jar;F:\Projects\Java\stack-overflow\lib\org.springframework.asm-3.1.0.RC2.jar;F:\Projects\Java\stack-overflow\lib\org.springframework.jms-3.1.0.RC2.jar;F:\Projects\Java\stack-overflow\lib\org.springframework.orm-3.1.0.RC2.jar;F:\Projects\Java\stack-overflow\lib\org.springframework.oxm-3.1.0.RC2.jar;F:\Projects\Java\stack-overflow\lib\org.springframework.web-3.1.0.RC2.jar;F:\Projects\Java\stack-overflow\lib\org.springframework.core-3.1.0.RC2.jar;F:\Projects\Java\stack-overflow\lib\org.springframework.jdbc-3.1.0.RC2.jar;F:\Projects\Java\stack-overflow\lib\org.springframework.beans-3.1.0.RC2.jar;F:\Projects\Java\stack-overflow\lib\org.springframework.aspects-3.1.0.RC2.jar;F:\Projects\Java\stack-overflow\lib\org.springframework.context-3.1.0.RC2.jar;F:\Projects\Java\stack-overflow\lib\org.springframework.expression-3.1.0.RC2.jar;F:\Projects\Java\stack-overflow\lib\org.springframework.instrument-3.1.0.RC2.jar;F:\Projects\Java\stack-overflow\lib\org.springframework.web.struts-3.1.0.RC2.jar;F:\Projects\Java\stack-overflow\lib\org.springframework.transaction-3.1.0.RC2.jar;F:\Projects\Java\stack-overflow\lib\org.springframework.web.portlet-3.1.0.RC2.jar;F:\Projects\Java\stack-overflow\lib\org.springframework.web.servlet-3.1.0.RC2.jar;F:\Projects\Java\stack-overflow\lib\org.springframework.context.support-3.1.0.RC2.jar;F:\Projects\Java\stack-overflow\lib\org.springframework.instrument.tomcat-3.1.0.RC2.jar;F:\Projects\Java\stack-overflow\test-lib\junit-4.10.jar;F:\Projects\Java\stack-overflow\test-lib\org.springframework.test-3.1.0.RC2.jar;C:\Program Files (x86)\JetBrains\IntelliJ IDEA 14.0.1\lib\idea_rt.jar" com.intellij.rt.execution.application.AppMain cruft.RecursionExample
n: 0 g(n): 0.00000015.5 +
n: 1 g(n): 0.66666715.5 +
n: 2 g(n): 0.81481515.5 +
n: 3 g(n): 0.86419815.5 +
n: 4 g(n): 0.88797415.5 +
n: 5 g(n): 0.90240315.5 +
n: 6 g(n): 0.91236115.5 +
n: 7 g(n): 0.91977515.5 +
n: 8 g(n): 0.92557415.5 +
n: 9 g(n): 0.93027315.5 +
n: 10 g(n): 0.93418015.5 +
n: 11 g(n): 0.93749715.5 +
n: 12 g(n): 0.94035715.5 +
n: 13 g(n): 0.94285715.5 +
n: 14 g(n): 0.94506715.5 +
n: 15 g(n): 0.94703915.5 +
total wall time: 11 ms
Process finished with exit code 0
Runs in 11 ms for me.
package cruft;
import java.util.HashMap;
import java.util.Map;
/**
* RecursionExample description here
* #author Michael
* #link https://stackoverflow.com/questions/28933093/recursive-function-gn
* #since 3/8/2015 7:28 PM
*/
public class RecursionExample {
private static final Map<String, Double> memo = new HashMap<String, Double>();
private static double f(int i, int j) {
if (i < 0) throw new IllegalArgumentException("i cannot be negative");
if (j < 0) throw new IllegalArgumentException("j cannot be negative");
if (i == 0 && j == 0) return 0.0;
if (i == 0 || j == 0) return 1.0;
String key = Integer.toString(i) + "~" + Integer.toString(j);
if (memo.containsKey(key)) {
return memo.get(key);
} else {
double value = (f(i-1, j) + f(i-1, j-1) + f(i, j-1))/3.0;
memo.put(key, value);
return value;
}
}
private static double g(int n) {
return f(n, n);
}
public static void main (String[] args)
{
long begTime = System.currentTimeMillis();
try {
for (int n = 0; n < 16; n ++) {
System.out.println(String.format("n: %d g(n): %f15.5 + ", n, g(n)));
}
} finally {
long endTime = System.currentTimeMillis();
System.out.println(String.format("total wall time: %10d ms", (endTime-begTime)));
}
}
}
You have forgotten to divide your result by 3, otherwise your code is fine. You can speed it up for an arbitrary amount of values by adding an array that previous results are saved in, I did it like this:
public class Recursivity {
static double[][] results = new double[20][20];
private static double f(int i, int j) {
if (i == 0 && j == 0) {
return 0.0;
}
if (i == 0 || j == 0) {
return 1.0;
}
if (results[i][j] != -1.0) {
return (results[i][j]);
}
double output = (f(i - 1, j) + (f(i - 1, j - 1) + (f(i, j - 1))));
results[i][j] = output;
return output;
}
private static double g(int n) {
return f(n, n);
}
public static void main(String[] args) {
for (int i = 0; i < results.length; i++) {
for (int j = 0; j < results.length; j++) {
results[i][j] = -1.0;
}
}
for (int n = 10; n < 16; n++) {
System.out.println("g(" + (int) n + "): " + g(n));
}
}
}
This runs a lot faster, but it requires you to have Integers as input for f. I don't know if there is any kind of list you can index by non-discrete numbers, but it should be possible for a finite amount of them.
To supplement the answer above, suppose a system can compute f(k, k) in time t. To compute f(k+1,k+1), it's going to have to compute f(k, k+1), f(k, k) and f(k+1, k). That's going to take about 3 times as long. In other words, for any given k, the time to compute f(k+1,k+1) is triple that of f(k,k). This gets out of hand fast: computing f(15, 15) is going to take 243 times as long as computing f(10, 10)!
your code is good but you just forgot to add 1/3 to here ;
return (f(i - 1, j) + f(i - 1, j - 1) + f(i, j - 1));
so it should be like this ;
return (f(i - 1, j)*0.33 + f(i - 1, j - 1) + f(i, j - 1));
or
return (f(i - 1, j)*(1/3) + f(i - 1, j - 1) + f(i, j - 1));

Android Minesweeper algorithm

I'm developing a game "Minesweeper" for Andoid on Java and I have a problem when opening the cells. How to make sure that I click on the cell opened adjacent empty cells? (How it is done in Miner for Windows).
Introduction: I have an array which i receive from bluetooth socket stream. Array like this :
1 9 1 0
1 1 1 0
0 0 0 0
0 0 0 0
9-is a mine
0-is blank cell
1-nearest mines count
After that i calculate game field
array = Model.getGameField();
int size = array.length;
for (int i = 0; i < size; i++)
for (int j = 0; j < size; j++)
{
((TableRow) table.getChildAt(i)).getChildAt(j).setTag(array[i][j] + "");
}
OnClick function :
if (iWantToSetFlag == 0)
{
tmpBtn = ((Button) v);
if (!(tmpBtn.getTag().equals("9")))
{
OpenButtons(tmpBtn.getId() / 10, tmpBtn.getId() % 10);
recreateTable();
}
else
startLose();
}
else
{
if (((Button) v).getText().equals("M"))
((Button) v).setText("");
else
((Button) v).setText("M");
}
I have a function
private void OpenButtons(int x, int y)
{
array[x][y] = -1;
for (int k = -1; k < 2; k++)
{
for (int k1 = 1; k1 >= -1; k1--)
{
if (x + k >= 0 && x + k < array.length && y - k1 >= 0 && y - k1 < array[x + k].length)
if (array[x + k][y - k1] == 0)
OpenButtons(x + k, y - k1);
}
}
}
which recursively open cells but i have a StackOverFlow error. Help please.
You should be calling your recursion with changed parameters:
if (array[x + k][y - k1] == 0)
OpenButtons(x + k, y - k1);
And of course, as has been mentioned in the comments of the question, you should check for the array bounds yourself instead of just ignoring the exceptions:
if (x + k >= 0 && x + k < array.length &&
y - k1 >= 0 && y - k1 < array[x + k].length) { ...
put before your other if-clause will only check fields which actually exist. Ridding you of your malicious empty try-catch.
Since the recursive algorithm will still cause a StackOverflowException for large fields, an iterative algorithm might be better suited here.
private void OpenButtons(int x, int y) {
Queue<Point> toOpen = new LinkedBlockingQueue<>();
toOpen.add(new Point(x, y));
array[x][y] = -1;
while (!toOpen.isEmpty()) {
Point p = toOpen.poll();
x = p.x;
y = p.y;
for (int k = -1; k < 2; k++) {
for (int k1 = 1; k1 >= -1; k1--) {
if (x + k >= 0 && x + k < array.length && y - k1 >= 0
&& y - k1 < array[x + k].length)
if (array[x + k][y - k1] == 0) {
array[x + k][y - k1] = -1;
toOpen.add(new Point(x + k, y - k1));
}
}
}
}
}

Categories