How would I code an algorithm that does as follow? - algorithm

I have three arrays of six red numbers ranging from 1 to 6. There can be multiple times the same number.
For example, [1, 4, 3, 3, 6, 2], [5, 5, 2, 1, 3, 4] and [2, 4, 3, 1, 1, 6]
The goal of the algorithm is to turn numbers blue in those arrays following these rules:
Every blue number has to be unique (1, 2, 3, 4, 5, 6)
Each array should have 2 blue numbers
The algorithm should warn me if it isn't possible to do so
In this example, the blue numbers could be (1, 4) in array one, (2, 5) in array two and (3, 6) in array three.
Is it realistic to code an algorithm that could do that? I'm looking for the logic that I could code to make it work.

You can reduce this problem to bipartite matching.
If we consider two sets of vertices, one for the arrays and one for the numbers, and make an edge between the array A and number n if n is an element of A, then we have a bipartite graph on which we can use any matching algorithm. Then, each match between an array and a number indicates that that number is blue in that array.
This only works for making a single number blue for each array, but can be expanded by adding every array as a vertex twice, thus getting two matches per array and therefore two blue numbers per array.

Related

Connected Component Range Query

A graph consisting of n nodes, where there is an edge from 1 to 2, 2 to 3, 3 to 4, ........, n-1 to n.
Now, there is an array consisting of permutation of 1 to n and there are number of queries given based on array segments. Determine number of connected components formed by the nodes(indicated by the array elements) for the given segment. For e.g.,
Array : 4 5 3 2 1
Queries are : [1, 5], [1, 4], [2, 4]
For [1, 5], array elements are 1 2 3 4 5 and all are connected and forms a single connected component.
For [1, 4], array elements are 2 3 4 5, they also forms a single connected component.
For [2, 4], array elements are 2 3 5, so 2 and 3 forms a single component and 5 forms a single component so total of 2 connected components are there in [2, 4].
Since the graph has no cycles, the number of components in the subgraph is equal to the number of vertices minus the number of edges. The number of vertices is the length of the query interval. The number of edges can be found quickly by constructing an oracle for 2D orthogonal range counting queries on points that are (position of k in the permutation, position of k+1 in the permutation) for all k.

Finding permutations for balanced distribution of values in lists

Sorry for the bad title, but I don't know how to call this.
I have K lists, N elements in each, for example:
[8, 5, 6]
[4, 3, 2]
[6, 5, 0]
and I want to find such a permutation of the lists' elements, so that the sum of elements in first column, second column etc are as close to each other as possible (so the distribution is "fair").
In my example that would be (probably):
[8, 5, 6]
[4, 2, 3] -- the lists contain the same values
[0, 6, 5] just in different order
sums: 12, 13, 14
Is there some more elegant way than finding all the permutations for each list, and brute-force finding the "ideal" combination of them?
I'm not asking for code, just give me a hint how to do it, if you know.
Thanks!
ps. the lists can be quite large, and more of them - think ~20x~20 max.
If you can accept an approximation, I would do it iteratively :
Sort matrix lines by descending weight (sum of line elements).
Edit : Sorting first by max element in line could be better.
Each time you are going to add a new line to your result matrix, put smaller elements into higher columns.
Order lines of your result matrix back to their initial state (if you have to).
It works with your example, but will obviously not be always perfect.
Here is an example (javascript)

Combine lists to the least possible amount of 2-dimensional lists

Sorry for the bad description in the title.
Consider a 2-dimensional list such as this:
list = [
[1, 2],
[2, 3],
[3, 4]
]
If I were to extract all possible "vertical" combinations of this list, for a total of 2*2*2=8 combinations, they would be the following sequences:
1, 2, 3
2, 2, 3
1, 3, 3
2, 3, 3
1, 2, 4
2, 2, 4
1, 3, 4
2, 3, 4
Now, let's say I remove some of these sequences. Let's say I only want to keep sequences which have either the number 2 in position #1 OR number 4 in position #3. Then I would be left with these sequences:
2, 2, 3
2, 3, 3
1, 2, 4
2, 2, 4
1, 3, 4
2, 3, 4
The problem
I would like to re-combine these remaining sequences to the least possible amount of 2-dimensional lists needed to contain all sequences but no less or no more.
By doing so, the resulting 2-dimensional lists in this particular example would be:
list_1 = [
[2],
[2, 3],
[3, 4]
]
list_2 = [
[1],
[2, 3],
[4]
]
In this particular case, the resulting lists can be thought out. But how would I go about if there were thousands of sequences yielding hundereds of 2-dimensional lists? I have been trying to come up with a good algorithm for two weeks now, but I am getting nowhere near a satisfying result.
Divide et impera, or divide and conquer. If we have a logical expression, stating that the value at position x should be a or the value at position y should be b, then we have 3 cases:
a is the value at position x and b is the value at position y
a is the value at position x and b is not the value at position y
a is not the value at position x and b is the value at position y
So, first you generate all your scenarios, you know now that you have 3 scenarios.
Then, you effectively separate your cases and handle all of them in a sub-routine as they were your main tasks. The philosophy behind divide et imera is to reduce your complex problem into several similar, but less complex problems, until you reach triviality.

Parallel algorithm for set intersections

I have n-sets (distributed on n-ranks) of data which represents the nodes of a mesh and I wanted to know an efficient parallel algorithm to find the intersection of these sets, i.e., the common nodes. An intersection is defined as soon as any 2 sets share a node.
For example;
Input:
Rank 0: Set 1 - [0, 1, 2, 3, 4]
Rank 1: Set 2 - [2, 4, 5, 6]
Rank 2: Set 3 - [0, 5, 6, 7, 8]
Implement Parallel Algorithm --> Result: (after finding intersections)
Rank 0: [0, 2, 4]
Rank 1: [2, 4, 5, 6]
Rank 2: [0, 5, 6]
The algorithm needs to be done on n-ranks with 1 set on each rank.
You should be able to this fast O(N), in parallel, with hash tables.
For each set S_i, for each member m_x (all of which can be done in parallel), put the set member into a hash table associated with the set name, e.g., . Anytime you get a hit in the hash table on m_x from set S_j, you now have the corresponding set number S_i, and you know immediately that S_i intersects S_j. You can put m_x in the derived intersection sets.
You need a parallel-safe hash table. That's easy; lock the buckets during updates.
[Another answer suggested sorting the sets. With most sort algorithms, would be O(N ln N) time, not as fast].

Find the middle element in merged arrays in O(logn)

We have two sorted arrays of the same size n. Let's call the array a and b.
How to find the middle element in an sorted array merged by a and b?
Example:
n = 4
a = [1, 2, 3, 4]
b = [3, 4, 5, 6]
merged = [1, 2, 3, 3, 4, 4, 5, 6]
mid_element = merged[(0 + merged.length - 1) / 2] = merged[3] = 3
More complicated cases:
Case 1:
a = [1, 2, 3, 4]
b = [3, 4, 5, 6]
Case 2:
a = [1, 2, 3, 4, 8]
b = [3, 4, 5, 6, 7]
Case 3:
a = [1, 2, 3, 4, 8]
b = [0, 4, 5, 6, 7]
Case 4:
a = [1, 3, 5, 7]
b = [2, 4, 6, 8]
Time required: O(log n). Any ideas?
Look at the middle of both the arrays. Let's say one value is smaller and the other is bigger.
Discard the lower half of the array with the smaller value. Discard the upper half of the array with the higher value. Now we are left with half of what we started with.
Rinse and repeat until only one element is left in each array. Return the smaller of those two.
If the two middle values are the same, then pick arbitrarily.
Credits: Bill Li's blog
Quite interesting task. I'm not sure about O(logn), but solution O((logn)^2) is obvious for me.
If you know position of some element in first array then you can find how many elements are smaller in both arrays then this value (you know already how many smaller elements are in first array and you can find count of smaller elements in second array using binary search - so just sum up this two numbers). So if you know that number of smaller elements in both arrays is less than N, you should look in to the upper half in first array, otherwise you should move to the lower half. So you will get general binary search with internal binary search. Overall complexity will be O((logn)^2)
Note: if you will not find median in first array then start initial search in the second array. This will not have impact on complexity
So, having
n = 4 and a = [1, 2, 3, 4] and b = [3, 4, 5, 6]
You know the k-th position in result array in advance based on n, which is equal to n.
The result n-th element could be in first array or second.
Let's first assume that element is in first array then
do binary search taking middle element from [l,r], at the beginning l = 0, r = 3;
So taking middle element you know how many elements in the same array smaller, which is middle - 1.
Knowing that middle-1 element is less and knowing you need n-th element you may have [n - (middle-1)]th element from second array to be smaller, greater. If that's greater and previos element is smaller that it's what you need, if it's greater and previous is also greater we need to L = middle, if it's smaller r = middle.
Than do the same for the second array in case you did not find solution for first.
In total log(n) + log(n)

Resources