Are there any algorithm that solves the following problem in time less than O(n!)? - algorithm

Are there any algorithm that solves the following problem in time less than O(n!), like polynomial time?
Otherwise, for this problem, does not anyone have found any polynomial time algorithm, like NP problems?
Input: n (number of elements)
Output: a list of all combinations of two, where, from top of the list, each unit of combinations of n/2 must have all elements.
Example 1
Input: n=4
Output:
[0, 1], [2, 3],
[0, 2], [1, 3],
[0, 3], [1, 2]
Example 2
Input: n=8
Output:
[0, 1], [2, 3], [4, 5], [6, 7],
[0, 2], [1, 3], [4, 6], [5, 7],
[0, 3], [1, 2], [4, 7], [5, 6],
[0, 4], [1, 5], [2, 6], [3, 7],
[0, 5], [1, 4], [2, 7], [3, 6],
[0, 6], [1, 7], [2, 4], [3, 5],
[0, 7], [1, 6], [2, 5], [3, 4]
P.S.
The following answer does not meet the requirements.
The first two (= n/2) pairs ([0, 1], [0, 2]) do not have "3", so the answer does not meet the condition where "0" and "1", "2", "3" must be in the first two pairs.
>>> n=4
>>> for i in range(0, n-1):
... for j in range(i+1,n):
... print( [i, j] )
...
[0, 1]
[0, 2]
[0, 3]
[1, 2]
[1, 3]
[2, 3]

As I said in my comment, this appears to be a type of (relaxed) Sports League Scheduling problem. If I understand what you are asking for, it can be summarized as follows:
Given a positive even integer N generate a set of n/2 "rounds" of pairings with the following qualities:
A pairing is a pair of two different integers [a, b] such that a and b are integers from 0..n-1 and a < b.
A round consists of n/2 pairings, such that every element from 0..n-1 appears exactly once in a pairing in the round, and
All pairings are unique across all rounds (that is no pairing ever appears more than once in the complete solution).
Assuming that this is a correct formulation of your problem, then the answer is
Yes, this can be done in O(n^2).
Further, not only can it be done, there exists a simple method to solve it for any even N:
For the first round, make n-1 pairs, filling in the first element of the pairs with the integers from 0 to (n/2)-1 going left-to-right. This how it would look for N=8:
[0, ], [1, ], [2, ], [3, ]
Then, fill in the second elements with (n/2) to n-1, but going right-to-left:
[0, 7], [1, 6], [2, 5], [3, 4]
This completes your first round.
For the next round, copy the first round, but keeping 0 in the same place, move the remaining left-side elements up the list, and the right-side elements down the list. When an element reaches the end of the list, reverse direction and swap them from first elements to second elements (or vice-versa):
----------------------->
[0, 7], [1, 6], [2, 5], [3, 4]
<-----------------------
Becomes
----------------------->
[0, 6], [7, 5], [1, 4], [2, 3]
<-----------------------
Now you just continue this process until you have N/2 rounds:
[0, 7], [1, 6], [2, 5], [3, 4]
[0, 6], [7, 5], [1, 4], [2, 3]
[0, 5], [6, 4], [7, 3], [1, 2]
[0, 4], [5, 3], [6, 2], [7, 1]
Finally swap any pairings where the first element happens to be greater than the second:
[0, 7], [1, 6], [2, 5], [3, 4]
[0, 6], [5, 7], [1, 4], [2, 3]
[0, 5], [4, 6], [3, 7], [1, 2]
[0, 4], [3, 5], [2, 6], [1, 7]
If you check this solution you will find that it fulfills all of the constraints. This solutions works for any even value of N and obviously runs in O(n^2) time.

Yes, this problem can be solved in quadratic time. It is not too hard to explicitly construct these pairings.
It is quite helpful to consider a regular (n-1)-gon with one additional point in the middle. Then take the lines through one of the (n-1) endpoints and the midpoint and choose the pairs given by the symmetry of this line.

Related

Why does this recursive Prolog predicate add some "_1508"-like numbers to lists?

My task is to split a given sorted list (LSorted) into several other ones, where the first one would contain values from the LSorted that are smaller than the first prime number (1 is not considered prime) (from Primes list), the second one would contain values from LSorted smaller than the second prime number but greater or equal to the first prime, etc.
ans(L, Res):-
max_list(L, X), /*determine the max value X of L*/
listPrimes(X, Primes), /*generate a list of primes up to X and the prime greater than X*/
msort(L, LSorted), /*sort L*/
ans_recur(LSorted, Primes, Res),!.
ans_recur([], _, [[]|[]]).
ans_recur([InH|Input], [PrimeH|Primes], [[InH|Res]|ResT]):-
InH < PrimeH,
ans_recur(Input, [PrimeH|Primes], [Res|ResT]).
ans_recur([InH|Input], [_|Primes], [_|ResT]):-
ans_recur([InH|Input], Primes, ResT).
When I run a query: ans([1,2,3,4], L)., I get this result:
L = [_1508, [1|_1522], [2|_1534], [3, 4]], while I expect [[1], [2], [3,4]]. The program does "put" the numbers into the "correct" lists, but adds some values like _1508.
As far as I understand, the reason for that is that Prolog is trying to assign some value to Res in ans_recur predicate, but why does it do that?
Tracing:
Call:ans([1, 1, 2, 2, 3, 4], _13636)
Call:lists:max_list([1, 1, 2, 2, 3, 4], _14050)
Exit:lists:max_list([1, 1, 2, 2, 3, 4], 4)
Call:listPrimes(4, _14080)
Exit:listPrimes(4, [1, 2, 3, 5])
Call:sort([1, 1, 2, 2, 3, 4], _14224)
Exit:sort([1, 1, 2, 2, 3, 4], [1, 2, 3, 4])
Call:ans_recur([1, 2, 3, 4], [1, 2, 3, 5], _13636)
Call:1<1
Fail:1<1
Redo:ans_recur([1, 2, 3, 4], [1, 2, 3, 5], _13636)
Call:ans_recur([1, 2, 3, 4], [2, 3, 5], _14156)
Call:1<2
Exit:1<2
Call:ans_recur([2, 3, 4], [2, 3, 5], [_14174|_14168])
Call:2<2
Fail:2<2
Redo:ans_recur([2, 3, 4], [2, 3, 5], [_14174|_14168])
Call:ans_recur([2, 3, 4], [3, 5], _14168)
Call:2<3
Exit:2<3
Call:ans_recur([3, 4], [3, 5], [_14204|_14198])
Call:3<3
Fail:3<3
Redo:ans_recur([3, 4], [3, 5], [_14204|_14198])
Call:ans_recur([3, 4], [5], _14198)
Call:3<5
Exit:3<5
Call:ans_recur([4], [5], [_14234|_14228])
Call:4<5
Exit:4<5
Call:ans_recur([], [5], [_14252|_14228])
Exit:ans_recur([], [5], [[]])
Exit:ans_recur([4], [5], [[4]])
Exit:ans_recur([3, 4], [5], [[3, 4]])
Exit:ans_recur([3, 4], [3, 5], [_14204, [3, 4]])
Exit:ans_recur([2, 3, 4], [3, 5], [[2|_14204], [3, 4]])
Exit:ans_recur([2, 3, 4], [2, 3, 5], [_14174, [2|_14204], [3, 4]])
Exit:ans_recur([1, 2, 3, 4], [2, 3, 5], [[1|_14174], [2|_14204], [3, 4]])
Exit:ans_recur([1, 2, 3, 4], [1, 2, 3, 5], [_14154, [1|_14174], [2|_14204], [3, 4]])
Exit:ans([1, 1, 2, 2, 3, 4], [_14154, [1|_14174], [2|_14204], [3, 4]])
L = [_1282, [1|_1296], [2|_1308], [3, 4]]
Thanks in advance.
ans_recur([InH|Input], [PrimeH|Primes], [[InH|Res]|ResT]):-
InH < PrimeH,
ans_recur(Input, [PrimeH|Primes], [Res|ResT]).
ans_recur([InH|Input], [_|Primes], [_|ResT]):-
ans_recur([InH|Input], Primes, ResT).
What you are trying to express in these clauses is something like this:
if InH is less than the next prime, it should be part of the current running result
otherwise, it should be part of some later running result
But in the last case, the "current running result" is finished, it has no more elements. So its tail, which is so far open, must be closed. You need to change the head of the last clause accordingly:
ans_recur([InH|Input], [_|Primes], [[]|ResT]):-
This now behaves like this:
?- ans_recur([1,2,3,4,5,6,7,8,9,10], [2,3,5,7,11], Result).
Result = [[1], [2], [3, 4], [5, 6], [7, 8, 9, 10]] ;
Result = [[1], [2], [3, 4], [5], [6, 7, 8, 9|...]] ;
Result = [[1], [2], [3, 4], [], [5, 6, 7, 8|...]] ;
Result = [[1], [2], [3], [4, 5, 6], [7, 8, 9, 10]] . % further incorrect answers
The problem is that you don't express the "otherwise" condition explicitly, and Prolog will not guess implicitly that it was what you meant. You can change the last clause to this:
ans_recur([InH|Input], [PrimeH|Primes], [[]|ResT]):-
InH >= PrimeH,
ans_recur([InH|Input], Primes, ResT).
And only get the expected answer:
?- ans_recur([1,2,3,4,5,6,7,8,9,10], [2,3,5,7,11], Result).
Result = [[1], [2], [3, 4], [5, 6], [7, 8, 9, 10]] ;
false.
As you can see, I only dealt with your implementation of ans_recur/3. There might be more bugs lingering in the rest of the code. We cannot tell because the code you posted is incomplete. In the future, please only post complete programs. Many contributors will not bother to try to complete your question for you, and you will get fewer answers.

Sorting a vector of vectors by multiple elements in Julia

I've had good read of the 'Sorting Functions' section of the Julia manual, and had a look at some of the similar questions that have already been asked on this board, but I don't think I've quite found the answer to my question. Apologies if I've missed something.
Essentially I have a vector of vectors, with the enclosed vectors containing integers. For the purposes of the example, each enclosed vector contains 3 integers, but it could be any number. I want to sort the enclosed vectors by the first element, then by the second element, then by the third element etc.
Let's start with the vector:
v = [[3, 6, 1], [2, 2, 6], [1, 5, 9], [2, 1, 8], [3, 7, 9],
[1, 1, 2], [2, 2, 2], [3, 6, 2], [1, 2, 5], [1, 5, 6],
[3, 7, 4], [2, 1, 4], [2, 2, 1], [3, 1, 2], [1, 2, 8]]
And continue with what I'm actually looking for:
v = [[1, 1, 2], [1, 2, 5], [1, 2, 8], [1, 5, 6], [1, 5, 9],
[2, 1, 4], [2, 1, 8], [2, 2, 1], [2, 2, 2], [2, 2, 6],
[3, 1, 2], [3, 6, 1], [3, 6, 2], [3, 7, 4], [3, 7, 9]]
So there should be no requirement for rocket science.
I can easily sort the vector by the first element of the enclosed vectors by one of two ways:
v = sort(v, lt = (x, y) -> isless(x[1], y[2]))
or:
v = sort(v, by = x -> x[1])
Both these methods produce the same answer:
v = [[1, 5, 9], [1, 1, 2], [1, 2, 5], [1, 5, 6], [1, 2, 8],
[2, 2, 6], [2, 1, 8], [2, 2, 2], [2, 1, 4], [2, 2, 1],
[3, 6, 1], [3, 7, 9], [3, 6, 2], [3, 7, 4], [3, 1, 2]]
So, as you can see, I have sorted by the first element of the enclosed vectors, but not by the subsequent elements.
So, to come back to the question in the title, is there a method of sorting by multiple elements using the sort() function?
I can actually get what I want using loops:
for i = 3:-1:1
v = sort(v, lt = (x, y) -> isless(x[i], y[i]))
end
or:
for i = 3:-1:1
v = sort(v, by = x -> x[i])
end
However, I don't want to re-invent the wheel, so if there's a way of doing it within the sort() function I'd love to learn about it.
You can use lexless function as lt keyword argument that does exactly what you want if I understood your question correctly:
julia> sort(v, lt=lexless)
15-element Array{Array{Int64,1},1}:
[1, 1, 2]
[1, 2, 5]
[1, 2, 8]
[1, 5, 6]
[1, 5, 9]
[2, 1, 4]
[2, 1, 8]
[2, 2, 1]
[2, 2, 2]
[2, 2, 6]
[3, 1, 2]
[3, 6, 1]
[3, 6, 2]
[3, 7, 4]
[3, 7, 9]
EDIT: I have just checked that this is a solution for Julia 0.6. In Julia 0.7 you can simply write:
julia> sort(v)
15-element Array{Array{Int64,1},1}:
[1, 1, 2]
[1, 2, 5]
[1, 2, 8]
[1, 5, 6]
[1, 5, 9]
[2, 1, 4]
[2, 1, 8]
[2, 2, 1]
[2, 2, 2]
[2, 2, 6]
[3, 1, 2]
[3, 6, 1]
[3, 6, 2]
[3, 7, 4]
[3, 7, 9]

Issue with sklearn k nearest neighbors

I wonder if there is a way to force sklearn NearestNeighbors algorithm, to take into account the order of a point in the input array, when there are duplicate points.
To illustrate:
>>> from sklearn.neighbors import NearestNeighbors
>>> import numpy as np
X = np.array([[-1, -1], [-2, -1], [-3, -2], [1, 1], [2, 1], [3, 2]])
nbrs = NearestNeighbors(n_neighbors=2, algorithm='ball_tree').fit(X)
distances, indices = nbrs.kneighbors(X)
indices
>>>> array([[0, 1],
[1, 0],
[2, 1],
[3, 4],
[4, 3],
[5, 4]])
Because the query set matches the training set, the nearest neighbor of each point is the point itself, at a distance of zero. If however, I allow for duplicate points in X, the algorithm, understandably, does not distinguish between the duplicates:
X = np.array([[-1, -1], [-2, -1], [-3, -2], [1, 1], [2, 1],[3, 2],[-1,-1],[-1,-1]])
nbrs = NearestNeighbors(n_neighbors=2, algorithm='auto').fit(X)
distances, indices = nbrs.kneighbors(X)
indices
>>>> array([[6, 0],
[1, 0],
[2, 1],
[3, 4],
[4, 3],
[5, 4],
[6, 0],
[6, 0]])
Ideally, I would like the last output to be something like:
>>>> array([[0, 6],
[1, 0],
[2, 1],
[3, 4],
[4, 3],
[5, 4],
[6, 0],
[7, 6]])
I think you cannot do that, since from the ref we got:
Warning: Regarding the Nearest Neighbors algorithms, if two neighbors,
neighbor k+1 and k, have identical distances but different labels, the
results will depend on the ordering of the training data.

Ruby array product with asterisk

I was studying how to list out all divisors of a number and came across this solution by Marc-Andre here. In his solution, there is one part of the code which does something like this:
array.product(*arrays_of_array) # the asterisk seems to have done sth.
I tried it in irb to try play around but I couldn't make sense of the outputs. I tried:
a=[0,1,2]
b=[3,4]
c=[[5,6],[7,8]]
I understand that array.product(other_array) is a method to list all combinations of the two arrays into one. With this knowledge, I tested out several experiments
a.product(b) => [[0, 3], [0, 4], [1, 3], [1, 4], [2, 3], [2, 4]] / 6 elements
a.product(*b) => TypeError: no implicit conversion of Fixnum into Array
a.product(c) => [[0, [5, 6]], [0, [7, 8]], [1, [5, 6]], [1, [7, 8]], [2, [5, 6]], [2, [7, 8]]] / 6 elements
a.product(*c) => [[0, 5, 7], [0, 5, 8], [0, 6, 7], [0, 6, 8], [1, 5, 7], [1, 5, 8], [1, 6, 7], [1, 6, 8], [2, 5, 7], [2, 5, 8], [2, 6, 7], [2, 6, 8]]
From observation, It seems the asterisk (*) has to be applied to a multi-dimensional array? (i.e. matrix?). Without the asterisk, the product returns 6 elements and the combinations only one level. While with the asterisk, the combination will go 1 level deeper and returns 12 elements, and combine until there is no array within the combinations. Where can I find more examples to study this behaviour of the asterisk?
Edit:
I tried to introduce one more variable
d=[[[9,0],[1,2]],[[3,4],[5,6]]]
a.product(*d) => [[0, [9, 0], [3, 4]], [0, [9, 0], [5, 6]], [0, [1, 2], [3, 4]], [0, [1, 2], [5, 6]], [1, [9, 0], [3, 4]], [1, [9, 0], [5, 6]], [1, [1, 2], [3, 4]], [1, [1, 2], [5, 6]], [2, [9, 0], [3, 4]], [2, [9, 0], [5, 6]], [2, [1, 2], [3, 4]], [2, [1, 2], [5, 6]]]
So the asterisk sign only makes it go one level deeper.
In the context of finding the list of divisors. Can anyone explain what the code exactly does?
require 'prime'
def factors_of(number)
primes, powers = number.prime_division.transpose
exponents = powers.map{|i| (0..i).to_a}
divisors = exponents.shift.product(*exponents).map do |powers|
primes.zip(powers).map{|prime, power| prime ** power}.inject(:*)
end
divisors.sort.map{|div| [div, number / div]}
end
p factors_of(4800) # => [[1, 4800], [2, 2400], ..., [4800, 1]]
*(splat) is used to expand collections.
In your example, with b = [3,4],
a.product(*b)
is equivalent to
a.product(3, 4)
which generates an error because Array#product expects an Array as argument, not two integers.

Find efficient maximum of groupings in all sets

I have a 2D array and want to generate a 3D array that will show the most efficient groupings for all sets. Example:
[[1, 2],
[1, 2, 3, 4],
[3, 4],
[1, 2, 5]]
Result:
[[[1, 2]],
[[1, 2], [3, 4]],
[[3, 4]],
[[1, 2], [5]]]
I think I would need to do a nested loop and determine the intersection and differences to generate the 3D array. However, inject(&:&) seems like it might solve it more elegantly, though I'm a bit new to inject and unsure how to implement it for this problem. This is to be done in Ruby.
Any help is appreciated. Thanks!
--Update--
By efficient groupings I mean find the best combination that generates the least amount of total sets in the result by finding the largest duplicate sets.
Another example:
[[1, 2, 3, 4],
[1, 4],
[1, 3, 4],
[1, 2, 3, 4, 5],
[2, 5]]
Possible Result (8 total sets):
[[[1, 3, 4], [2]],
[[1, 4]],
[[1, 4], [3]],
[[1, 3, 4], [2, 5]],
[[2, 5]]]
This is a good result, but the first set could be optimized.
Better Result (7 total sets):
[[[1, 2, 3, 4]],
[[1, 4]],
[[1, 4], [3]],
[[1, 2, 3, 4], [5]],
[[2, 5]]]
Both results contain a total of 5 unique sets. The sets in the better result are (1, 2, 3, 4), (1, 4), (3), (5), and (2, 5). The total number of sets in the better result is 7 as opposed to 8 in the possible result. We want the least amount of sets.
You definitely should explain what "the most efficient grouping" means. In the meantime, if you just need to split arrays into 2-element chunks, just combine map and each_slice:
arr.map{|a| a.each_slice(2).to_a}
# => [[[1, 2]], [[1, 2], [3, 4]], [[3, 4]], [[1, 2], [5]]]
First you should figure out the algorithm in pseudocode for what you want to do (its not the Ruby that's keeping you back right now). Then go use these ruby primatives to make it happen
http://ruby-doc.org/core/classes/Enumerable.html
http://www.ruby-doc.org/core/classes/Array.html
http://corelib.rubyonrails.org/classes/Set.html

Resources