I'd like to detect a "complete loop". Let's suppose that lists are connectable if the first value of a list is equal to the end value of another list. For example, we may have 5 lists like below.
a1 = [1, 14, 0]
a2 = [2, 14, 3]
a3 = [0, 14, 2]
a4 = [3, 14, 1]
a5 = [0, 14, 3]
where a1, a3, a2, and a4 can be connected to each other, forming a "complete loop" as a4 and a1 can also be connected. So the output shall be [a1, a3, a2, a4].
(It looked like as if it were an NP-Hard Problem, but I think I was wrong!) I've tried solutions such as Doubly Linked List or Hash Table, but it somehow then turned out to be recursive programming, which I'm terrible at and was not very successful.
Of course, I may just generate all the permutations and check one by one. Can there be a more beautiful way?
This is not NP-hard. Conceptually, this problem is known as 'cycle detection' and is a part of graph theory.
If you would like to see the code approaches to cycle detection, here is a decent beginner's tutorial:
https://www.tutorialspoint.com/Detect-Cycle-in-a-an-Undirected-Graph
https://www.techiedelight.com/check-undirected-graph-contains-cycle-not
If this problem was NP-hard, we wouldn't be able to do a lot of relatively-important things like dependency calculations and circular reference detection.
Related
This question already has answers here:
Ruby - array intersection (with duplicates)
(7 answers)
Closed 1 year ago.
I have two arrays
a1 = [1, 1, 1, 2, 3, 3, 3]
a2 = [1, 1, 3, 3, 5, 5]
I want to return the values that appear in both arrays AND the exact amount that they appear
# => [1, 1, 3, 3]
I can't use a1 & a2 because that will return unique values ([1, 3])
What's the best way to achieve this?
It looks like what you have there are not really arrays, they are multisets or bags.
There is a general rule in programming: if you choose your data representation right, your algorithms become simpler.
So, if you use multisets instead of arrays, your problem will become trivial, since what you are looking for is literally just the intersection of two multisets.
Unfortunately, there is no multiset implementation in the core or standard libraries, but there are a couple of multiset gems available on the web. For example, there is the multimap gem, which also includes a multiset. Unfortunately, it needs a little bit of love and care, since it uses a C extension that only works until YARV 2.2. There is also the multiset gem.
require 'multiset'
m1 = Multiset.new(a1)
#=> #<Multiset:#3 1, #1 2, #3 3>
m2 = Multiset.new(a2)
#=> #<Multiset:#2 1, #2 3, #2 5>
m = m1 & m2
#=> #<Multiset:#2 1, #2 3>
Personally, I am not too big a fan of the inspect output, but we can see what's going on and that the result is correct: m contains 2 × 1 and 2 × 3.
If you really need the result as an Array, you can use Multiset#to_a:
m.to_a
#=> [1, 1, 3, 3]
At first I do get the intersection between a1 and a2 with (a1 & a2). After that I iterate over the intersection and check which array has a lower count of each element. The element gets than added to the result array as many times as it occurs in the array with the lower count using result.fill
a1 = [1, 1, 1, 2, 3, 3, 3]
a2 = [1, 1, 3, 3, 5, 5]
result = []
(a1 & a2).each do |e|
a1.count(e) < a2.count(e) ? result.fill(e, result.size, a1.count(e)) : result.fill(e, result.size, a2.count(e))
end
pp result
It is known that Knuth's Algorithm X or Dancing Links is used to resolve exact cover problem. But now I have a problem similar with exact cover.
The problem has some overlapped area, different from exact cover. In exact cover, all coverage’s height/weight is 1. But in my problem, the coverage may has different heights (always a positive integer less than 4).
For example, I just want to find the subsets from a gave sets to cover with S [ 2, 1, 3]:
Now, A [1,0,2] and B [1,1,1] are the expected subsets.
S = [2, 1, 3]
A = [1, 0, 2]
B = [1, 1, 1]
C = [0, 1, 0]
D = [1, 1, 0]
Any clue or pager, thank you very much~
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)
How can I check whether one array is a subset of another array, regardless of the order of elements?
a1 = [3, 6, 4]
a2 = [1, 2, 3, 4, 5, 6, 7, 8, 9]
...?
a1 is a subset of a2
Easiest may be:
(a1 - a2).empty?
Use sets. Then you can use set.subset?. Example:
require 'set'
a1 = Set[3,6,4]
a2 = Set[1,2,3,4,5,6,7,8,9]
puts a1.subset?(a2)
Output:
true
See it working online: ideone
The data structure you already have is perfect, just check the intersection:
(a1 & a2) == a1
Update: The comment discussing permutations is interesting and creative, but quite incorrect as the Ruby implementors anticipated this concern and specified that the order of the result is the order of a1. So this does work, and will continue to work in the future. (Arrays are ordered data structures, not sets. You can't just permute the order of an array operation.)
I do rather like Dave Newton's answer for coolness, but this answer also works, and like Dave's, is also core Ruby.
Perhaps not fast, but quite readable
def subset?(a,b)
a.all? {|x| b.include? x}
end
Suppose I have a vector of n elements, and I want to distribute it on p processes, where n isn't necessary a multiple of p. Each process has a rank from 0 to p-1. How to determine how many elements will be on each process, to have data distributed the more evenly possible?
For example, if n=14 and p=4, I want a distribution like [3, 3, 4, 4] or [3, 4, 3, 4], but not [3, 3, 3, 5] nor [4, 4, 4, 2].
I want a function f(n, p, r) that returns me the number of elements for process with rank r.
Does
(n + r) / p
work for you?
This seems to be a special case of the Bin Packing problem. There are some very good approximation algorithms, but in theory it is NP-hard.
If you can't be bothered to read the wiki page, I'll cut it down into a few lines. If you want to look deeper for possibly better solutions, or for an analysis on how well the approximation schemes work, by all means.
Step 1: sort the elements by priority.
Step 2: grab the element with highest priority, and shove it on the least burdened process.
Step 3: If you have more elements, go to Step 1. Else return.