I tried to search for the answer of one problem of my interview. But got no solution. Can anyone help me in this question. Here is the problem Description:
Given two person's name A & B. You know both exist on FB. You have to tell is there any connectivity between them. If connectivity exists then you have to tell the exact path of connectivity.
By Connectivity they mean that B could be a friend of C which is friend of A . In this way the re is a connectivity between A & B and the path would be A -> B- > C
You can use Bidirectional search.
The main idea:
AGroup = {A}, BGroup = {B}.
while intersect(AGroup,BGroup) = empty set:
2.1 Expand every person from AGroup that you have not expanded yet and insert the result to AGroup.
2.2 Expand every person from BGroup that you have not expanded yet and insert the result BGroup.
2.3 if AGroup and BGroup have not changed, return "A and B are not connected".
Denote S the person in both AGroup and in BGroup.
Now you have the path from A to S, and the path from B to S.
Return A->...->S->...->B.
Related
I am working through a book on algorithms and it contains a description of Dijkstra's algorithm with a code sample in Ruby. The code solves a hypothetical problem of finding the cheapest flight path from city A to city B. You cannot necessarily fly directly from A to B, and so there may be multiple flights required to complete your trip.
A City object has a #name that is a String and #routes that is a hash with a City object as the key and ticket price as the value.
For example, the city of Atlanta is defined by
atlanta = City.new("Atlanta")
atlanta.add_route(boston, 100)
atlanta.add_route(denver, 160)
# where the add_route method states that
#routes[city] = price
Further, unvisited_cities is an array of City objects, and cheapest_prices_table is a hash with a city #name as the key and ticket price as the value.
My question is, what does the following code, which is part of the Dijkstra algorithm code sample, do? I am unfamiliar with the syntax unvisited_cities.min do |city|. I placed a puts statement just above the code in question (p unvisited_cities.min), and I received an error: ArgumentError (comparison of City with City failed). I could not find a description of this syntax anywhere to understand exactly what the lines below do. That is, how does the code below set current_city to be the least expensive city to fly to in unvisited_cities?
# We visit our next unvisited city. We choose the one that is cheapest
# to get to from the STARTING city:
current_city = unvisited_cities.min do |city|
cheapest_prices_table[city.name]
end
Thank you!
We have a problem where we want to find the optimal path for swapping employees' locations across the country.
Hypothetically, a company allows for employees to request to move to another city only if a vacancy is available in that city, and also if someone is willing to take their soon-to-be vacant position. Examine the example:
Employee A who currently works in Los Angeles wants to move to Boston.
Employee B who currently works in Boston wants to move to New York.
Employee C who currently works in New York wants to move to Los Angeles.
In the above triangle, we can grant all three employees the permission to do the move, since there won't be any vacancies once they move. But the situation gets more complex when:
Multiple employees are competing for the same location. We can solve this with a hypothetical score of some sort, like more years working for the company gets the priority.
We have more cities to consider. (in the hundreds)
We have more employees to consider. (in the hundreds of thousands)
Ultimately the goal is to grant the highest number of move permissions without leading to any vacancies in the system.
We're currently exploring the idea of simulating all the swapping paths, and then selecting the one that generates the highest number of moves.
But I feel that this problem existed in the wild before, I just don't know what keywords to look for in order to get more insights. Any ideas? What algorithms should we look into?
Remove the impossible move requests, like this
A,B are specific cities. n is amy city
RAB is a request to move from A to B
RAn is a request to move from A
RnA is a reuest to move to A
CAn is the number of requests to move from A
CnA is the number of requests to move to A
set flag TRUE
WHILE ( flag == TRUE )
set flag = FALSE
LOOP A over all cities
IF CAn > CnA then not all RAn can be permitted.
Remove lower scoring requests until CAn == CnA.
set flag TRUE
Once these "impossible" moves are removed, all of the remaining move requests are "in-balance". That is, all of the move requests to a city are equal all of those from a city. From that point on it no longer matters which cycles you choose to implement: once you implement them, the remainings requests are still all in-balance. And no matter which move-cycle and which order they are implemented in, it stays in-balance until all remaining requests are zero, and the total number of moves will be exactly the same no matter how they are implemented. ( This explanation is due to https://stackoverflow.com/users/109122/rbarryyoung )
Here is C++ code implementing this
void removeForbidden()
{
bool flag = true;
while (flag)
{
flag = false;
for (auto &city : sCity)
{
auto vFrom = RequestCountFrom(city);
auto vTo = RequestCountTo(city);
if (vFrom.size() > vTo.size())
{
for (int k = vTo.size(); k < vFrom.size(); k++)
{
vFrom[k]->allowed = false;
}
flag = true;
}
}
}
std::cout << "Permitted moves:\n";
for (auto &R : vRequest)
{
if (R.allowed)
std::cout << R.text();
}
}
The complete application code is at https://gist.github.com/JamesBremner/5f49beaca59a7a7043e356fbb35f0d09
The input is a space delimited text file with 4 columns: employee name, employee score, from city, to city
Here is sample input based on your example but adding another request that cannot be permitted
e1 1 a b
e2 1 b c
e3 1 c a
e4 0 a c
The output from this is
Permitted moves:
e1 1 a b
e2 1 b c
e3 1 c a
Note: I have not implemented the scoring. For simplicity I assume that move requests are entered in order of descending score. So, the requests that are dropped when necessary, change according to the order you enter them. I assume you will be able to implement whatever scoring system you require. Also note that, unless you calculate a unique score for every request from a city, then which requests are denied may vary with the order of input.
I was about to post this in a comment but it was more than the the actually allowed characters.
I'm not sure about existing advanced algorithms that could potentially solve this problem, but you can custom fit some fundamental ones:
An employee wanting to move from city1 to some city2 is a directed edge from city1 to city2. Make sure that if 2 employees want to move from A to B, you add 2 directed edges for that or somehow keep count of the quantity.
Find disjoint components of the graph.
In each disjoint component, find the largest possible circle. A circle means A -> B -> C -> A.
Remove those edges and keep count of the number of successful swaps.
Rpeat until there are no circles in any of the disjoint components.
This is a greedy algorithm. At the moment I'm still not quite sure if it would produce the optimal solution in each and every situation. Any input is appreciated.
I'm using neo4j as a graph database to store user's connections detail into this. here I want to show the level of one user with respect to another user in their connections like Linkedin. for example- first layer connection, second layer connection, third layer and above the third layer shows 3+. but I don't know how this happens using neo4j. i searched for this but couldn't find any solution for this. if anybody knows about this then please help me to implement this functionality.
To find the shortest "connection level" between 2 specific people, just get the shortest path and add 1:
MATCH path = shortestpath((p1:Person)-[*..]-(p2:Person))
WHERE p1.id = 1 AND p2.id = 2
RETURN LENGTH(path) + 1 AS level
NOTE: You may want to put a reasonable upper bound on the variable-length relationship pattern (e.g., [*..6]) to avoid having the query taking too long or running out of memory in a large DB). You should probably ignore very distant connections anyway.
it would be something like this
// get all persons (or users)
MATCH (p:Person)
// create a set of unique combinations , assuring that you do
// not do double work
WITH COLLECT(p) AS personList
UNWIND personList AS personA
UNWIND personList AS personB
WITH personA,personB
WHERE id(personA) < id(personB)
// find the shortest path between any two nodes
MATCH path=shortestPath( (personA)-[:LINKED_TO*]-(personB) )
// return the distance ( = path length) between the two nodes
RETURN personA.name AS nameA,
personB.name AS nameB,
CASE WHEN length(path) > 3 THEN '3+'
ELSE toString(length(path))
END AS distance
I have rather large dataset (20mln nodes, 200mln edges), simplest shortestPath queries finish in milliseconds, everything is great.
But... I need to allow shortestPath to have ZERO or ONE relation of type 999 and it can be only the first from the start node.
So, my query became like this:
MATCH (one:Obj{oid:'startID'})-[r1*0..1]-(b:Obj)
WHERE all(rel in r1 where rel.val = 999)
WITH one, b
MATCH (two:Obj{oid:'endID'}), path=shortestPath((one) -[0..21]-(two))
WHERE ALL (x IN RELATIONSHIPS(path)
WHERE (x.val > -1 and x.val<101) or (x.val=999 or x.val=998)) return path
it runs in milliseconds when there's a short path (up to 2-4), but can take 5 or 20 seconds for paths like 5++. Maybe I've composed inefficient query?
This question will be bountied when available.
Some of your requirements are a bit unclear to me, so I'll reiterate my understanding and offer a solution.
You want to inspect the shortest paths between a start and end node.
The paths returned should have ZERO or ONE relationship with a val of 999. If it's ONE relationship with that value, it should be the first.
Here's an attempt based on that logic:
MATCH (start:Obj {oid:'startID'}),
(end:Obj {oid:'endID'}),
path=shortestPath((start)-[1..21]->(end))
WITH path, relationships(path) AS rels
WHERE all(r IN relationships WHERE r.val != 999)
OR (relationships[0].val = 999
AND all(r IN relationships[1..] WHERE r.val != 999))
RETURN path
I haven't had a chance to test on actual data, but hopefully this logic and approach at least point you in the right direction.
Also note: it's possible the entire WHERE clause at the end could be reduced to:
WHERE all(r IN relationships[1..] WHERE r.val != 999)
Meaning you don't even need to check the first relationship.
I currently have a worksheet that I have multiple people filling out every day. There are 4 columns that the users fill out: C, E, H, & J (all numerical values, one row per day of the month.)
The users fill in C, E, & H every day no matter what, but a lot of days there is no value to put in column J. I need the value in J to be set to 0 if the user doesn't enter anything. Of course it would be easier to just have the users enter 0, but I'm working with a complicated group of people here.
Anyway, I want to use a macro that runs automatically when the user clicks the save button (before it actually saves, of course), and have it do the following: (I am more familiar with php, so I'm just typing this out how I'm familiar - I'm sure my syntax is incorrect)
Foreach Row
If "column A" != "" {
If "column J" != "" {
//Everything is good, continue on...
} else {
CurrentRow.ColumnJ.value == 0
}//Value has been set - continue loop
}
//column A is blank, this day hasn't come yet - quit looping here
End Foreach
If anyone could help me out with this I'd appreciate it. With some research, this is what I've come up with so far, and now I'm stuckā¦
Private Sub Workbook_BeforeSave(ByVal SaveAsUI As Boolean, Cancel As Boolean)
Dim curCell As Range
'Labor Flow Sheet'.Select
For Each curCell in Range( ???? )
If curCell.Value = "" Then
???????
End If
Next curCell
End Sub
Thanks in advance!
See this link about finding the right range, and as for the question marks inside the If statement, you would want to put
curCell.Value = 0
For the question marks in your statement
For Each curCell in Range( ???? )
Solution 1:
To find the full range you're working with, you'll need to use a column that is filled out each day. You mentioned columns C, E, and H were filled out every day. Using one of those columns (let's pick C for the example here), you could find the range by using the .end method. This goes out either up down left or right from a range until it doesn't find any data. So,
Range("J1", Range("C1").End(xlDown)).Select
will select all cells from J1 (or whatever column is the last in your sheet) to the bottom-most cell containing data in column C, automatically.
Solution 2:
Manually put in the range. For example, to choose A1 to J300:
Range("A1", "J300").Select