permutation ranking with DI sequence - arrays

I want to rank and unrank through a subset of permutations given by length. The subset is definded as follows:
Example for permutation length 4:
We have the Input the Bitstring length 3 (always permutation length - 1)
010
0 means 2 consecutive elements are Increasing.
1 means 2 consecutive elements are Decreasing.
For this Bitstring exist the subset with following permutations: 1324,1423,2314,2413,3412
The bitstring defined subset of permutations i want to rank and unrank? Is there an algotrithmic way for a given bitstring to do this?

Let me restate the problem that I think you mean.
You have a bit string of length n-1. If its digits are a pattern of increase/decrease, that describes a set of permutations that fit the pattern. That set can be put into ascending order.
You want to be able to solve two problems.
Given a permutation that fits the pattern, say where it is in that order (ie "rank" it)
Given a number, produce the permutation that is at that place in the order (ie "unrank" it)
And ideally you'd like to be able to solve these without having to generate all of the permutations that fit the pattern.
The key to both is the following function:
def count_matching (bitstring, start):
''' Returns how many permutations of 1..(len(bitstring) + 1)
''' match bitstring with starting value start
# some implementation here.
This can be calculated recursively fairly easily. However doing it the naive way generates all permutations. But if we add a caching layer to memoize it, then we store a polynomial amount of data and make a polynomial number of calls to fill it in.
Here is the data you get once it is cached for your example:
{
('010', 1): 2,
('010', 2): 2,
('010', 3): 1,
('010', 4): 0,
('10', 1): 0,
('10', 2): 1,
('10', 3): 1,
('0', 1): 1,
('0', 2): 0,
('', 1): 1
}
Now this seems like a lot of data for a small number of patterns. But for a permutation of length n the number of entries grows like O(n^2) and the number of calls to populate it grows like O(n^3). (Any eagle eyed readers may figure out how to populate it in time O(n^2). I'm going with the simple version.)
With this in hand, we can take a rank and figure out which permutation it must be with the following idea.
Suppose that we want to find the rank 4 permutation. Our starting list of numbers is (1 2 3 4). We can skip over 0 permutations which start with ('010', 1) and the answer will be the second of the 2 with ('010', 2).
Take the second number 2 and our partial permutation is [2, and we have the numbers (1 3 4). We are looking for the 2nd for bitstring '10'. We skip over the 0 permutations which start ('10', 1), the 1 with ('10', 2) and want the first of the 1 with ('10', 3).
Take the third number 4 and our partial permutation is [2, 4, and we have the numbers (1 3). As before we find that we want the first of the 1 with ('0', 1).
Take the first number 1 and our partial permutation is [2, 4, 1 and we have the numbers (3). There aren't a lot of choices.
So we finish and get [2, 4, 1, 3]. Which you can verify is the 4th.
And so we finish with [2, 4, 3, 1].
We can also go the other way. Taking the same permutation, we start with [2, 4, 3, 1] and want its rank.
How many are before it that differ in the first digit? It used the 2nd possible first number. From the entry for ('010', 1) we know there are 2. And the numbers left are 1 3 4.
How many are before it that differ in the second digit? It uses the 3rd possible second number. From the entries for ('10', 1) and ('10', 2) we know there is 1 more in front of it.
We now have the numbers 1 3 left. None came before it in the third digit. And again, none in the last.
With 3 before it, it must have rank 4.
And there you have it. For memoizing one recursive function, you now make finding permutations by rank, or ranking a given permutation straightforward.

Related

Next unicycle Permutation

I want to get the nextPermutation which has just one cycle. I am familiar with the nextPermutation function but this creates also permutations with more than one cycle. I have no idea how to modify this function to create the nextUnicyclePermution
unicycle permutations of length 4:
2341 -> 2413 -> 3142 -> 3421 -> 4123 -> 4312
Here's an initial idea for generating all the unicyclic permutations.
Each unicyclic permutation, in cycle notation, consists of a single cycle of the elements from the original array (e.g. (1 2 3 4) or (4 1 3 2)). Given any unicyclic permutation of an array of n elements, there are n different ways to write that permutation as a simple cycle. For example, the unicyclic permutation (1 2 3 4) can be written as (1 2 3 4), or (2 3 4 1), or (3 4 1 2), or (4 1 2 3). We'll pick a single canonical way of writing out the permutation by enforcing that the first element of the array comes at the front of the cycle notation.
Once we've fixed that element in place, we can enumerate all the unicyclic permutations by simply enumerating all the permutations of the remaining elements in the cycle notation. For example, here's all the unicyclic permutations of four elements:
(1 2 3 4) ↠ [4, 1, 2, 3]
(1 2 4 3) ↠ [3, 1, 4, 2]
(1 3 2 4) ↠ [4, 3, 1, 2]
(1 3 4 2) ↠ [2, 4, 1, 3]
(1 4 2 3) ↠ [3, 4, 2, 1]
(1 4 3 2) ↠ [2, 3, 4, 1]
The general algorithm would then be the following:
Compute the cycle notation of the current permutation.
Rotate that cycle notation to put the first element into the first slot.
Use a standard next-permutation algorithm to advance the last n-1 elements of the cycle notation to their next permutation.
Reorder the elements to match that cyclic ordering.
There is probably a faster way to enumerate them (with, say, O(1) work done between permutations) and there might be a way to generate them in lexicographical order. But this hopefully gives a starting algorithm to work with!

Next permutation/ranking with specific strength

I am searching an algorithm which gives me the next permutation with a specific strength.
A permutation of length n is defined with the elements (1,2,3,...n)
What is the strength of a permutation?
The strength of a permutation with length 10 is definded as |a1-a2|+|a2-a3|+...+|a9-a10|+|a10-a1|.
For example:
(1,2,3,4,5,6) has the strength 10
(1,2,6,3,4,5) has the strength 14
Exist there a formula to compute the next permutation of a given strength and length, or its necesary to compute all elements?
Is ranking/unranking of the subsets possible?
The next permutation function should return the next lexicographical permutation within the subset defined by the given strength and length and without compute the intermediate permutations different strengths.
This is a nicely masked problem in combinatorics. First, note that this is a ring of integers; the linear "array" is an implementation choice, rather than part of the strength analysis. Let's look at the second case, given as (1,2,6,3,4,5):
1
5 2
4 6
3
Every element appears in exactly two terms. Thus, we have a simple linear combination of the elements, with coefficients of -2, 0 2. If the element is larger than both neighbors (e.g. 5), the coefficient is 2; if smaller than both neighbors (e.g. 1), it's -2; if between, the two abs operations cancel, and it's 0 (e.g. 4).
Lemma: the strength must be an even number.
Thus, the summation and some transformations can be examined easily enough with simple analysis. The largest number always has a coefficient of +2; the smallest always has a coefficient of -2.
You can find "close relative" permutations by finding interchangeable elements. For instance, you can always interchange the largest two elements (6 and 5) and/or the smallest two elements (1 and 2), without affecting the strength. For instance, 6 and 5 can be interchanged because they're strictly larger than their neighbors:
(6-2) + (6-3) + (5-1) + (5-4) =
(5-2) + (5-3) + (6-1) + (6-4) =
2*6 + 2*5 - 2 - 3 - 1 - 4
1 and 2 can be interchanged, even though they're adjacent, for a similar reason ... except that there are only three terms, one of which involves the pair:
(5-1) + (2-1) + (6-2) =
(5-2) + (2-1) + (6-1) =
5 + 6 - 2*1
Depending on the distribution of the set of numbers, there will likely be more direct ways to construct a ring with a given strength. Since we do not yet have an ordering defined on the permutations, we have no way to determine a "next" one. However, the simple one is to note that rotations and reflections of a given permutation will all have the same strength:
(1,2,6,3,4,5)
(2,6,3,4,5,1)
(6,3,4,5,1,2)
...
(5,4,3,6,2,1)
(4,3,6,2,1,5)
...
Does that get you moving?
Addition w.r.t. OP updates:
There are several trivially strength-invariant swaps available. I've already mentioned the two extreme pairs (6-5) and (1-2). You can also swap adjacent, consecutive numbers: that adds (4-5) and (3-4) in the above example. From simple algebraic properties, you can often identify a 2-element swap or 3-element rotation (respecting an increase in lexicographic position) that generates the next desired permutation. For instance:
(5, 6, 1, 3, 4, 2)
(5, 6, 1, 4, 2, 3) rotate 3, 4, 2
(5, 6, 1, 4, 3, 2) swap 2, 3
However, there are irruptions in the sequence that you'd be hard-pressed to find in this fashion. For instance, making the leap to change the first or second element is not so clean:
(5, 6, 3, 1, 4, 2)
(5, 6, 3, 2, 4, 1) swap 1, 2 -- easy
(6, 1, 2, 4, 5, 3) wholesale rearrangement --
hard to see that this is the next strength=14
I feel that finding these would require a set of algebraic rules that would find the simple moves and eliminate invalid moves (such as generating 563421 before the "wholesale rearrangement" just above). However, following these rules would often take more time than working through all permutations.
I'd love to find that I'm wrong on this last point. :-)

Given two arrays, find the number of elements greater

This was the interview question I had from a tech company. I got it wrong, which I think doomed my chances, but I honestly I still cannot figure out the answer... here's the question. Assume that all elements of the sequence are unique.
We have two finite sequences: X={Xi}, Y={Yi} where Yi is a sub-sequence of Xi.
Let's write them as separate arrays: [X1, X2, ..., Xn], [Y1, Y2, ..., Yk] where n is the length of X, k is the length of Y, and obviously, since Y is a sub-sequence of X, we have n>=k.
For instance
X=[1, 10, 5, 7, 11, -4, 9, 5]
y=[10, 7, -4, 9]
Then for each element in Y, we want to find the number of elements in X which 1) appear after that element and 2) greater than that element.
Using the example above
X=[1, 10, 5, 7, 11, -4, 9, 5]
y=[10, 7, -4, 9]
ans=[1, 2, 2, 0]
explanation:
the first element of ans is 1 because only 11 appears after 10 and greater than 10 in X,
so there's only 1 element
second element of ans is 2 since 11, 9 both appear after 7 in X, so there are 2 elements
that appear after 7 and greater than 7.
the third element of ans is also 2 since 9, 5 appear after -4 and are both greater than
-4 in X.
the fourth element is 0 since no element in X appears after and greater than 9.
The interviewer wanted me to solve it in O(N) time complexity where N is the length of X. I did not find how.
Anybody has an idea?
If have an algorithm that can solve this problem, then by setting Y = X, you can make it provide enough information to sort X without any further comparisons among elements in X. Therefore, you can't do this in linear time under the usual assumptions, i.e., arbitrary integers in X that you can do operations on in constant time, but no constant bound on their size.
You can do it in O(N log N) time pretty easily by walking backwards through X and maintaining an order statistic tree of the elements seen so far. See https://en.wikipedia.org/wiki/Order_statistic_tree
I think it's impossible same as it's impossible for sorting and here is the reason
For solving this we should save state for previous calculation in limited number variable, for example store addition, subtraction or multiply.
So if there is a big number in A thats not in B its very clear it's not usefull at all, and we already know the only possible solution is to save previous state in limited variable, So we can't have numbers that related only to item in A.
So far we know to solve this is we should figure out the saving state algorithm, for saving state we can only store some number that represent for all previous numbers for current element in Y all of these calculation its not helping because we dont know the next item in Y (for example the current number is -1000 and next number is 3000 and other number in X is 1,2,3). so because of that we cant have any stored number that related to current element in Y. also we cant have any number that's not related to Y(as its usefull at all)

Determining whether or not a binary array has two consecutive 1s with less than n index accesses?

Say we have an array of size n, with each index containing the values 0 or 1. We need to determine whether or not the array contains two consecutive 1 bits.
For which values of n in the range {3, 4, 5, 6, 7} can this be done by checking fewer than n elements (in the worst case)?
My attempt:
When n is in {4,7}, we can determine if there are consecutive 1's without checking all the elements.
For 4, we can do this by checking the either of the middle two elements. If either of them is 0, then we no longer have to check the index on its outer side.
For we first check if the 2nd index has a 1, if it does then we check the 1st and 3rd element. If there is not a consecutive pair, then we move on to the 6th element. If it has a 1, then we check the 5th and 7th element. If there is no consecutive pair, then we return false. However, if the 6th element did not contain a 1, then we consider the 4th and 5th element. This is a max total of 6 indexes checks for any list combination of 1's and 0's of size 7.
Am I missing something? I sort of just tried out random algorithms to see if I can get less than n index accesses for each value of n. How can I prove that {3,5,6} can't be done with less than n index checks?

How to divide array in to groups with smallest sum difference?

I have array of integers, I need to sort them in unknown number of groups with minimal difference in sum of each group.
example:
Array: 2, 1, 4, 7, 1, 2, 6, 8
Number of groups = 3
Result:
Group 1 – 8, 2 = 10
Group 2 – 7, 2, 1 = 10
Group 3 – 6, 4, 1 = 11
Is there any alghoritham too solve this problem?
I'm stuck.
Firstly, if the number of groups is 2 this reduces to the subset sum problem variant the partition problem. This proves the problem is NP-hard, so you shouldn't try to find an efficient algorithm.
Given that it will be at least exponential you might as well just generate all permutations and pick the best. I know some people don't like recursion, but it really is useful here for enumerating the group possibilities:
recfunc(array, groups):
if array is empty
return an array containing the element groups
else
groupsList = empty array
foreach aGroup in groups
element = array[0]
groupsList += recfun(array - element, groups where aGroup adds element)
return groupsList
This algorithm will create a list of all possibilities. It is fairly inefficient, but shouldn't be too hard for you to implement. From here just go through the list and calculate if the sum of the groups is the minimum of the list.

Resources