How to check which points are in a circle? - java

Okay so say there is a grid, which I have stored as a 2 dimensional array, that is 10 by 10.
int[][] grid = new int[10][10];
The origin of the grid is at the bottom left, like a normal x y plane, and there is a circle of radius 5 in the centre of the grid at (5,5), like so:
I want to go through this array and basically check which points are inside the circle, but I do not want to loop through the entire array. By default, every point on a corner is not going to be in the circle, so I would want to ignore those, and similarly the points that are close to the corner, etc.
Just the points that are in the circle. I have a much bigger grid and looping through unnecessary stuff that I already know isn't in the circle would waste time. Is there a way to do this? Because, given that I already know the radius and centre of the circle, there should be a nice easy way to go through those points which are in the circle and change them from 0 to -1, for example.
Otherwise, I would stand to lose 100 - 25π ≈ 21.46% time.
BETTER CLARITY: I already know that I can bound the circle with a square, and loop through the points in that square and check each points distance from the centre of the circle (x^2 + y^2 < r^2), but this is what I am trying to avoid, due to the constant overhead every time of checking the bits that aren't in the circle, when I know they are not in the circle beforehand.

Ok, after a long discussion, here is the solution. You scan across one axis of a quarter slice, compute the extension to which you need to fill that quarter outwards and then fill all 4 quarters at once.
int n = 1000;
// you will need to think yourself about the odd number or elements
int r = n / 2;
int r2 = r * r;
Putting (0,0) at the centre of the matrix in both cases, the optimized solutions can look like this:
int[][] grid0 = new int[n][n];
for (int i = 0; i < r; i++) {
double m = Math.sqrt(r2 - i * i);
for (int j = 0; j < m; j++) {
grid0[r + i][r + j] = 1;
grid0[r + i][r - j] = 1;
grid0[r - i][r + j] = 1;
grid0[r - i][r - j] = 1;
}
}
As commented elsewhere, the extension of filling the circle is computed in O(n).
Here is the straightforward validation:
int[][] grid1 = new int[n][n];
// you will need to think yourself about the even number
for (int i = 0; i < n; i++) {
for (int j = 0; j < n; j++) {
if ((i - r) * (i - r) + (j - r) * (j - r) < r2) {
grid1[i][j] = 1;
}
}
}
Both produce the same number of filled points.
Time measurements over 10000 executions (with array initialization outside of the time loop):
the optimized one 6.0s
the exhaustive one 15.6s
So, I do admit there is a difference, an astonishing one. Although for a fair comparison, the latter snippet should also be using a quarter slice of the circle.
One can speed up the optimized solution even further using some sort of memory copy routine to fill the values from 0 to the computed point rather than a plain loop, but that is beyond the scope.

Related

How can you find the max rectangular area in histogram recursively?

I need to come up with a recursive solution for the "Maximum rectangular area in a histogram" problem. For those not familiar with it, here´s an explanation:
A histogram is a display of statistical information that uses rectangles to show the frequency of data items. These rectangles are usually vertical.
In the histogram, all the bars are usually different sizes. In the problem, you have to find the maximum rectangular area in the histogram. For example, if the sizes are [4,1,4,5,6] the maximum area is 12 because we take the last 3 bars [4,5,6], take the shortest bar [4], and apply the rectangular area formula (4x3=12).
The only requirements are:
-It has to be done in java.
-Stacks can´t be used.
-It has to be recursive.
In case it helps, i have a non-recursive solution:
public static int MaxHistograma(int[] histograma) {
if (histograma.length == 1) {
return histograma[0];
}
int res = 0;
for (int i = 0; i < histograma.length - 1; i++) {
int min = histograma[i];
for (int j = i + 1; j < histograma.length; j++) {
min = Math.min(min, histograma[j]);
res = Math.max(histograma[j], Math.max(res, min * (j - i + 1)));
res = Math.max(res, histograma[i]);
}
}
return res;
}
If you start with the base case of a histogram with 1 column then the largest area is simply equal to height of the column.
When you add a include the 2nd column, the area may be either be
1) Equal to the max area from the previous histogram
2) Equal to the height of this 2nd column
3) Equal to the area of the new rectangle which has been formed horizontally
When you look at the third column, it's the same. It's either the max area from the previous histogram (2 cols), the height of the new column (red), or the area of the horizontal rectangle (purple).
Here is a code skeleton to achieve this
private int getLargestArea(int[] histogram)
{
if (histogram.length > 1)
{
int horizontalRectangleArea = 0; //TODO
int lastColumnHeight = 0; //TODO
return Math.max(
Math.max(horizontalRectangleArea, lastColumnHeight),
getLargestArea(Arrays.copyOf(histogram, histogram.length - 1)) //copy the array, subtracting 1 column
);
}
else
{
return histogram[0]; // height of single column
}
}

How to Implementating This EgienVector Code Python Code into Java

I have found right result Of Algorithm Can I implementating this code into Java?
import numpy as np
from scipy.linalg import eig
transition_mat = np.matrix([
[0.8, 0.15, 0.05],\
[0.075, 0.85, 0.075],\
[0.05, 0.15,0.8 ]])
S, U = eig(transition_mat.T)
stationary = np.array(U[:, np.where(np.abs(S - 1.) < 1e-8)[0][0]].flat)
print stationary
print np.sum(stationary)
stationary = stationary / np.sum(stationary)
print stationary
I Was Implementated this code in Java but Result is wrong
Matrix A = new Matrix(transition);
A = A.transpose();
Matrix x = new Matrix(N, 1, 1.0 / N); // initial guess for eigenvector
for (int i = 0; i < 50; i++) {
x = A.times(x);
x = x.times(1.0 / x.norm1()); // rescale
}
// compute by finding eigenvector corresponding to eigenvalue = 1
EigenvalueDecomposition eig = new EigenvalueDecomposition(A);
Matrix V = eig.getV();
double[] real = eig.getRealEigenvalues();
for (int i = 0; i < N; i++) {
if (Math.abs(real[i] - 1.0) < 1E-8) {
x = V.getMatrix(0, N-1, i, i);
x = x.times(1.0 / x.norm1());
System.out.println("Stationary distribution using eigenvector:");
x.print(9, 6);
}
}
From a quick look the code seems correct, provided that
your matrix transition is the same as in the python example. From your result I assume
the method Matrix.times does a vector multiplication and not a entry-wise multiplication
the number of 50 iterations should be enough for this example. In cases where your 2nd eigenvalue is also close to one this number will be much larger
the function EigenvalueDecomposition.getV returns the eigenvectors in the orientation you expect (row / column)
Note that a valid transition matrix (the matrix of jumping probabilities) has row or column sum of 1 (a matter of definition) since the chances of staying or switching must be 100%. This implies the existance of an eigenvectors of one. From your use of initial transpose of the matrix, I assume you need row-sum of one.
Since you seem to not have an eigenvalue of 1, the most logical error is a typo in your matrix.

How to write this algorithm more efficiently

I have an assignment where I have to write an algorithm which 'splits' the array in two. Left side should be odd numbers, and right side should be even numbers. Both sides should be sorted in ascending order. I'm not allowed to use temp arrays or existing api.
I have managed to make a working method, problem is with an array of say 100 000 integers, it takes approximately 15 seconds to finish. The requirement is 0,1 seconds, so I obviously have a lot to improve. I'm not looking for someone to spoon-feed me the answer, just a nudge in the right direction. Please don't write any working code for me, though I would like to know if and why something I've written is bad!
What I have so far:
public static void delsortering(int[] a){
int oddnum = 0;
int n = a.length;
for(int k : a){ //finds how many odd numbers there are
if((k & 1) != 0) oddnum++;
}
for(int i = 0; i < n; i++){
if((a[i] & 1) != 0){ //finds odd numbers
for(int j = 0; j < n; j++){
if((a[j] & 1) == 0) //looks for even numbers to change pos with
switch(a, j, i);
}
}
}
for (int i = 0; i < n; i++){
int from = i < oddnum ? 0 : oddnum;
int to = i < oddnum ? oddnum - i: n - i + oddetall;
int m = maxValue(a, from, to); //finds max value in specified range
switch(a, m, to - 1); //puts said max value at specified index
}
}
Appreciate all the help I can get!
A better solution would be:
Firstly keep two variables that point to the first and last elements of the array e.g x=0; y=N-1.
Then start moving x to the right until you find an even number (all numbers until now are odd !!!), then start moving y to the left until you find an odd number (all number you examine while decreasing-moving left y are even until the first one odd you find !!!)
Swap values x,y ,increase x,y and repeat the same procedure until x,y get crossed.
Then you have the array with evens on the right and odd on the left but not ordered. So you could count during the above procedure the number of odds and evens in order to know where there are separated in the array let's say in k index.
Sort array[0 - k], Sort array[k+1 - N].
Complexity: O(n) for the first part (x,y are only once moving to one direction) and O(nlogn) for both sorts so O(nlogn) which is better than O(n^2) that is your solution.

Java 2D Array: Go through groups of entries and sum their values

Let's say that there exists a 2D Java array (4x6 for representation purposes) filled with numbers ranging from 1 to 9 in a random order.
What if one wanted to calculate the individual sum of all groups of numbers in that array?
Simple illustration:
In this particular case:
Sum of the blue area
Sum of the violet area
Sum of the red area
Sum of the yellow area
...
The following code works for any array, but only if each entry is precisely 1x1 big which is useless in this case (and any other case), as it simply goes through all entries.
for (int a = 0; a < x; a++) {
for (int b = 0; b < y; b++) {
sum = array[a][b];
}
}
How would you make it go through groups of entries and then sum all values located in an individual group?
startx, starty, endx, endy is the answer to that. You will iterate from start to end. This does require you to know (or be able to calculate) those variables. If not please clarify the exact structure.
If your array is declared like:
int[][] matrix = new int [4][6];
A rough example:
public int sumOfSubMatrix (int startx, int starty, int endx, int endy) {
int sum = 0;
for (int x = startx; x <= endx; x++) {
for (int y = starty; y <= endy; y++) {
sum += matrix[x][y];
}
}
return sum;
}
You simply add every "cell" to the sum variable.
Now, this is not possible if the "colors" were spread out, even one cell being off, then the algorithm has to something of them, like their position. If the structure is 100% chaotic then your best option is brute force with if-guards.

Big O for 2D for loop

I have to write down the Big O notation of an algorithm I had to think up for my homework.
I'm able to tell that the code below is O(n^2). Because for every x I have to go through all of the y's and it becomes slower as the world grows larger.
int[][] world = new world[20][20];
for (int x = 0; x < 20; x++)
{
for (int y = 0; y < 20; y++)
{
..
}
}
But, for another question I have to go through the bottom half of the world, so my y loop gets halved.
int[][] world = new world[20][20];
for (int x = 0; x < 20; x++)
{
for (int y = 10; y < 20; y++)
{
..
}
}
I'm not quite sure what Big O notation is appropriate for the above loop, is it still O(n^2) because it still becomes slower the bigger the world gets? Or is it O(log n) because the y is halved?
it is simply speaking O(n*n/2)=O(n^2) since constants arent considered in big O.
It's O(n^2) as y is still a function of n i.e. O(n^2/2) is still O(n^2).
Both of your algorithms are in fact O(n) (assuming n is the number of bits in the input, which is the common definition). The first one touches each "pixel" in the world array once, so it's easy to see it is O(n). The second one touches half of the pixels, but is still O(n) since O(n/2) = O(n). In both cases, doubling the size of the world array will more or less double the execution time, which is typical of O(n) algorithms.

Categories