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));
}
}
I am supposed to write a method that scrambles a word, switching two letters in a word that is not the first or last character.
I've initialized i and j as random integers between positions 1 and str.length() -1. Is there a reason why this loop would not print the scrambled version of a word?
char[] chararray = word.toCharArray();
int i = (int) (Math.random() * ((word.length()-2) - (1)) + 1);
int j = (int) (Math.random() * ((word.length()-2) - (1)) + 1);
for (int x = 0; x < word.length(); x++)
{
if (x == i)
{
chararray[x] = word.charAt(i);
}
else if (x == j)
{
chararray[x] = word.charAt(j);
}
}
word = new String (chararray);
System.out.println(word);
When I input tofu it would reprint tofu. I'd like to input "tofu" and have it output "tfou".
I think you would be looking for the following
for (int x = 0; x < word.length(); x++)
{
if (x == i)
{
chararray[x] = word.charAt(j);
}
else if (x == j)
{
chararray[x] = word.charAt(i);
}
}
Interchange the i and j values in the if and else blocks.
when x equals i you are assigning the same value back in the chararray, hence you are getting the same value. But your intention is to interchange the character in i and j positions I hope.
And one more thing, make sure i never equals to j
Your logic seems to be wrong,
if (x == i)
{
chararray[x] = word.charAt(i);
}
The above will just point to same index, both x and i points to same, you need to interchange the indexes.
Below code
public static void main(String args[]) {
String word = "ankur";
char[] chararray = word.toCharArray();
int i = (int) (Math.random() * ((word.length() - 2) - (1)) + 1);
int j = (int) (Math.random() * ((word.length() - 2) - (1)) + 1);
System.out.println(i + " and " + j);
for (int x = 0 ; x < word.length() ; x++) {
if (x == i) {
chararray[x] = word.charAt(j);
} else if (x == j) {
chararray[x] = word.charAt(i);
}
}
word = new String(chararray);
System.out.println(word);
}
output
2 and 1
aknur
Start with an character array.
Use a random generator to get 2 integers between 0 (inclusive) and length of character array (exclusive).
If i != j, swap them. (No point swapping a character with itself)
public class QuickTester {
public static void main(String[] args) {
Random rand = new Random();
char[] charArr = "elephant".toCharArray();
// Using charArr.length - 2 + 1 to exclude first and last
int i = rand.nextInt(charArr.length - 2) + 1;
int j = rand.nextInt(charArr.length - 2) + 1;
if (i != j) {
System.out.printf("Going to swap %c at position %d "
+ "with %c at position %d%n", charArr[i], i, charArr[j], j);
char temp = charArr[i];
charArr[i] = charArr[j];
charArr[j] = temp;
System.out.println("\nResult: " + new String(charArr));
}
}
}
Result:
Going to swap t at position 7 with e at position 2
Result: eltphane
Update:
Changed from charArr.length to charArr.length - 2 + 1 to exclude first and last character.
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));
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
}
}