Comparing Distance within an Array - java

I have a question in comparing values within an Array and drawing a line to the points that have the largest distance.
Point2D[] pts = new Point2D[N];
for (int i = 0; i < pts.length; i++){
pts[i] = new Point2D(Math.random(), Math.random());
StdDraw.setPenColor(StdDraw.RED);
StdDraw.setPenRadius(0.008);
pts[i].draw();
if(SOMETHING){
StdDraw.setPenColor(StdDraw.BLACK);
StdDraw.setPenRadius(0.002);
pts[i].drawTo(SOMETHING);
so far that's part of my code that generates the random points, but I have no clue how to approach measuring the distance and then drawing it.
Would I have to create a nested loop?
Any advice would be great!

It is likely that, if you only want to draw the longest edge (a graph theory term), your draw call will not be inside of your for loop. Rather, your loop (and possibly with a second nested loop) will run through all of your possibilities and find the longest edge first, by saving and overwriting data on whichever is the most-longest it has found thus far every time it breaks the previous record, and then commence drawing once after the loop.

Related

Is there a way to reduce complexity when modelling interactions between nodes in a simulation engine?

I am building a simulation in Java w/JavaFX UI.
The idea is that I can create many Person objects (in an array) which will contain (x,y) co-ordinates to denote positioning for rendering on the screen. At each step in time I will iterate through the array and apply some to the Person objects to calculate their next position (based on current velocity etc). So far so good...
However, I also want to model interactions between Person objects (make sure that they can't overlap for instance and would just bounce off each other). The only way that I can see to do this is by iterating over the array for each Person to compare their x,y values against every other person e.g.
Person [] population = initialisePopulationArray(); //Helper function to just set initial values
//A step in time occurs just before I render the new positions on screen
void step(){
//Do basic initial calculation on positions O(n)
for(Person person: population){
updatePosition(person); //Based on trajectory etc
}
//Determine if new positions mean that people are overlapping and resolve O(n ^ 2)
for(int i=0; i<population.length; i++){ //For every person
Person person = population[i];
for(int x=i+1; i<population.length-(i+1); i++){ //Compare against every other person
compareAndResolve(person, population[x]; // Some function to compare and resolve any issues
}
}
}
As you can see this gives exponential complexity - is this just the way it has to be in a simulation like this or is there a better way that I have missed?
Any help would be greatly appreciated!!!
If two people don't interact as long as they are farther apart than some distance d, then you can divide your world into squares of size d x d. Then you only have check each person against other people in the same or adjacent squares.
In Java you could use, for example, a Hashmap<java.awt.Point, List<Person>> to keep track of which people are in each square.

Fastest way to check which rectangle is clicked in a list of rectangles

I have a rectangle Object with x, y, width and height. I have a list of these rectangles which are displayed on a screen. It is guaranteed that none of them overlap. Given a user's click position (x and y coordinates), I want to see which of these rectangles were clicked (since they do not overlap, there is a maximum of one rect that can be clicked).
I can obviously look through all of them and check for each one if the user clicked it but this is very slow because there are many on the screen. I can use some kind of comparison to keep the rectangles sorted when I insert a new one into the list. Is there some way to use something similar to binary search in order to decrease the time it takes to find which rect was clicked?
Note: the rectangles can be any size.
Thanks:)
Edit: To get an idea of what I am making visit koalastothemax.com
It highly depends upon your application and details we're not quite aware of yet for what the best solution would be. BUT, with as little as I know, I'd say you can make a 2D array that points to your rectangles. That 2D array would map directly to the pixels on the screen. So if you make the array 10x20, then the coordinate x divided by screen width times 10 (casted to int) will be the first index and y divided screen height times 20 would be your y index. With your x and y index, you can map directly to the rectangle that it points to. Some indexes might be empty and some might point to more than one rectangle if they're not perfectly laid out, but that seems the easiest way to me without knowing much about the application.
I have tackled a very similar problem in the past when developing a simulation. In my case the coordinates were doubles (so no integer indexing was possible) and there could be hundreds of millions of them that needed to be searched.
My solution was to create an Axis class to represent each axis as a sequence of ranges. The ranges were guaranteed to go from a minimum to a maximum and the class was smart enough to split itself into pieces when new ranges were added. Each range has a single generic object stored. The class used a binary search to find a range quickly.
So roughly the class looks like:
class Axis<T> {
public Axis(double min, double max, Supplier<T> creator);
public Stream<T> add(double from, double to);
public T get(double coord);
}
The add method needs to return a stream because the added range may cover several ranges.
To store rectanges:
Axis<Axis<Rectangle>> rectanges = new Axis<>(0.0, 100.0,
() -> new Axis<>(0.0, 100.0, Rectangle::new));
rectangles.add(x, x + w).forEach(r -> r.add(y, y + h).forEach(Rectangle::setPresent));
And to find a rectangle:
rectangles.get(x).get(y);
Note that there's always an object stored so you need a representation such as Rectangle.NULL for 'not present'. Or you could make it Optional<Rectangle> (though that indirection eats a lot of memory and processing for large numbers of rectangles).
I've just given the high level design here rather than any implementation details so let me know if you want more info on how to make it work. Getting the logic right on the range splits is not trivial. But I can guarantee that it's very fast even with very large numbers of rectangles.
The fastest way I can come up with is definitely not the most memory efficient. This works by exploiting the fact that an amortized hash table has constant lookup time. It will map every point that a rectangle has to that rectangle. This is only really effective if your are using integers. You might be able to get it to work with floats if you use a bit of rounding.
Make sure that the Point class has a hash code and equals function.
public class PointCheck
{
public Map<Point, Rect> pointMap;
public PointCheck()
{
pointMap = new HashMap<>();
}
/**
* Map all points that contain the rectangle
* to the rectangle.
*/
public void addRect(Rect rect)
{
for(int i = rect.x; i < rect.x + rect.width; ++i)
{
for(int j = rect.y; j < rect.y + rect.height; ++i)
{
pointMap.put(new Point(i, j), rect);
}
}
}
/**
* Returns the rectangle clicked, null
* if there is no rectangle.
*/
public Rect checkClick(Point click)
{
return pointMap.get(click);
}
}
Edit:
Just thought I should mention this: All of the rectangles held in the value of the hash map are references to the original rectangle, they are not clones.

Stacking Tiles (Hard algorithm)

This is a question from a code competition, I am finding it unbelievably difficult to come up with any working algorithm to solve it. So I'm not really looking for the code but rather a step by step algorithm on how to solve it.
Stacking Tiles
Stacking tiles against the wall is one of Bongani's favourite pasttimes. His tiles all have the same thickness, but vary
in width and height. Bongani is given N tiles and has to use them in
the sequence given according to a set of rules. He can place a tile on
top of another only if it is narrower than the previously stacked
tile. Bongani is allowed to rotate the tiles by 90 degrees so that
width becomes height and height becomes width. He is also allowed to
discard a tile altogether. Given a list of tiles, help Bongani find
the highest stack he can build The example specifies tiles (3, 3),
(12, 5), (5, 8), (6, 10). To get the highest stack Bongani ignores the
first tile (3, 3) as it is smaller than the next tile. He uses the
next tile (12, 5) with 12 as the width and 5 as the height. He uses
the next two tiles with 8 as the width and 5 as the height followed by
6 as the width and 10 as the height.
The only thing I can possibly think of is getting every possible valid permutation of tiles and find the highest permutation.
The exact question can be found here http://www.olympiad.org.za/olympiad/wp-content/uploads/2013/01/2011PO-R2-Questions-0421.pdf (Question 5)
Here's an outline of dynamic programming solution:
You "move from left to right" and for each tile you figure out
how high tower can I build by using this tile unrotated
how high tower can I build by using this tile rotated
how high tower can I build by not using this tile
The first key observation is that each question can be answered recursively ("how high tower can I build for the remaining tiles if the current width is updated according to my current choice?"). Pseudo code:
maxHeight(tiles, currentWidth) {
// Base case
if (tiles.isEmpty())
return 0; // no tiles -> maxHeight == 0
int h = 0;
currentTile = tiles[0]
remainingTiles = tiles[1...]
// Compute maxHeight for the case when not using current tile
h = max(h, maxHeight(remainingTiles, currentWidth)
// Compute maxHeight when using current tile
if (currentWidth > currentTile.width)
subHeight = maxHeight(remainingTiles, currentTile.width)
h = max(h, subHeight + currentTile.height)
// Compute maxHeight when using current tile rotated
if (currentWidth > currentTile.height)
subHeight = maxHeight(remainingTiles, currentTile.height)
h = max(h, subHeight + currentTile.width)
return h
}
The second key observation is that many of the invocations of maxHeight have the same arguments, which means that previous computations can be reused. You can either use memoization or tabulation (both are variants of dynamic programming) If you choose to use a tabulation matrix, it would look like this:
M[tileN][width] = the height of the tower possible to build from
tileN onwards with width 'width'
(As you may note width does not have a clear upper bound. This can be solved by mapping all values to 1, 2, 3, ... before starting. Maximum width will then be 2N.)
Here is a quadratic time algorithm using dynamic programming. Let f(i) be the greatest height of a tower you can build using the ith block in the original orientation and no later blocks. Let g(i) be the greatest height of a tower you can build with the ith block rotated and no later blocks. Note that blocks can be omitted, so to compute f(i), you have to take 1 more than the maximum over all previous f and g values compatible with that orientation, and similarly for g(i). At the end, the answer is the maximum over all f(i) and g(i).
The following code shows code for f. Youc an write g similarly, or modify this to take another parameter for whether block i is in the original orientation.
public int f(int i)
{
if (i == 0)
return 1;
if (memoF[i] > 0)
return memoF[i];
int maxFound = 1; // using just this block is legal
for (int j = 0; j<i; j++){
if (widths[i] < widths[j])
maxFound = Math.max(f(j)+1,maxFound);
if (widths[i] < heights[j])
maxFound = Math.max(g(j)+1,maxFound);
}
memoF[i] = maxFound;
return memoF[i];
}
I think this is typical example for easy and effective solving using Backtracking.
You just go in sequence and try first things you can do, when you cant continue, you go back and try the one you did not try before. Just google "Sudoku Backtracking" there are a lot of pages explaing that.
The huge advantage of backtracking in this case is, it "cuts" off a lot scenariou which would make no sense, therefore it would be much more effective than trying to check every possible combination.
(like in sudoku, with backtracking, the most sudokus are solved in 1000-10000 steps, which is pretty good, given that the all possible combinations of numbers you can write are ~10^60)

Find available "number" in a 2d array

I have this problem that I need to solve in the most effecient way.
I have a 2d array that contains the following:
Everything that is a 1 is a "wall" which means you cannot go through it. 2 is the entrance where you "enter" the array or map if you like. 3 are the things we need to find. Here is an example of a map:
1111111
1 3131
2 11111
1 31
1111111
This could be an example of an array that i need to look in. As you can see there is a 3 that is "unreachable, since it's surrounded by a wall "1". Which means that there are two available numbers in this array.
First we need to find the entrance. Since the entrance can be anywhere I need to search the entire array. I have done the following:
int treasureAmount = 0;
Point entrance = new Point(0,0);
for (int i = 0; i < N; i++) {
for (int j = 0; j < N; i++){
if(map[i][j] == 2){
entrance.x =i;
entrance.y =j;
}
}
This takes O(n^2) time, and i don't really see another way to do this, since the entrance can be anywhere.
However i'm not really sure how to find the available numbers effectivly and fast. I thought about while searching the arrays for the entrance i will at the same time find the all the number 3 in the array even though some might not be accessible, and after that i'm not really sure how to effectivly find which are accessible.
You cannot do it better that O(n^2). It will take that much time just to read the array. But then you could do a depth first search to find the reachable 3's in the array. Here is the pseudo code.
main()
{
read array and mark the entrance as ent.x and ent.y and also an array threex[] and threey[] that stores all the exit position.
boolean visited[][]; //stores whether array[i][j] is reachable or not.
dfs(ent.x,ent.y);
for each element in three arrays
{
if(visited[threex[i]][threey[i]]) print ("Reachable");
else print("not reachable", threex[i], threey[i]);
}
}
int dx[]={1,0,-1,0},dy[]={0,1,0,-1}; // dx[i], dy[i] tells whether to move in E,N,W,S respectively.
dfs(int x,int y)
{
visited[x][y]=true;
for(i=0;i<4;i++)//move in all directions
{
int newx=x+dx[i],newy=y+dy[i];
//check if this is within the array boundary
if(newx>=0&&newx<N && newy>=0&&newy<N)
if(!visited[newx][newy] && array[newx][newy]!=1) // check if the node is unvisited and that it is pemissible
dfs(newx,newy);
}
}
Since each array element is taken up not more than once in the dfs function the complexity of the code is O(n^2).
When creating the array, you can keep a list of coordinates of that have the value of 2. You can traverse that list in O(n).
Since both entrance and target items can be anywhere in the array you don't have much choice, but to search everything. So, your entrance search is as efficient as it can be, and regarding the target items I recommend the maze flood fill algorithm.
However, the linked version of the algorithm favorizes one direction (like it is filling it with water, it floods "down"). To be as efficient as it can, you should make it expand in all directions (like you're filling it with gas), e.g.:
2
1 212
0 101 21012
1 212
2
The numbers represent the iterations of expansion. The expansion is made in four directions: left, right, up and down. When you reach the target item, you can find the shortest route simply by backtracking to the adjacent cell neighbour whose iteration index is lesser by one, until you return to the 0 iteration index - the entrance.

Finding neighbors to Points in an ArrayList

I've recently started learning Java and though doing a "Conway's Game of Life" style program would be a good thing to start out with. Everything works fine but I'm having some serious performance issues with this part:
static List<Point> coordList = new ArrayList<Point>();
public int neighbors(int x, int y){
int n = 0;
Point[] tempArray = { new Point(x-1, y-1), new Point(x, y-1), new Point(x+1, y-1),
new Point(x-1, y ), new Point(x+1, y ),
new Point(x-1, y+1), new Point(x, y+1), new Point(x+1, y+1)};
for (Point p : tempArray) {
if (coordList.contains(p))
n++;
}
return n;
}
The method is used when iterating the ArrayList coordList filled with Points and checking every element how many neighbors they have. When the list size gets to about 10000 Points every cycle takes about 1 seconds and for 20000 Points it takes 7 seconds.
My question is, what would be a more effective way to do this? I know there are several other programs of this kind with source code available too look at, but I wan't do do as much as I can by my self since the point of the project is me learning Java. Also, I don't want to use a regular array because of the limitations.
If your points are unique, you could store them in a HashSet instead of an ArrayList. The contains method will then become an O(1) operation vs. O(n) in your current setup. That should speed up that section significantly.
Apart from the declaration, your code should remain mostly unchanged as both implement the Collection interface, unless you call List-specific method such as get(i) for example.
Performance-wise, I think your best bet is to have a plain numeric (effectively Boolean) array representing the grid. Since this is a learning exercise, I'd start with a simple one-element-per-cell array, and then perhaps progress to packing eight adjacent cells into a single byte.
It is not entirely clear what you mean by "the limitations".
The following has some interesting pointers: Optimizing Conway's 'Game of Life'
Your current code scales in a quadratic manner O(n^2). You have only given part of the program. If you look at your whole program there will be a loop that calls neighbors() and you will see that neighbors() is called n times. Also the operation contains() is linear in n, so the time is proportional to their product n*n.
Quadratic scaling is a common problem but can often be reduced to linear by using indexed data structures such as HashSet.

Categories

Resources