Counting with booleans - java

I was wondering if I could add booleans up like numbers. I am making something that uses a grid, and I want it to find the surrounding squares and return a number.
EDIT:
This is how I count with booleans.
int count = 0;
for (int x = -1; x<=1;x++){
for (int y = -1; y <=1;y++){
if (grid[xPos+x][yPos+y]){
count++;
}
}
}

boolean[] bools = ...
int sum = 0;
for(boolean b : bools) {
sum += b ? 1 : 0;
}
This assumes that you want true to be 1 and false to be 0.

To add to Jeffrey's answer, don't forget:
If your at the center cell of your nested for loops, don't check the grid, and don't add to count. Else you're counting the cell itself in its neighbor count. In your situation, it's were (x == 0 && y == 0)
You will need to check if the cell is on the edge, and if so make sure you're not trying to count cells that are off the grid. I've done this using something like this: int xMin = Math.max(cellX - 1, 0); where xMin is the lower bound of one of the for loops. I do similar for y, and similar for the maximum side of the grid. In your code this will happen when xPos + x < 0 or xPos + x >= MAX_X (MAX_X is a constant for the max x value allowed for the grid), and similar for the y side of things.

What is your goal? Speed? Readability? Code terseness?
If you're seeking speed, think about minimizing the number of memory accesses. If you can force your booleans to be stored as bits, you could use >> and & to compare only the bits you care about in each row. Maybe something like this:
byte grid[m][n / 8];
int neighbor_count = 0;
for (int row = yPos - 1; row < yPos + 1; row++) {
// calculate how much to shift the bits over.
int shift = 5 - (xPos - 1 % 8);
if (shift > 0) {
// exercise for the reader - span bytes.
} else {
// map value of on-bits to count of on bits
static byte count[8] = [0, 1, 1, 2, 1, 2, 2, 3];
// ensure that only the lowest 3 bits are on.
low3 = (grid[row][xPos / 8] >> shift) & 7;
// look up value in map
neighbor_count += count[low3];
}
caveat coder: this is untested and meant for illustration only. It also contains no bounds-checking: a way around that is to iterate from 1 to max - 2 and have a border of unset cells. Also you should subtract 1 if the cell being evaluated is on.
This might end up being slower than what you have. You can further optimize it by storing the bitmap in int32s (or whatever's native). You could also use multithreading, or just implement Hashlife :)
Obviously this optimizes away from terseness and readability. I think you've got maximum readability in your code.
As Jeffrey alludes to, storing a sparse array of 'on' booleans might be preferable to an array of values, depending on what you're doing.

Related

Why doesn't my code flip image horizontally?

public void flipImageHorizontally(){
this.redisplayImage();
for(int x = 0; x < this.image.length; x++)
for(int y = 0; y < this.image[0].length; y++){
this.image[x][y] = this.image[x][this.image[0].length - 1 - y];
}
}
The code runs but it doesn't perform the action intended. It is supposed to flip the image horizontally, but instead it only flips half of the image.
Let's say you have an image two pixels wide and one pixel high:
1 2
After the first iteration of your loop, the end pixel will be swapped to the beginning (image[0][0] = image[0][2 - 1 - 0];):
2 2
But now you lost the original value of image[0][0]! So when you do the swap image[0][1] = image[0][2 - 1 - 1];, you are copying the second half of the image back to itself.
The right answer is to use a buffer so you don't overwrite the swap:
for(int y = 0; y < this.image[0].length / 2; y++) {
int buffer = this.image[x][y];
this.image[x][y] = this.image[x][this.image[0].length - 1 - y];
this.image[x][this.image[0].length - 1 - y] = buffer;
}
Integer truncation ensures that this.image[0].length / 2 is an efficient bound. For even numbers, you iterate exactly the first half. For odd numbers, you iterate the first half, not including the middle pixel. That's a good thing, because the middle does not need to be swapped.
You need to iterate up to the middle, and swap pixels that are on the left with pixels that are on the right. Otherwise you end up overwriting your changes.
public void flipImageHorizontally() {
this.redisplayImage();
for(int x = 0; x < this.image.length; x++) {
for(int y = 0; y < this.image[x].length / 2; y++) {
int pixel = this.image[x][y]; // assuming int
this.image[x][y] = this.image[x][this.image[x].length - 1 - y];
this.image[x][this.image[x].length - 1 - y] = pixel;
}
}
}
In this code
the pixel variable temporarily holds the value on the left;
the value on the left gets assigned the value on the right;
the value on the right gets the value that was originally on the left (i.e. whatever is in pixel).
Notes:
I maintained your naming of x and y, even though it's counter-intuitive because it makes it look like you're performing a vertical flip instead of a horizontal one.
I don't know the data type of the array; I assumed int, but it might be a float array, Pixel objects, or something else.
I don't know what this.redisplayImage(); is supposed to do, and whether it's in the right location.

How do you find the number of rectangles in a 2D matrix of 0s and 1s?

I have searched a number of posts here on SO as well as other resources online. Most of them provide a solution for finding the maximum area of a rectangle in a 2D matrix, which I understand. However, I am curious to know the way you find the number of rectangles in a 2D matrix where a rectangle is represented by 1s.
Update:
Apologize for not clarifying the scenario as to what classifies as a rectangle - it is considered a rectangle if the cells inside a certain perimeter are filled with 1s.
Some pseudo-code:
for x_0 in rows:
for x_1 > x_0 in rows: # symmetry-reduction: x_0 always "top"
for y_0 in columns:
for y_1 > y_0 in columns: # symmetry reduction: y_0 always "left"
if mat[x_0, y_0] == mat[x_0, y_1] == mat[x_1, y_0] == mat[x_1, y_1] == 1:
found rectangle!
Keep in mind: it's pseudo-code (partially based on python-style) and the boolean-evaluation does not work like that in most languages!
The symmetry-reduction is not only improving performance, but it's also important when you are counting. There are visually equal rectangles, where x_0 and x_1 just take different roles (left and right point). You have to decide how to count this.
Edit: After Ole V.V.'s comment above i realized that there are indeed very different interpretation's. Most of these can be realized with the pseudo-code above but with a different check on the inner-level. But that might be your work then (and there are more-tuned approaches possible then in some cases)!
Here i assume, a rectangle is just defined by 1's at the 4 corners!
Edit: After your new definition of a rectangle, the inner-check changes to:
if all(mat[x_0:x_1, y_0:y_1]) # python/numpy inspired pseudo-code!
So basically you might check all the values defined by the 4 border-points. That's easy and solves your problem.
But of course you could be much more efficient. It might be wise to add some binary-flag which indicates if the current rectangle (they are growing) is still filled with only 1's. Actually you would probably need 2 binary-flags, 1 for each dimension. Then you can do early-stopping if that's not the case.
Here is a non-optimized version that should give the correct result:
int sum = 0;
for (int row = 0; row < n; row++) {
for (int col = 0; col < m; col++) {
// count all rectangles with top left corner at (row,col)
int upperLimit = m; // this number sets the max width that rectangles with greater
// height can have (depends on the 1s in the rows above)
for (int r = row; r < n && matrix[r][col] == 1; r++) {
int c = col;
for (; c < upperLimit && matrix[r][c] == 1; c++)
sum++;
upperLimit = c;
}
}
}

Optimize algorithm from O(n^3) to O(n^2)

The problem I am trying to solve is as follows:
Assume you are given set of points in a two dimensional space and how
can we get maximum number of colinear points.
I did the problem in Java.
First I created a method that checks for linearity:
return (y1 - y2) * (x1 - x3) = (y1 - y3) * (x1 - x2);
Then I used three for loops which makes my algorithm O(n^3). But I am trying to see if this can be reduce to O(n^2).
After searching on the net I found that my implementation is very similar to whats here. So the question is how can we improve the complexity. Any example would be great.
This is what I ended up doing:
int p = 2;
for (int i = 0; i < points.lenght(); i++) {
for (int j = i+1; j < points.length(); j++) {
int count = 2;
for (int k =0; i < points.length(); k++) {
if (k == i || k == j)
continue;
//use linearity function to check if they are linear...
}
p = max(p,count);
}
}
I came to something very similar to #hqt's solution and want to elaborate on the details they've left out.
Two elements of this class are equal if their ratio dx to dy ratio (i.e., the slope) is the same.
static class Direction {
Direction(Point p, Point q) {
// handle anti-parallel via normalization
// by making (dx, dy) lexicographically non-negative
if (p.x > q.x) {
dx = p.x - q.x;
dy = p.y - q.y;
} else if (p.x < q.x) {
dx = q.x - p.x;
dy = q.y - p.y;
} else {
dx = 0;
dy = Math.abs(p.y - q.y);
}
}
public boolean equals(Object obj) {
if (obj==this) return true;
if (!(obj instanceof Direction)) return false;
final Direction other = (Direction) obj;
return dx * other.dy == other.dx * dy; // avoid division
}
public int hashCode() {
// pretty hacky, but round-off error is no problem here
return dy==0 ? 42 : Float.floatToIntBits((float) dx / dy);
}
private final int dx, dy;
}
Now fill a Guava's Multimap<Direction, PointPair> by looping over all pairs (complexity O(n*n)). Iterate over all keys (i.e. directions) and process the List<PointPair> via a union find algorithm. The found partitions are sets of pairs of collinear points. If there are k collinear points, then you'll find a set containing all pairs of them.
Because of the union find algorithm, the complexity is O(n*n*log(n)), avoiding sorting didn't help.
You can use angular coefficient between two points with Ox to solve this problem. For example, for 3 points : A B C. If they're collinear if and only if line AB and line AC make a same angular coefficient with Ox line. So, here is pseudocode of mine :
// Type : an object to store information to use later
List<Type> res = new ArrayList<Type>();
for (int i = 0; i < points.lenght(); i++) {
for (int j = i+1; j < points.length(); j++) {
double coefficient = CoeffiecientBetweenTwoLine(
line(points[i], points[j]), line((0,0), (0,1));
res.add(new Type(points[i], points[j], coefficient);
}
}
After that, you use QuickSort, sort again above List base on Coefficient. And any coefficient equals, we can know which points are collinear. Complexity of this algorithm is O(N^2logN) (dominated by sorting a list with O(N^2) elements, only O(N^2) required to build the list).
#Edit:
So how can we know how many points collinear when we show equal coefficient ?
There are many ways to solve this problem.
At sort step, you can sort by first parameter (is which point in
that line) when two coefficient are equal. For example. After sort,
the result should be (in this case, if 1 3 and 4 are collinear) :
(1 3)
(1 4)
(3 4)
From above building, you just need to see streak of 1. in this example, is 2. so the result should be 3. (always k + 1)
Use formula : because number of pair that equals always : n*(n-1)/2
. So, you will have : n*(n-1)/2 = 3. and you can know n = 3 (n >=
0). That means you can solve quadratic equation here (but not too
difficult, because you always know it have solution, and just get
one solution that positive)
Edit 2
Above step to know how many collinear points is not true, because at case for example, A B and C D are two parallel line (and line AB is different from line CD), the result, they still have same coefficient with Ox. So, I think to fix this problem, you can use Union-Find Data structure to solve this problem. Step will be :
Sort again angular coefficient
For example : (1 2 3 4) is collinear and they're parallel with (5,6,7) and point 8 stands somewhere else. So, after sort, the result should be :
(1 2) (1 3) (1 4) (2 3) (2 4) (5 6) (5,7) (6,7) angular coefficient equals, but at two different line
(1,5) (1, 6) .. // Will have some pair connect between two set of parallel line. (1, 8)
(5, 8) (3, 8) .... // Random order. because don't know.
Use Union-Find Data structure to join tree: Start iterate from second element, if you see its angular coefficient equals with previous, join itself and join previous. For example,
(1,3) == (1,2) : join 1 and 2, join 1 and 3.
(1,4) == (1,3) : join 1 and 3, join 1 and 4. ....
(5,6) : join 2 and 4, join 5 and 6.
(5,7): join 5 and 7, join 5 and 6 ...
(1,8) : not join anything. (5,8) : not join anything ...
After you finish this step. All you have is a multi-tree, in each tree, is a set of points that they're collinear.
Above step, you see that some pairs are join multi-time. you can simply fix this by mark, if they're already join, ignore to enhance more in performance.
# : I think this solution is not good, I just do by my brain-thinking, not a real algorithm behind. So, any other clear ideas, please tell me.
Try Below
//just to create random 15 points
Random random = new Random();
ArrayList<Point> points = new ArrayList<Point>();
for(int i = 0; i < 15; i++){
Point p = new Point(random.nextInt(3), random.nextInt(3));
System.out.println("added x = " + p.x + " y = " + p.y);
points.add(p);
}
//code to count max colinear points
int p = 0;
for(int i = 0; i < points.size() -1; i++){
int colinear_with_x = 1;
int colinear_with_y = 1;
for(int j = i + 1; j < points.size(); j++){
if(points.get(i).x == points.get(j).x){
colinear_with_x++;
}
if(points.get(i).y == points.get(j).y){
colinear_with_y++;
}
}
p = max(p,colinear_with_x,colinear_with_y);
}
An approach, that relies heavily on a good hashed map:
As key use the a linear equation (defining a line), so that you have a map along the line of
map<key=(vector, point), value=quantity> pointsOnLine
where vector and point define the linear function that two points determine.
Then you iterate over all n points:
maxPoints = 2
for i=1 to n
for j=i+1 to n
newKey = lineParametersFromPoints(point[i], point[j])
if pointsOnLine.contains(newKey)
pointsOnLine[key] += 1
if maxPoints < pointsOnLine[key]
maxPoints = pointsOnLine[key]
else
pointsOnLine.add(key)
pointsOnLine[key] = 2
maxPoints then contains the maximum number of colinear points.
Please note (this is probably most important), that the hash-compare function of the map must check that the two lines represent the same linear function, even if the vectors are anti-parallel or the points on the two lines are not the same (but one satisfies the other equation).
This approach does of course heavily rely on the map having fast access and insertion times.
Algorithm :-
Simple algorithm which can do it in O(N^2*logN) :-
Pick a point p.
Find slope from p to all other points
sort the points according to slopes
scan the sorted array to check for maximum consecutive points with same slope value
maximum value + 1 is maximum points collinear with p included.
Do 1 to 5 for all points and find maximum collinear points found
Time complexity : O(N) for slope calculation, O(NlogN) for sorting and O(N^2*logN) for all N points.
Space complexity : O(N) for slopes and points

Need help reducing triple for loop to increase efficiency

for (int i = 0; i < 3; ++i) {
for (int k = 0; k < 7; ++k) {
for (int h = i; h < 4 + i; ++h) {
result = state.getAt(k, h);
if (result == 1) {
++firstpl;
}
if (result == 2) {
++secondpl;
}
if (firstpl > 0 && secondpl > 0) {
break;
}
//y = k;
}
if (firstpl == 0 && secondpl == 0) {
break;
} else if (firstpl > secondpl) {
score += firstpl * firstpl;
//if(state.getHeightAt(y)-3 < 3) score += 3+firstpl*2;
} else {
score -= secondpl * secondpl;
//if(state.getHeightAt(y)-3 < 3) score -= 3+secondpl*2;
}
firstpl = 0;
secondpl = 0;
}
}
basically I have a 7 by 6 grid. I am going through 7 columns and looking at every 4 consecutive blocks vertically. Since there is 6 blocks upward. There is 3 four consecutive block for each column. State.getAt(k,h) takes in a x and y and returns a value.
I don't think you can improve on this, unless you can figure out an alternative representation for this "state" that allows this computation to be performed incrementally.
And since you have failed to properly explained what the state or the calculation actually mean, it is difficult for anyone but you to figure out whether an alternative approach is even feasible. (And I for one am not going to attempt to reverse engineer the meaning from your code.)
OK. For Connect4, the win / lose is a line of 4 checkers horizontally, vertically or diagonally in the 7x6 grid. So what you could do is represent the score-state as an array of counters, corresponding to each of the columns, rows and diagonals in which a winning line could be made. (7 + 5 + 4 + 4 = 20 of them => 20 counters) Then construct a static mapping from an (x,y) position to the indexes of lines that pass through that. When you add a checker at point (x,y) you look up the counters and increment them. When you remove a checker ... decrement.
I'm not sure how that relates to your existing scoring function ... but then I don't see how that function relates to a strategy that would win the game. Either way, you could potentially use the approach above to calculate scores incrementally.

Matrix Multiplication Java

I need help, I am trying to make use of Lattice Multiplication in java for use in a BigInt class I am having to write for a class.
Right now I have the code storing the digits needed for the adding part of the algorithm in a 2 dimensional array. From there though I am at a lose as to how to make a loop to go through the array and add the numbers in what would be a diagonal.
For instance here is the test numbers etc:
200
*311
= 62200
The array is holding:
6 0 0
2 0 0
2 0 0
6 is (2,2) in the array and the bottom right is (0,0)
I need to add in a diagonal, such as (1,0) + (0,1) = 0
The issue is how do I do this, since not only is it moving up and left in different ways, but it goes from 1 element to 2 elements to 3 elements, then back the other way, and of course this will get bigger the longer the number is.
This is the code that I have:
public int multiply(BigInt val){
int[] bigger;
int[] smaller;
int[] dStore;
int lengthMax = (val.getSize()+this.getSize()) - 1;
int first = 0;
int second = 0;
int[][] tempResult;
//Checks to see which is bigger and then adds that to bigger
if(val.getSize() >= this.getSize()){
bigger = val.getData();
smaller = this.getData();
dStore = new int[val.getSize()+this.getSize()];
}else{
bigger = this.getData();
smaller = val.getData();
dStore = new int[val.getSize()+this.getSize()];
}
tempResult = new int[smaller.length][bigger.length];
for(int i=0;i < smaller.length;i++){
for(int j = 0;j < bigger.length;j++){
tempResult[i][j] = smaller[i] * bigger[j];
}
}
** there is the return statement etc below
This might help as to explain lattice multi better: Lattice Multi Video
I would try a different approach. Look at the lattice in the video and imagine that you rotates the array a little bit to the left so that the diagonals becomes vertical. The array would then look like this:
2 3 5
8 3
2 4 0
Now, just summarize the columns and you would have the total.
You would of course have to split the numbers into arrays of digits first. The easiest way to do that (but not the most efficient) is to convert them into strings ...
Good luck!
To move diagonally, you'd increment both x and y:
// Loop though the diagonal of an array
x = 0;
y = 0;
while (x < ARR_X_SIZE && y < ARR_Y_SIZE) {
// Do something with arr[x][y]
x++;
y++;
}
This is the basic loop; you can change the x and y increments to determine the direction you need to go. The key to going through the whole array is the value of the coordinates going into the loop. Array:
1 2 3
4 5 6
7 8 9
If you set x = 1; y=0 at the beginning of the loop, you'll get 2 6. Set x = 0, y = 1 and you'll get 4 8.
I hope this helps you with your assignment. Good luck on the rest! That is definately an interesting algorithm to implement.

Categories

Resources