How to solve a problem with ArrayLists recursively - java

I'm trying to write a program that "solves a circle". The Circle class contains an ArrayList of Triangle Objects and an ArrayList of Integers. The Triangle objects each have three int instance fields that represent three numbers at the vertices of each triangle. There is also a Pairs class (you can see all of the code I have in the "code" section)
Here is an example of the setup using four triangles that is not solved:
And here is the same circle after it has been "solved":
The Circle in the second picture is a solved Circle because the number on any arc of the circle is equal to the sum of the two vertex numbers next to it: 6 = 1+5, 15 = 6+9, 11 = 7+4, and 9 = 5+4. Note that this was obtained by rotating the given triangles. This is analagous in the code to simply changing the Pair that is present in the solution for each triangle (where a "Pair" is an object of two ints, where those ints are the values on the circle for each triangle)
A Circle isn't always given in a "solved" state. If this is the case, the triangles can be rotated so that the circle will be in the solved state. The precondition of any given circle is that there is a solved state, so the numbers will always line up.
A circle will always have at least two triangles and there is no (practical) maximum number. Every given circle will always be solvable, meaning there is a way to rotate each triangle so that the number on the circle is the result of the sum of the two adjacent vertices from the two different triangles.
The point of the program is not to alter any of the given instance fields; instead, I just want to create a method called solveCircle that returns an ArrayList of Pairs that represents the solution to the Circle. In the above example, the solveCircle method would return an ArrayList containing the following pairs: (4,1), (5,6), (9,7), (4,5). These pairs are in the solution because they are all pairs of numbers on a triangle, and each pair is also on the circle. Note that the solution goes counter-clockwise around the circle.
My gut is telling me that this process should involve some type of recursion, since a loop would be tricky due to the circular nature of the circle; in other words, I could loop through each pair of triangles finding the proper solution, but there could easily be more than one, and comparing each one with the solution to the next sum seems like it will be inefficient; recursion seems like a better option but I'm not sure what to apply the recursion to...what alrgorithm should I use and what is even the base case?
public class Triangle
{
private int num1;
private int num2;
private int num3;
public Triangle(int n1, int n2, int n3)
{
num1 = n1;
num2 = n2;
num3 = n3;
}
public ArrayList<Pair> getPairs()
{
ArrayList<Pair> pairs = new ArrayList<Pair>();
pairs.add(new Pair(num1, num2));
pairs.add(new Pair(num2, num3));
pairs.add(new Pair(num3, num1));
return pairs;
}
}
class Pair
{
private int p1;
private int p2;
public Pair(int x, int y)
{
p1 = x;
p2 = y;
}
}
public class Circle
{
private ArrayList<Triangle> triangles;
private ArrayList<Integer> sums;
public Wheel(ArrayList<Integer> s, ArrayList<Triangle> t)
{
triangles = t;
sums = s;
}
public ArrayList<Pair> solveCircle()
{
//need help here
}
}

You can use a tree to separate the triangles that are solved from the ones that are unsolved. The same for the circles that are solved and that are unsolved. This way, you would make it a log n search function that would ignore the solved ones, thus avoiding unnecessary comparisons.
if (solved)
add to left side of the tree
else
add to right side of the tree
The complexity as well for this could be an extreme overkill depending on the use case.

for the initial step, you call the helper three times: once for each pair, until a success is returned (boolean could be used to indicate success.)
the helper performs the recursive step.
for the recursive step, you have a sum extending behind you, an integer which you must combine with to meet that sum, and three possible ways to acheive it... however you do not return success unless your recursive call also returns success
for the terminal step, there is no rotating allowed, just a final true or false for did I complete the sum behind me.

Related

Summing over a N dimensional function - Monte Carlo Integration?

I wanted to evaluate a certain sum needed for a monte carlo method in N dimensions. In N dimensions I have N variables with M data points, meaning that I basically have M N-D vectors representing M sampling points. I have to hold one variable fixed while I sum over all other variables for M values. Currently my code is (assuming my mesh which has N columns and M rows is static):
public static double myFunction(int row, int col){
double checkMesh = mesh[row][col];
return myFunctionHelper(0,col,checkMesh);
}
public static double myFunctionHelper(int j, int col, double checkMesh){
//function is initialized with j=0
if (j >= mesh[0].length){
return 0;
}
double sum = 0;
for (int i=0 ; i<mesh.length ; i++){
sum += myFunctionHelper(j+1,col,checkMesh);
if (j==mesh[0].length-1){
if (mesh[0][col]==checkMesh){
sum += function(mesh[0]);
}
mesh = rotate(mesh,j);
}
}
if (j>=1){
mesh = rotate(mesh,j-1);
}
return sum;
}
Now this function works but it doesn't hold any variables fixed, instead it just sums over all possible combinations of variables. I was wondering if anyone had any suggestions on how I can alter this to make it work as I want it to. Currently the only workaround that I can think of is to remove the fixed column from my matrix, sum over the combinations of the altered matrix, and when the function gets evaluated make sure the fixed variable is included in the right spot of an altered list, except I want to avoid doing this as it requires more memory and isn't as clean. I'd appreciate the help :).
EDIT: The rotate function takes the mesh and rotates the j-th column by one vertically upwards movement. Also function takes a vector as an argument, where the vector is represented by an array.
(1) You are computing the sum recursively, through myFunctionHelper calling myFunctionHelper. This may work, but it makes the code more involved than necessary. Recursion is not really not suited for this kind of numeric computation. Rewrite your algorithm without recursion, as a double loop over row and columnd indices, and things will get much clearer.
(2) With mesh[0][col]==checkMesh you try to identify the fixed entry by value. Why not by column and row index?

Shuffling through all the points in a 3-dimensional space without storing all possible coordinates

I'm programming a 3-dimensional cellular automata. The way I'm iterating through it right now in each generation is:
Create a list of all possible coordinates in the 3D space.
Shuffle the list.
Iterate through the list until all coordinates have been visited.
Goto 2.
Here's the code:
I've a simple 3 integer struct
public class Coordinate
{
public int x;
public int y;
public int z;
public Coordinate(int x, int y, int z) {this.x = x; this.y = y; this.z = z;}
}
then at some point I do this:
List<Coordinate> all_coordinates = new ArrayList<>();
[...]
for(int z=0 ; z<length ; z++)
{
for(int x=0 ; x<diameter ; x++)
{
for(int y=0 ; y<diameter ; y++)
{
all_coordinates.add(new Coordinate(x,y,z));
}
}
}
and then in the main algorithm I do this:
private void next_generation()
{
Collections.shuffle(all_coordinates);
for (int i=0 ; i < all_coordinates.size() ; i++)
{
[...]
}
}
The problem is, once the automata gets too large, the list containing all possible points gets huge. I need a way to shuffle through all the points without having to actually store all the possible points in memory. How should I go about this?
One way to do this is to start by mapping your three dimensional coordinates into a single dimension. Let's say that your three dimensions' sizes are X, Y, and Z. So your x coordinate goes from 0 to X-1, etc. The full size of your space is X*Y*Z. We'll call that S.
To map any coordinate in 3-space to 1-space, you use the formula (x*X) + (Y*y) + z.
Of course, once you generate the numbers, you have to convert back to 3-space. That's a simple matter of reversing the conversion above. Assuming that coord is the 1-space coordinate:
x = coord/X
coord = coord % X
y = coord/Y
z = coord % Y
Now, with a single dimension to work with, you've simplified the problem to one of generating all the numbers from 0 to S in pseudo-random order, without duplication.
I know of at least three ways to do this. The simplest uses a multiplicative inverse, as I showed here: Given a number, produce another random number that is the same every time and distinct from all other results.
When you've generated all of the numbers, you "re-shuffle" the list by picking a different x and m values for the multiplicative inverse calculations.
Another way of creating a non-repeating pseudo-random sequence in a particular range is with a linear feedback shift register. I don't have a ready example, but I have used them. To change the order, (i.e. re-shuffle), you re-initialize the generator with different parameters.
You might also be interested in the answers to this question: Unique (non-repeating) random numbers in O(1)?. That user was only looking for 1,000 numbers, so he could use a table, and the accepted answer reflects that. Other answers cover the LFSR, and a Linear congruential generator that is designed with a specific period.
None of the methods I mentioned require that you maintain much state. The amount of state you need to maintain is constant, whether your range is 20 or 20,000,000.
Note that all of the methods I mentioned above give pseudo-random sequences. They will not be truly random, but they'll likely be close enough to random to fit your needs.

Using random function in selecting an object if two same distance values

I have an ArrayList unsolvedOutlets containing object Outlet that has attributes longitude and latitude.
Using the longitude and latitude of Outlet objects in ArrayList unsolvedOutlets, I need to find the smallest distance in that list using the distance formula : SQRT(((X2 - X1)^2)+(Y2-Y1)^2), wherein (X1, Y1) are given. I use Collections.min(list) in finding the smallest distance.
My problem is if there are two or more values with the same smallest distance, I'd have to randomly select one from them.
Code:
ArrayList<Double> distances = new ArrayList<Double>();
Double smallestDistance = 0.0;
for (int i = 0; i < unsolvedOutlets.size(); i++) {
distances.add(Math.sqrt(
(unsolvedOutlets.get(i).getLatitude() - currSolved.getLatitude())*
(unsolvedOutlets.get(i).getLatitude() - currSolved.getLatitude())+
(unsolvedOutlets.get(i).getLongitude() - currSolved.getLongitude())*
(unsolvedOutlets.get(i).getLongitude() - currSolved.getLongitude())));
distances.add(0.0); //added this to test
distances.add(0.0); //added this to test
smallestDistance = Collections.min(distances);
System.out.println(smallestDistance);
}
The outcome in the console would print out 0.0 but it wont stop. Is there a way to know if there are multiple values with same smallest value. Then I'd incorporate the Random function. Did that make sense? lol but if anyone would have the logic for that, it would be really helpful!!
Thank you!
Keep track of the indices with min distance in your loop and after the loop choose one at random:
Random random = ...
...
List<Integer> minDistanceIndices = new ArrayList<>();
double smallestDistance = 0.0;
for (int i = 0; i < unsolvedOutlets.size(); i++) {
double newDistance = Math.sqrt(
(unsolvedOutlets.get(i).getLatitude() - currSolved.getLatitude())*
(unsolvedOutlets.get(i).getLatitude() - currSolved.getLatitude())+
(unsolvedOutlets.get(i).getLongitude() - currSolved.getLongitude())*
(unsolvedOutlets.get(i).getLongitude() - currSolved.getLongitude()));
distances.add(newDistance);
if (newDistance < smallestDistance) {
minDistanceIndices.clear();
minDistanceIndices.add(i);
smallestDistance = newDistance;
} else if (newDistance == smallestDistance) {
minDistanceIndices.add(i);
}
}
if (!unsolvedOutlets.isEmpty()) {
int index = minDistanceIndices.get(random.nextInt(minDistanceIndices.size()));
Object chosenOutlet = unsolvedOutlets.get(index);
System.out.println("chosen outlet: "+ chosenOutlet);
}
As Jon Skeet mentioned you don't need to take the square root to compare the distances.
Also if you want to use distances on a sphere your formula is wrong:
With your formula you'll get the same distance for (0° N, 180° E) to (0° N, 0° E) as for (90° N, 180° E) to (90° N, 0° E), but while you need to travel around half the earth to travel from the first to the second, the last 2 coordinates both denote the north pole.
Note: I believe fabian's solution is superior to this, but I've kept it around to demonstrate that there are many different ways of implementing this...
I would probably:
Create a new type which contained the distance from the outlet as well as the outlet (or just the square of the distance), or use a generic Pair type for the same purpose
Map (using Stream.map) the original list to a list of these pairs
Order by the distance or square-of-distance
Look through the sorted list until you find a distance which isn't the same as the first one in the list
You then know how many - and which - outlets have the same distance.
Another option would be to simply shuffle the original collection, then sort the result by distance, then take the first element - that way even if multiple of them do have the same distance, you'll be taking a random one of those.
JB Nizet's option of "find the minimum, then perform a second scan to find all those with that distance" would be fine too - and quite possibly simpler :) Lots of options...

algorithm to calculate perimeter of unioned rectangles

I'm trying to calculate the perimeter of the union of a n rectangles, of which I have the bottom left and top right points. Every rectangle sits on the x axis (bottom left corner of every rectangle is (x, 0)). I've been looking into different ways of doing this and it seems like the Sweep-Line algorithm is the best approach. I've looked at Graham Scan as well. I'm aiming for an O(n log n) algorithm. Honestly though I am lost in how to proceed, and I'm hoping someone here can do their best to dumb it down for me and try to help me understand exactly how to accomplish this.
Some things I've gathered from the research I've done:
We'll need to sort the points (I'm not sure the criteria in which we are sorting them).
We will be dividing and conquering something (to achieve the O (log n)).
We'll need to calculate intersections (What's the best way to do this?)
We'll need some sort of data structure to hold the points (Binary tree perhaps?)
I'll ultimately be implementing this algorithm in Java.
The algorithm is a lot of fiddly case analysis. Not super complicated, but difficult to get completely correct.
Say all the rectangles are stored in an array A by lower left and upper right corner (x0, y0, x1, y1). So we can represent any edge of a rectangle as a pair (e, i) where e \in {L, R, T, B} for left, right, top, and bottom edge and i denotes A[i]. Put all pairs (L, i) in a start list S and sort it on A[i].x0.
We'll also need a scan line C, which is a BST of triples (T, i, d) for top edges and (B, i, d) for bottom. Here i is a rectangle index, and d is an integer depth, described below. The key for the BST is the edges' y coordinates. Initially it's empty.
Note that at any time you can traverse C in order and determine which portions of the sweep line are hidden by a rectangle and not. Do this by keeping a depth counter, initially zero. From least y to greatest, when you encounter a bottom edge, add 1 to the counter. When you see a top edge, decrement 1. For regions where the counter is zero, the scan line is visible. Else it's hidden by a rectangle.
Now you never actually do that entire traversal. Rather you can be efficient by maintaining the depths incrementally. The d element of each triple in C is the depth of the region above it. (The region below the first edge in C is always of depth 0.)
Finally we need an output register P. It stores a set of polylines (doubly linked lists of edges are convenient for this) and allows queries of the form "Give me all the polylines whose ends' y coordinates fall in the range [y0..y1]. It's a property of the algorithm that these polylines always have two horizontal edges crossing the scan line as their ends, and all other edges are left of the scan line. Also, no two polylines intersect. They're segments of the output polygon "under construction." Note the output polygon may be non-simple, consisting of multiple "loops" and "holes." Another BST will do for P. It is also initially empty.
Now the algorithm looks roughly like this. I'm not going to steal all the fun of figuring out the details.
while there are still edges in S
Let V = leftmost vertical edge taken from S
Determine Vv, the intersection of V with the visible parts of C
if V is of the form (L, i) // a left edge
Update P with Vv (polylines may be added or joined)
add (R, i) to S
add (T, i) and (B, i) to C, incrementing depths as needed
else // V is of the form (R, i) // a right edge
Update P with Vv (polylines may be removed or joined)
remove (T, i) and (B, i) from C, decrementing depths as needed
As P is updated, you'll generate the complex polygon. The rightmost edge should close the last loop.
Finally, be aware that coincident edges can create some tricky special cases. When you run into those, post again, and we can discuss.
The run time for the sort is of course O(n log n), but the cost of updating the scan line depends on how many polygons can overlap: O(n) for degenerate cases or O(n^2) for the whole computation.
Good luck. I've implemented this algorithm (years ago) and a few others similar. They're tremendous exercises in rigorous logical case analysis. Extremely frustrating, but also rewarding when you win through.
The trick is to first find the max height at every segment along the x axis (see the picture above). Once you know this, then the perimeter is easy:
NOTE: I haven't tested the code so there might be typos.
// Calculate perimeter given the maxY at each line segment.
double calcPerimeter(List<Double> X, List<Double> maxY) {
double perimeter = 0;
for(int i = 1; i < X.size(); i++){
// Add the left side of the rect, maxY[0] == 0
perimeter += Math.abs(maxY.get(i) - maxY.get(i - 1))
// add the top of the rect
perimeter += X.get(i) - X.get(i-1);
}
// Add the right side and return total perimeter
return perimeter + maxY.get(maxY.size() - 1);
}
Putting it all together, you will need to first calculate X and maxY. The full code will look something like this:
double calcUnionPerimeter(Set<Rect> rects){
// list of x points, with reference to Rect
List<Entry<Double, Rect>> orderedList = new ArrayList<>();
// create list of all x points
for(Rect rect : rects){
orderedList.add(new Entry(rect.getX(), rect));
orderedList.add(new Entry(rect.getX() + rect.getW(), rect));
}
// sort list by x points
Collections.sort(orderedList, new Comparator<Entry<Double,Rect>>(){
#Override int compare(Entry<Double, Rect> p1, Entry<Double, Rect> p2) {
return Double.compare(p1.getKey(), p2.getKey());
}
});
// Max PriorityQueue based on Rect height
Queue<Rect> maxQ = new PriorityQueue<>(orderedList, new Comparator<Rect>(){
#Override int compare(Rect r1, Rect r2) {
return Double.compare(r1.getH(), r2.getH());
}
}
List<Double> X = new ArrayList<>();
List<Double> maxY = new ArrayList<>();
// loop through list, building up X and maxY
for(Entry<Double, Rect> e : orderedList) {
double x = e.getKey();
double rect = e.getValue();
double isRightEdge = x.equals(rect.getX() + rect.getW());
X.add(x);
maxY.add(maxQ.isEmpty() ? 0 : maxQ.peek().getY());
if(isRightEdge){
maxQ.dequeue(rect); // remove rect from queue
} else {
maxQ.enqueue(rect); // add rect to queue
}
}
return calcPerimeter(X, maxY);
}

Computing circle intersections in O( (n+s) log n)

I'm trying to figure out how to design an algorithm that can complete this task with a O((n+s) log n) complexity. s being the amount of intersections. I've tried searching on the internet, yet couldn't really find something.
Anyway, I realise having a good data structure is key here. I am using a Red Black Tree implementation in java: TreeMap. I also use the famous(?) sweep-line algorithm to help me deal with my problem.
Let me explain my setup first.
I have a Scheduler. This is a PriorityQueue with my circles ordered(ascending) based on their most left coordinate. scheduler.next() basically polls the PriorityQueue, returning the next most left circle.
public Circle next()
{ return this.pq.poll(); }
I also have an array with 4n event points in here. Granting every circle has 2 event points: most left x and most right x. The scheduler has a method sweepline() to get the next event point.
public Double sweepline()
{ return this.schedule[pointer++]; }
I also have a Status. The sweep-line status to be more precise. According to the theory, the status contains the circles that are eligible to be compared to each other. The point of having the sweep line in this whole story is that you're able to rule out a lot of candidates because they simply are not within the radius of current circles.
I implemented the Status with a TreeMap<Double, Circle>. Double being the circle.getMostLeftCoord().
This TreeMap guarantees O(log n) for inserting/removing/finding.
The algorithm itself is implemented like so:
Double sweepLine = scheduler.sweepline();
Circle c = null;
while (notDone){
while((!scheduler.isEmpty()) && (c = scheduler.next()).getMostLeftCoord() >= sweepLine)
status.add(c);
/*
* Delete the oldest circles that the sweepline has left behind
*/
while(status.oldestCircle().getMostRightCoord() < sweepLine)
status.deleteOldest();
Circle otherCircle;
for(Map.Entry<Double, Circle> entry: status.keys()){
otherCircle = entry.getValue();
if(!c.equals(otherCircle)){
Intersection[] is = Solver.findIntersection(c, otherCircle);
if(is != null)
for(Intersection intersection: is)
intersections.add(intersection);
}
}
sweepLine = scheduler.sweepline();
}
EDIT: Solver.findIntersection(c, otherCircle); returns max 2 intersection points. Overlapping circles are not considered to have any intersections.
The code of the SweepLineStatus
public class BetterSweepLineStatus {
TreeMap<Double, Circle> status = new TreeMap<Double, Circle>();
public void add(Circle c)
{ this.status.put(c.getMostLeftCoord(), c); }
public void deleteOldest()
{ this.status.remove(status.firstKey()); }
public TreeMap<Double, Circle> circles()
{ return this.status; }
public Set<Entry<Double, Circle>> keys()
{ return this.status.entrySet(); }
public Circle oldestCircle()
{ return this.status.get(this.status.firstKey()); }
I tested my program, and I clearly had O(n^2) complexity.
What am I missing here? Any input you guys might be able to provide is more than welcome.
Thanks in advance!
You can not find all intersection points of n circles in the plane in O(n log n) time because every pair of circles can have up to two distinct intersection points and therefore n circles can have up to n² - n distinct intersection points and hence they can not be enumerated in O(n log n) time.
One way to obtain the maximum number of n² - n intersection points is to place the centers of n circles of equal radius r at mutually different points of a line of length l < 2r.
N circles with the same centre and radius will have N(N-1)/2 pairs of intersecting circles, while by using large enough circles so that their boundaries are almost straight lines you can draw a grid with N/2 lines intersecting each of N/2 lines, which is again N^2. I would look and see how many entries are typically present in your map when you add a new circle.
You might try using bounding squares for your circles and keeping an index on the pending squares so that you can find only squares which have y co-ordinates that intersect your query square (assuming that the sweep line is parallel to the y axis). This would mean that - if your data was friendly, you could hold a lot of pending squares and only check a few of them for possible intersections of the circles within the squares. Data unfriendly enough to cause real N^2 intersections is always going to be a problem.
How large are the circles compared to the entire area? If the ratio is small enough I would consider putting them into buckets of some sort. It'll make the complexity a little more complicated than O(n log n) but should be faster.

Categories