Iam searching one permutation P consisting of p1...pn of following subset S.
S is defined of the Labels L.
L1...Lk. Where a L contains pi...pj.
Where the inverse of P has at most k-1 decreasing adjecent Elements. k <= n.
Example:
n := 4
k := 2
L1 := 1,2
L2 := 3,4
L := L1,L2,L1,L2
S := 1324,1423,2314,2413
one solution would be P := 1342
no solution would be P := 3142 because decreasing adjecent elements are 2 but only max1 ist allowed because k =2.
Exists therefor an algorithm to find P of S defined by L?
Currently I use bruteforce to figure one permutation P, but its getting very fast unusable slow.
So each of
L1, ..., Lkis a consecutive set of elements. At each place we seeLi, Ljin the definition ofL, one of three things is true:i < jin which case it is ascending.i = jin which case it could be ascending or descending.i > jin which case it must be descending.By counting the number of places where case 3 is true, we get a minimum number of descending elements already in the definition of
L.Next, for each
Liwe have a pattern we can write down withlen(Li)-1;and,where a;means that there are elements of otherLjs between two members ofLi, and,means thatLielements are adjacent and so the order of the elements may result in a descent. We want to know, "For each possible number of descents withinLi, how many permutations ofLihave that number of descents?"We will think of building the permutations as follows:
A descent is when the next element is smaller than the previous, at a transition matching a
,.We actually will want the following data structure for later use:
So we can write a recursive function that takes:
Li.It then returns a dictionary mapping descents to count of ways to finish the permutation for
Li.Memoize that and we get our desired data structure.
Now we'll repeat the idea. We want:
Again we can write a recursive function using
cacheto calculate this, and we can memoize it to getcache2.And NOW we can reverse the process.
L.cache2[1], so we can randomly pick how many descents there will be meeting our condition amongL1...Lk.L1...Lkwe can look atcache[L1][1][0]andcache2[i+1]to figure out how many descents there will be withinLiwith the correct probability.Liwe can look at how many descents we want to wind up with, its pattern, andcache2[Li]to figure out a random sequence of inserts winding up with the right pattern. The first insert is always at0. After that you always know the size, and where the last insert was, and how many descents are left. So for each possiblenext insert you figure out if it counts as a descent (look at both pattern, and whether it is before the last insert), and the number of ways to finish from there. Then you can choose the next insert randomly with the right possibility.Liwe can turn the pattern of inserts into the list of values in order. (I will explain this step more.)Land fill in all of the values.Now for step 5, let's illustrate with your example from the chat. Suppose that
L2 = [4, 5, 6]and the pattern of inserts we came up with was[0, 1, 0]. How do we figure out the arrangement of values?Well first we do our inserts:
This says that the first element (
4) goes to the third place, the second (5) to the first, and the third (6) to the second. So our permutation forL2is[5, 6, 4].This will be a lot of code to write. But it will be polynomial. Specifically if
mis the count of the most common label,cachewill have total size at mostO(k m^2). Thanks to memoization, each entry takesO(m)to calculate. Everything else is small relative to that. So total space isO(k m^2)and time isO(k m^3).