I'm looking for an algorithm that given a set of number pairs as below, can pair them in such a way that each group contains four unique numbers ie [1,2,3,4]
Any ideas?
[1, 2]
[1, 3]
[1, 4]
[1, 5]
[2, 3]
[2, 4]
[2, 5]
[3, 4]
[3, 5]
[4, 5]
You can think of this as a maximum matching problem. In the maximum matching problem, you have a collection of items (nodes) and possible links between them (edges). The goal is to pair off the items using only the possible links so that as many items as possible are paired off.
In your case, your items are the pairs, and you'd say that two pairs can be linked if they have no numbers in common.
Once you've set things up this way, you can use an off-the-shelf solver for maximum matching to find the optimal pairing. Python's networkx package has the support to do this, for example.
Hope this helps!
Related
I am faced with this optimization challenge:
Take for example the array, [1, 2, 4, 3, 3, 6, 2, 1, 6, 7, 4, 2]
I want to split this into multiple sub-arrays, such that their sums are as close to a target sum. Say, 7.
The only condition I have is the sums cannot be more that the target sum.
Using a greedy approach, I can split them as
[1, 2, 4], [3, 3, 1], [6], [2, 4], [6], [7], [2]
The subset sums are 7, 7, 6, 6, 6, 7 and 2.
Another approach I tried is as follows:
Sort the array, in reverse.
Set up a running total initialized to 0, and an empty subset.
If the list is empty, proceed to Step 6.
Going down the list, pick the first number, which when added to the running total does not exceed the target sum. If no such element is found, proceed to Step 6, else proceed to Step 5.
Remove this element from the list, add it to the subset, and update running total. Repeat from step 3.
Print the current subset, clear the running total and subset. If the list isn't empty, repeat from Step 3. Else proceed to Step 7.
You're done!
This approach produced the following split:
[7], [6, 1], [6, 1], [4, 3], [4, 3], [2, 2, 2]
The subset sum was much more even: 7, 7, 7, 7, 7 and 6.
Is this the best strategy?
Any help is greatly appreciated!
I think you should use the terms "subset" and "sub-array" carefully. What you are looking for is "subset".
The best strategy here would be to write the recursive solution that tries each possibility of forming a subset so that the sum remains <= maximum allowed sum.
If you carefully understand what the recursion does, you'll understand that some sub-problems are being solved again and again. So, you can (memoize) store the solutions to the sub-problems and re-use them. Thus, reading about dynamic programming will help you.
I have array of size N, I need to generate all permutations variants of size K from this array. Variants [1 2 3] and [3 1 2] are different. Standard solutions which I found were
1) Just permutations, where I obtain all reordering of the same size as array.
2) Just combinations, where I obtain all combinations of size K from array of size N, but for these algorithms [1 2 6] and [6 1 2] are the same, while I need them to be different.
Could You help me to find an effective solution?
I should implement it on Matlab, but I hope I will be able to translate Your solutions from other languages.
Basically, in any language which can produce all unordered subsets of size K from 1:N, and which can produce all permutations of 1:K, getting all the ordered subsets is as simple as iterating over the subsets and permuting them using every K-permutation.
In Julia language:
using Combinatorics, Iterators, Base.Iterators
N = 4
K = 2
collect(flatten(permutations(subset) for subset in subsets(1:N,K)))
Gives:
12-element Array{Array{Int64,1},1}:
[1, 2]
[2, 1]
[1, 3]
[3, 1]
[1, 4]
[4, 1]
[2, 3]
[3, 2]
[2, 4]
[4, 2]
[3, 4]
[4, 3]
Combine the two solutions you found. Here's the python code:
allPermutations = list()
combinations=getCombinations(arr, K)
for comb in combinations:
allPermutations.extend(getPermutations(comb))
1.arr is the input array.
2.getCombinations is a function which returns a list of all the combinations in arr of size K.
3.getPermutations returns all permutations of the array given as input.
The task says: the numbers are represented by lists (e.g. 123 = [1, 2, 3]), write a predicate which adds two such numbers. (e.g. sum([4, 5, 6], [9], [4, 6, 5])).
I have been thinking how to express this recursively but what trips me up is when the sizes of the arrays vary. It seems, that this would be simple if the arrays were reverted, so that HEAD is actually the last element. Because the problem for me is that my sum looks like that that:
[4, 5, 6]
+
[9]
instead of
[4, 5, 6]
+
[9]
What could be the proper way to write such predicate? I need some pointers or reference for help...
Here is my implementation:
sum(L1,L2,OutL):-
reverse(L1,List1),reverse(L2,List2),
add_lists(List1,List2,0,List3),
reverse(List3,OutL).
add_lists([],[],0,[]).
add_lists([],[],1,[1]).
add_lists([],[H|T],C,[H1|T]):-H1 is H+C.
add_lists([H|T],[],C,[H1|T]):-H1 is H+C.
add_lists([H|T],[H1|T1],C,[H2|T2]):-NH is H1+H,
(NH > 10 -> NC is 1,H2 is NH+C-10; H2 is NH+C,NC is 0),
add_lists(T,T1,NC,T2).
The idea is to reverse lists in order to add right positions and avoid the problem you referred. Also you just keep a carry which is 1 if an addition is greater than 10 where you reduce 10.
Example:
?- sum([4, 5, 6], [9], L).
L = [4, 6, 5] ;
false.
I want to generate a pair of random numbers withing a range but also the pair must not be contained in an array of pairs I have, so you can basically think of the task as generating a random pair with exceptions. I know you can do it with a loop but I've been told it's possible with only one level of indentation. I've been searching around for something similar, so far no results. Your help would be much obliged, cheers.
Very inefficient, but expressive and short:
range = (1..3).to_a
undesired_pairs = [[1, 1], [2, 2], [3, 3]]
(range.product(range) - undesired_pairs).sample # => [1, 3]
Another solution: Create a random pair until you have a result, that is not in undesired_pairs:
undesired_pairs = [[1, 1], [2, 2], [3, 3]]
until ! undesired_pairs.include?(hit =[rand(3)+1,rand(3)+1])
end
p hit
I have created several arrays, containing multiple integers. Now i want the integers to be sorted, lowest first. Say for instance, i have this in an array: 6,6,1,2,4,4, i want it to be sorted: 1,2,4,4,6,6. Also, is there anyway i can make ruby recognize the 4 lowest values, and display them somehow? I have tried to mess around with .show, but since im quite new to programming i'm rather confused by the results i receive.
did you try this?
a = [6,6,1,2,4,4]
p a.sort
#=> [1, 2, 4, 4, 6, 6]
sort will sort in ascending order.
if you need them sorted in descending order, use sort with a block:
p a.sort {|a,b| b <=> a}
#=> [6, 6, 4, 4, 2, 1]
UPDATE: not sure how i missed the part about lowest values ...
thank you #Mladen
a.sort.take(4)
#=> [1, 2, 4, 4]