Determining best start and end points for line segment on polygon - java

I'm having trouble figuring out the best way to solve the following problem. I've tried out multiple methods of solving them but I'm always running into some corner cases.
The problem is the following:
You have a List of coordinates (x and y points) forming a closed polygon. This list is guaranteed to form a polygon with points ordered in a clockwise direction.
You are given a Set of coordinates (x and y points) which are from the above List of coordinates.
You must figure out the start and end points of the line formed using all points in the above Set.
The issue I'm having is that I can't figure out the method of finding the 'best' start and end points. For many scenarios, you can pick the first and last point (using the indices of the List) to form the start and end points, however this could result in a line which is longer than it has to be.
For example, let's say we have the following polygon:
0 -> 1 -> 2 -> 3 -> 4 -> 5 -> 6 -> 7 -> 0
And the following Set of coordinates our line segment must contain: 0, 7, 3.
If we find the min and max indices, we get index(0), index(7), so we can form the line 0 -> 1 -> 2 -> 3 -> 4 -> 5 -> 6 -> 7, which is a valid line but it is longer than it needs to be. The best line segment would be 7 -> 0 -> 1 -> 2 -> 3.
How can I find the best (shortest which contains all points in Set) line segment in an efficient manner?
For context: I'm working on an application which using JTS Geometries to draw shapes. The drawn shapes are smoothed using Bezier curves to result in 'curved edges'. After drawing the shapes (by dropping points), users can edit the shape. We want to figure out the start and end points using the points they modify (forms the Set above) so we can 'smooth' only the affected area.

Transform your set into sorted list, concatenate this list with it's copy, where every element is added with number of polygon vertices N, then find the longest empty run (neighbor difference) in this doubled list. Then get sublist of needed length, transform it to continuous range (but take elements modulo N)
(0,3,7) + (0+8,3+8,7+8) = (0,3,7,8,11,15)
max difference is 7-3, so the best case sublist starts with 7, it is
(7%8 .. 11%8) = (7,0,1,2,3)

so we have a Set and we nead to walk this set in the order of the index into List.
convert ISet = [Index(i, List) for i in Set]
next sort ISet
for pairs of consecutive items in ISet and the pair (last, first) compute the distances for that pair.
fined the pair with the max distances. Then the best end and start are that pair.

Related

Displaying Numbers in Certain Shapes

I just thought of this problem 15 minutes ago and even though it appears insanely easy I'm having a serious problem coming up with an answer.
Basically what I would like to do is based on a number (n) given by the user, I would like to draw a square shape.
Example: let's say the user gives the number 2, the result should be:
12
43
Now, suppose the user gives the number 3, the result should be:
123
894
765
etc..
Please don't give me the solution to this problem, I just want a clue or two to get me going.
I thought about doing it with a simple java class but I'm still struggling to get past the first condition:
public class DrawSquareWithNumbers {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
System.out.println("Enter your number: ");
int number = scanner.nextInt();
for (int i = 0; i <= number; i++) {
if (i<number)
System.out.print(i);
if (i>=number) {
System.out.println("\n"+i);
}
}
}
}
Any tip? Thanks in advance.
So I think I just put way too much time in this but it's a fun challenge so I thought let's give it a go.
I implented a code version for this solution and it works quite well although it's probably not the cleanest as I approached the whole problem backwards.
Here is my solution to try out online (note it's severely unoptimized and by no ways good Java code. It's a quick and dirty implementation to be honest):
https://ideone.com/97JB7Y
So the idea is quite simple: We first calculate the correct value for each position in a matrix and then we print that matrix out.
Let's go over it in a bit more detail:
We start of by creating the Matrix for our values to print:
With a given size n this is
int[][] values = new int[n][n];
Now we want to calculate the correct value at each point. I chose to tackle it the "wrong way" around by not starting at the first point but at the center of the spiral.
Basically imagine this matrix with n = 3:
[1][2][3]
[8][9][4]
[7][6][5]
Instead of at 1 I just start at 9. Reasoning for this is that it's actually easier to calculate the position spiraling out from a point over spiraling in to a point.
So starting at this center point we spiral out from there in a circular fashion. For the matrix
[1][2]
[4][3]
this means we visit 4 -> 3 -> 2 -> 1. And then just save the correct value in the matrix.
Only problem with my approach is that for a matrix with uneven size (3, 5, 7, etc.) I still visit the points in spiraling order, for 3x3 the order of visiting is e.g. 9 -> 4 -> 3 -> 2 -> 1 -> 8 -> 7 -> 6 -> 5, as visualized in this perfect picture I totally drew in Paint:
This leads to the result matrix being inversed as such:
[5][6][7]
[4][9][8]
[3][2][1]
This small problem is easily fixed though by simply printing the matrix out inversed once more should n%2 != 0.
Hope I could help with maybe a different approach to the problem.
I think you want to make nxn matrix with user entered number. So you can check the input and then you can use loop as for(i=1; i<=n; i++) for rows and similarly for column(for j=0;j<=n;j++) and then you can print your desired shape. Since you have asked to give you idea only so I am not posting any code here. If in case you get stuck somewhere you can refer : https://www.google.com/amp/s/www.geeksforgeeks.org/print-a-given-matrix-in-spiral-form/amp/
Ok, let's give this a try. First let's assume you'll have to store the matrix before printing it and that there's no magic formula that allows you to print what you need in a single iteration.
Now, you've the NxN matrix, for example for 3 it'd be 3x3, 9 positions. Instead of solving it with a series of ifs in an ugly way, you could use direction vectors for a cleaner solution. Also assume for now that you've another NxN matrix filled with booleans, all set to false, that will represent the already printed positions in the NxN matrix that you will print in the end. When you write a number in the final NxN matrix, you put the same position's boolean to true in the boolean matrix.
So for example, you want to print the positions of the first row, 1 2 3. You are displacing to the right to print. This'd be the direction (1,0), aka the starting direction vector. You advance through the NxN matrix using this coordinates. When you go outside the matrix (in the example, your x position is 3) you decrease your x position by one and you "spin" your direction vector (this should be done in a separate function). (1,0) would spin to (0,-1). You keep using this vector to iterate your matrix, spinning as necesary. After the first whole circle, you will get to an already printed position before going outside the matrix. So after every print you've to check not only if you go outside the matrix, but also if that position has already a number on it. For this, you use the boolean matrix.
This is how I'd solve it, there are probably many other ways (and better ones). For starters you could use null, or a mark, in the final matrix and save yourself the booleans one.
Create the result matrix beforehand, and declare a variable for the current number, starting value = 1, the current co-ordinates, starting with (0,0), the stepping direction starting with "to the right"
Start loop
Calculate the co-ordinates of next step, and check it
If it is off the matrix, then change direction, and re calculate, re-check
If free, then put the number in the matrix, increment it, and loop
If it is not free, then end loop, print out result matrix

How to get the top-k closest elements in a Java TreeSet?

Supposing I have this TreeSet<Integer>:
1 3 4 6 8 9 10
And I want the top-k "closest" elements to an input number x.
For example, with k=3 and x=5 I want to get:
4 6 3
Is there any way to do this?
It seems what you need to do is to get a headSet with all elements smaller than the target element and a tailSet for the bigger elements. Now the algorithm will be somewhat similar to merge phase of merge sort.
Take a descendingIterator of the headSet and an iterator over the tail set. Call these c_desc, and c_asc
Check which of the two elements is closer to the target value x. Take this value and advance the iterator
Take care for when one of the iterators is at the end of the corresponding set view
Continue doing that until you have taken k elements
By "closest to x" I assume you mean the lowest values of abs(n - x).
That is, for x=5, k=3:
1,3,4,6,8,9,10 -> 3,4,6
3,4,5,10,11,12 -> 3,4,5
0,1,2,5,6,7,8 -> 5,6,7
If that's the case, I would:
map each Integer to a Pair<Integer,Integer>
n -> new Pair(n, abs(n - x)) so one value is n, the other is its distance from x.
(write your own Pair, (ab)use Map.Entry, (ab)use Integer[2] or find one in a library)
sort the list of Pair<> using a comparator that uses the distance
take the first k elements from that sorted list.
Using Java 8 streams:
set.stream()
.map( n -> new Pair(n, Math.abs(x - n)))
.sorted(Comparator.comparing( p -> p.right())
.limit(k)
.map( p -> p.left())
.collect(Collectors.toSet());

Find if an array can form a graph

[Interview Question] I got this question in a recent online interview. I had no clue how to solve it. Can anyone please help me solve this so that I can learn in Java.
Tom is very good in problem-solving. So to test Tom's skills, Jerry asks Tom a graph problem. Jerry gives Tom, an array A of N integers.
A graph is a simple graph, iff it has no self-loop or multi-edges.
Now Jerry asks Tom whether he can design a simple graph of N vertices or not. The condition is that Tom has to use each and every element of A exactly once for the degrees of vertices of the graph.
Now, Tom wants your help to design his graph. Print "YES" if the graph can be designed, otherwise print "NO" (without quotes).
Input
A single integer T, in the first line, denoting the number of test cases.
For each test case, there are 2 lines.
The first line is a single integer N, denoting the number of elements of array A.
The second line has N-space separated integers, representing elements of A.
Output
For each test case, print "YES" or "NO" (without quotes) whether the graph can be designed or not, in a new line.
Constraints
1<= T <= 100
1<= N <= 100
0<= Element of A <= 5000
Sample Test Cases
Input
1
2
1 1
Output
YES
Explanation
For this test case, a simple graph with 2 vertices can be designed, where each vertex has degree 1.
Input
2
3
1 2 1
3
1 1 1
Output
YES
NO
Explanation
For the first test case, we can design a simple graph of 3 vertices, which has degree sequence as [1, 2, 1]. The first vertex has degree 1, second, has 2 and third has 1.
For the second test case, we cannot make a simple graph of 3 vertices, which has degree sequence as [1, 1, 1].
One necessery condition is that sum of elements in A is even. That is due each edge
is counted twice in adjencency list.
Next is to try to construct graph, or at least 'allocate' pairs of nodes.
Sort elements of A in decending order,
Let the largest (first) element be a,
Check are element on positions 2 to a+1 larger than 0,
If there is a element with value 0 than it is not possible to construct a graph,
Decrease these a elements by 1 and set first element to 0,
Repeat process until all elements are 0.
Note that sorting in subsequent steps can be done in O(n) with merge sort step, since list consists
of three sorted parts:
first element (0) which can go to the end,
sorted part with a elements,
rest which is also sorted.

Optimize algorithm to find intersection points in 2d roads (lines)

I have a list of Lines which represent Roads such that each road has a "StartingPoint" and an "EndingPoint". My goal is to find "Next" road of each road. A road is Next of another road if its starting point OR ending point falls on top of the starting point or ending point of another road. For example :
Road A : starting point of : (0,0) and ending point of (2,0)
Road B : starting point of : (2,0) and ending point of (5,0)
Road C: starting point of : (2,0) and ending point of (4,2)
So Roads Next is will be :
A NEXT { B , C}
B NEXT { A }
C NEXT { A }
My current algorthim is doing it in O(n^2) by comparing every starting point of a road to starting and ending of another road. How can make this faster. I think sorting the roads might work but I'm not sure. Please tell me what you think!
Note: Those who are saying use Hashmap<Start/EndPoint,Road> your solution is still O(N^2).
It depends what you want to do with the result. The result of your calculation is of size O(#roads^2). This means that if you want to iterate over it then you will need O(#roads^2) at best. This being said if you just want to be able to answer questions like "return all adjacencies of a given road" then you can do that in O(#roads) with the algorithm you implemented.
In Java, a HashMap<XYPoint, HashSet<Road>> endPoints, and another HashMap<Road, HashSet<Road> next should suffice; assuming your Road objects have a ending and starting XYPoint s. The logic would go as follows:
for each road R,
add it, using its starting point, to the endPoints map; and
for each road X with a co-incident endpoint,
next.put(R, X); next.put(X, R);
add it, using its ending point, to the map endPoints map; and
for each road X with a co-incident endpoint,
next.put(R, X); next.put(X, R);
At the end of this procedure, your next map would contain the next roads for each road. You would just have to iterate this map to generate the desired output.
If there are no next roads, the algorithm is O(n). In the worst case (all roads have the same starting and ending points), it is O(n^2); you can eliminate this by using suitable equals/hashcode for your Roads, at the cost of some extra complexity (you would need to count repetitions).
In my opinion, the easiest way to do this is to create a class Cell that would represent a certain point like (x;y). Override equals and hashCode of Cell and then simply store your Cell objects in a HashMap that guaranties a high speed of retrieving its elements.
There's an O(n log n) algorithm, I'm not sure if there are any that are superior.
You can:
1) Create a Point class that consists of a 2D point, and a pointer to the road that it has an endpoint (starting point or ending point) of.
2) Create an Array twice as big as your collection of roads
3) Loop through all roads, and add a Point representing both the starting point or the ending point to an Array - have said Point point back to the road that created it.
4) Order the array using the sort of your choice. You can use a lot of sorting functions, but since you're writing code I would say you use one that first sorts by y, then uses x to tiebreak on equal y's. So:
if ( a.y < b.y ) return -1;
if ( a.y > b.y ) return 1;
if ( a.x < b.x ) return -1;
if ( a.x > b.x ) return 1;
return 0;
Only for points you should probably rewrite it as non-branching if you care about speed.
5) Adjacent points may be the same. Non-adjacent points are certainly not. Run through the ordered array in O(n) time. Points refer back to their roads. Combine as you see fit.
The storage of your final result doesn't have to be of size O(roads^2) if you allow 3 things:
Store separate sub-lists for roads that overlap a road's start point and its end point. You can just concatenate the two lists together to get a road's complete next list when looking it up, or iterate through one and then the other.
Share lists between roads. The start point list of one road might be another road's start or end point list. In other words, for each point there is a single list of all roads that either start or end there.
Allow a road to be a member of its own lists (and just ignore it when retrieving the list).
The hash map you need is HashMap<XYPoint, List<Road>>
For each road, store List<Road> startList and endList
The algorithm is (pseudo-code):
For each road in list
For point in [start, end]
Look up List<Road> roadlist from hash map based on point X,Y
If null then
roadlist = new List<Road>
add road to roadlist
add roadlist to hash map
else
add road to roadList
set roadList as either road.startList or road.endList
You only add each road to a List twice. Assuming hash lookups and adds are O(1) then this should be O(n).

Skip list in java

I was going through data structures in java under the topic Skip list and I came across the following:
In a skip list of n nodes, for each k and i such that 1 ≤ k ≤lg n and 1 ≤ i ≤
n/2k–1⎦ – 1, the node in position 2k–1 · i points to the node in position 2k–1 · (i + 1).
This means that every second node points to the node two positions ahead, every
fourth node points to the node four positions ahead, and so on, as shown in Figure
3.17a. This is accomplished by having different numbers of reference fields in nodes
on the list: Half of the nodes have just one reference field, one-fourth of the nodes
have two reference fields, one-eighth of the nodes have three reference fields, and so
on. The number of reference fields indicates the level of each node, and the number of
levels is maxLevel = ⎣lg n⎦ + 1.
And the figure is :
A skip list with (a) evenly and (b) unevenly spaced nodes of different levels;
(c) the skip list with reference nodes clearly shown.
I don't understand the mathematical part and what exactly the sktip list is and even nodes?
Ok let me try to make you understand this.
A skip list is a data-structure which definitely makes your searches faster in a list of given elements.
A better analogy would be a network of subway in any of the bigger cities. Imagine there are 90 stations to cover and there are different lines (Green, Yellow and Blue).
The Green line only connects the stations numbered 0, 30, 60 and 90
The Yellow line connects 0, 10, 20, 30, 40, 50, 60, 70, 80 and 90
The blue line connects all the station from 0 through 90.
If you want to board the train at station 0 and want to get down at 75. What is the best strategy?
Common sense would suggest to board a train on Green line from station 0 and get down at station 60.
Board another train on Yellow line from station 60 and get down at station 70.
Board another train on Blue line from station 70 and get down at 75.
Any other way would have been more time consuming.
Now replace the stations with the nodes and lines with three individual lists (the set of these lists are called skip list).
And just imaging that you wanted to search an element at a node containing the value 75.
I hope this explains what Skip Lists are and how they are efficient.
In the traditional approach of searching, you could have visited each node and got to 75 in 75 hops.
In case of binary search you would have done it in logN
In skip list you can do the same in 1 + 1 + 15 in our particular case. You can do the math, seems to be simple though :)
EDIT: Evenly spaced nodes & Unevenly spaced nodes
As you can see my analogy, it has equal number of stations between each node on each line.
This is evenly spaced nodes. It is an ideal situation.
To understand it better we need to understand the creation of Skip Lists.
In the early stages of its construction there is only one list (the blue line) and each new node is first added to the list at an appropriate location. When the number of nodes in the blue line increases then there comes a need to create another list (yellow line) and promote one of the nodes to list 2. (PS: The first and the last element of list 1 is always promoted to the newly added list in the skip lists set). Hence, the moment a new list is added it will have three nodes.
Promotion Strategy : How to find out which node to promote from the bottom most list(blue line) to the upper lists (yellow line and green line).
The best way to decide is randomly :) So lets say upon addition of a new node, we flip a coin to see if it can be promoted to the second list. if yes, then we add it to the second list and then flip a coin again to check if it has to be added in the third list or not.
So you see, if you use this random mechanism, there might arrive situations where the nodes are unevenly spaced. :)
Hope this helps.

Categories