Index of a permutation - algorithm

I was recently reading about Lehmer codes and how they can be used to map an index to a permutation corresponding to that index and realized they can be quite useful to quickly generate a permutation. Does anyone know how can this be done using an algorithm, and also what are the limits of such a method, I suppose we can't go above index = 1.7977e+308, but still seems quite an interesting method.
So basically lets say we have
perm
1 0 0 0
2 0 0 1
3 0 0 2
4 0 1 0
5 0 1 1
6 0 1 2
...
We should be able to deduce that the index of [ 0 1 0 ] is 4,
or that the index 6 corresponds to [ 0 1 2 ]
Thanks for any help.

The vector for each index is the base 3 representation of the index (minus one)
the functions dec2base and base2dec can be used for this with a little fiddling to get the sting outputs to the required format
index to vector
index=4; % input index
n=3; % length of vector
vec=str2num([dec2base(index-1,3,n)].').'
vec=
0 1 0
vector to index
vec=[0,1,2]; % input vector
vecstr=strcat(['' vec(:)+'0'].');
index=base2dec(vecstr,3)+1
index =
6

Related

Fill matrix randomly without row-repetitions

Please help. I'm new to matlab scripting and need a bit of help. I have a series of numbers:
A=[1 1 1 2 2 2 3 3 3 4 4 4 5]
which I want to fill randomly into an 8x12 matrix without having the same number in the same row. At the end I want all the "empty" cells of the 8x12 matrix being filled with 0's or nan.
an example could be:
result=
3 1 5 2 4 5 0 0 0 0 0 0
4 1 3 2 0 0 0 0 0 0 0 0
1 3 4 2 0 0 0 0 0 0 0 0
make sure A is sorted. A = sort(A)more info
make an empty matrix.
For each number in A: more info
find out how many repetitions of the number there are -> for loop in A, start is the first occurance of the number, end is the last, n = last-first+1
find all rows that have space for an extra number, just do a double for loop and keep track of elements that are zero
randomly pick n rows -> more info. To do this, make an array R of all available row indixes. Then take a random sample between 1..size(R,2) with the provided function and get all the values, you now have your row indixes.
randomly pick one of the empty spots in each of the selected rows and assign the number

Distinct values of bitwise and of subarrays

How to find number of distinct values of bitwise and of all subarrays of an array.(Array size <=1e5 and array elements<=1e6).
for eg.
A[]={1,2,3}
distinct values are 4(1,2,3,0).
Let's fix the right boundary r of the subarray. Let's image the left boundary l moves to the left starting from r. How many times can the value of the and change? At most O(log(MAX_VALUE)). Why? When we add one more element to the left, we've got two options:
The and value of the subarray doesn't change.
It changes. In that case, the number of bits in it gets strictly less (as it's a submask of the previous and value).
Thus, we can consider only those values of l where something changes. Now we just need to find them quickly.
Let's iterate over the array from left to right and store the position of the last element that doesn't have the i-th bit for all valid i (we can update it by iterating over all bits of the current element). This way, we'll be able to find the next position where the value changes quickly (namely, it's the largest value in this array over all bits that are set). If we sort the positions, we can find the next largest one in O(1).
The total time complexity of this solution is O(N * log(MAX_VALUE) * log(log(MAX_VALUE))) (we iterate over all bits of each element of the array, we sort the array of positions for each them and iterate over it). The space complexity is O(N + MAX_VALUE). It should be good enough for the given contraints.
Imagine the numbers as columns representing their bits. We will have sequences of 1's extending horizontally. For example:
Array index: 0 1 2 3 4 5 6 7
Bit columns: 0 1 1 1 1 1 0 0
0 0 0 1 1 1 1 1
0 0 1 1 1 1 1 0
1 0 0 0 1 1 0 1
0 1 1 1 1 1 1 0
Looking to the left, the bit-row for any subarray anded after a zero will continue being zero, which means no change after that in that row.
Let's take index 5 for example. Now sorting the horizontal sequences of 1's from index 5 to the left will provide us a simple way to detect a change in the bit configuration (the sorting would have to be done on each iteration):
Index 5 ->
Sorted bit rows: 1 0 0 0 1 1
0 0 0 1 1 1
0 0 1 1 1 1
0 1 1 1 1 1
0 1 1 1 1 1
Index 5 to 4, no change
Index 4 to 3, change
Index 2 to 1, change
Index 1 to 0, change
To easily examine these changes, kraskevich proposes recording only the last unset bit for each row as we go along, which would indicate the length of the horizontal sequence of 1's, and a boolean array (of 1e6 numbers max) to store the unique bit configurations encountered.
Numbers: 1, 2, 3
Bits: 1 0 1
0 1 1
As we move from left to right, keep a record of the index of the last unset bit in each row, and also keep a record of any new bit configuration (at most 1e6 of them):
Indexes of last unset bit for each row on each iteration
Numbers: 1, 2, 3
A[0]: -1 arrayHash = [false,true,false,false], count = 1
0
A[1]: -1 1 Now sort the column descending, representing (current - index)
0 0 the lengths of sequences of 1's extending to the left.
As we move from top to bottom on this column, each value change represents a bit
configuration and a possibly distinct count:
Record present bit configuration b10
=> arrayHash = [false,true,true,false]
1 => 1 - 1 => sequence length 0, ignore sequence length 0
0 => 1 - 0 => sequence length 1,
unset second bit: b10 => b00
=> new bit configuration b00
=> arrayHash = [true,true,true,false]
Third iteration:
Numbers: 1, 2, 3
A[2]: -1 1 1
0 0 0
Record present bit configuration b11
=> arrayHash = [true,true,true,true]
(We continue since we don't necessarily know the arrayHash has filled.)
1 => 2 - 1 => sequence length 1
unset first bit: b11 => b10
=> seen bit configuration b10
0 => 2 - 0 => sequence length 2,
unset second bit: b10 => b00
=> seen bit configuration b00

Fast index mapping in matlab

I have the following problem:
Given a matrix A
A = [ 1 2 2 3 3 ;
2 2 2 7 9 ]
where the sequence of unique numbers within the matrix is not continuous. In this example
unique(A) = [ 1 2 3 7 9 ]. % [ 4 5 6 8 ] are missing
I want to compute the same matrix, but using instead a continuous sequence, such that
unique(A_new) = [ 1 2 3 4 5 ];
I came up with the following solution
T = [ unique(A), [ 1:numel(unique(A)) ]' ];
A_new = zeros(size(A));
for i = 1:size(T,1)
A_new( A == T(i,1) ) = T(i,2);
end
This is incredibly slow: the size of the matrix A I have to work with is 200x400x300 and the the number of unique elements within this matrix is 33406.
Any idea on how to speed up the procedure?
If I understand correctly, in your example you want:
A_new = [ 1 2 2 3 3 ;
2 2 2 4 5 ]
So just compute a lookup table (lookup) such that you can then do:
A_new = lookup(A);
So in your case, lookup would be:
[ 1 2 3 0 0 0 4 0 5 ]
I'll leave the process for generating that as an exercise for the reader.
Approach 1 (not recommended)
This should be pretty fast, but it uses more memory:
[~, A_new] = max(bsxfun(#eq, A(:).', unique(A(:))));
A_new = reshape(A_new, size(A));
How does this work?
First A is linearized into a vector (A(:)). Also, a vector containing the unique values of A is computed (unique(A(:))). From those two vectors a matrix is generated (with bsxfun) in which each entry of A is compared to each of the unique values. That way, for each entry of A we know if it equals the first unique value, or the second unique value, etc. For the A given in your question, that matrix is
1 0 0 0 0 0 0 0 0 0
0 1 1 1 1 1 0 0 0 0
0 0 0 0 0 0 1 0 1 0
0 0 0 0 0 0 0 1 0 0
0 0 0 0 0 0 0 0 0 1
So for example, the value 1 in entry (2,3) indicates that the third value of A(:) equals the second unique value of A (namely 2). The 1 in the lower-right entry (5,10) indicates that the tenth value of A(:) is the fifth unique value of A (which is 9).
Now the second output of max is used to extract the row position of the 1 value in each columnn (i.e. to obtain the numbers indicating "second", "fifth" etc in the above example)). These are the desired results. It only remains to reshape them into the shape of A.
Approach 2 (recommended)
The third output of unique does what you want:
[~, ~, labels] = unique(A);
A_new = reshape(labels, size(A));

How I can get the 'n' possible matrices from two vectors?

I've been searching for an algorithm for the solution of all possible matrices of dimension 'n' that can be obtained with two arrays, one of the sum of the rows, and another, of the sum of the columns of a matrix. For example, if I have the following matrix of dimension 7:
matriz= [ 1 0 0 1 1 1 0
1 0 1 0 1 0 0
0 0 1 0 1 0 0
1 0 0 1 1 0 1
0 1 1 0 1 0 1
1 1 1 0 0 0 1
0 0 1 0 1 0 1 ]
The sum of the columns are:
col= [4 2 5 2 6 1 4]
The sum of the rows are:
row = [4 3 2 4 4 4 3]
Now, I want to obtain all possible matrices of "ones and zeros" where the sum of the columns and the rows fulfil the condition of "col" and "row" respectively.
I would appreciate ideas that can help solve this problem.
One obvious way is to brute-force a solution: for the first row, generate all the possibilities that have the right sum, then for each of these, generate all the possibilities for the 2nd row, and so on. Once you have generated all the rows, you check if the sum of the columns is right. But this will take a lot of time. My math might be rusty at this time of the day, but I believe the number of distinct possibilities for a row of length n of which k bits are 1 is given by the binomial coefficient or nchoosek(n,k) in Matlab. To determine the total number of possibilities, you have to multiply this number for every row:
>> n = 7;
>> row= [4 3 2 4 4 4 3];
>> prod(arrayfun(#(k) nchoosek(n, k), row))
ans =
3.8604e+10
This is a lot of possibilities to check! Doing the same for the columns gives
>> col= [4 2 5 2 6 1 4];
>> prod(arrayfun(#(k) nchoosek(n, k), col))
ans =
555891525
Still a large number, but 'only' a factor 70 smaller.
It might be possible to improve this brute-force method a little bit by seeing if the later rows are already constrained by the previous rows. If in your example, for a particular combination of the first two rows, both rows have a 1 in the second column, the rest of this column should all be 0, since the sum must be 2. This reduces the number of possibilities for the remaining rows a bit. Implementing such checks might complicate things a bit, but they might make the difference between a calculation that takes 2 days or one that takes just 1 hour.
An optimized version of this might alternatively generate rows and columns, and start with those for which the number of possibilities is the lowest. I don't know if there is a more elegant solution than this brute-force method, I would be interested to hear one.

How to perform spiral order traversalin one dimensional array? [duplicate]

This question already has answers here:
Closed 10 years ago.
Possible Duplicates:
Looping in a spiral
Writing a string in a spiral
Print two-dimensional array in spiral order
2d Array in Spiral Order
We have a data in the form of matrix
0 0 0 0 0
0 1 2 3 0
0 4 5 6 0
0 7 8 9 0
0 0 0 0 0
which is stored in a 1d array in this fashion
[0 0 0 0 0 0 1 2 3 0 0 4 5 6 0 0 7 8 9 0 0 0 0 0 0]
This is a zero padded 3x3 array transformed into 5x5. We know the start index and end index.
As we see, we can perform 25 operations and print all values, but instead if we go in spiral order we should ideally do this in only 9 operations.
Does anyone know how to do this?
We know the number of rows and number of columns. Here it would be rows=5 cols=5.
Hence start index would be rows+1 and end index would be rows*cols-6
I'm visualizing it as a spiral order traversal.
Given your 5x5 matrix assuming a zero index base you know the row indices are:
0,1,2,3,4
5,6,7,8,9
10,11,12,13,14
15,16,17,18,19
20,21,22,23,24
you know your first index is 6 and the last is 18. So as a starting point you know you can eliminate the following pieces of the matrix:
0,1,2,3,4
and
19,20,21,22,23,24,25
this counts as 2 operations.
you also know that since you are starting at index 6 and it was a 3x3 you only need to go to index 8, this is one operation.
you then need to add 5 to your previous index of 6 this yields 11 and proceed again (2 operations in total) current operation count is 5)
do this again with 11 and you get 16 one operation. Get 2 more operations and you end up with 18. This is now 8 operations in total.
I'd do something like this:
POINT ul = (start_idx/width, start_idx%width);
POINT br = (end_idx/width, end_idx%width);
POINT p = ul
dir = RIGHT;
while (ul != br)
visit(ARRAY[p.x+p.y*WIDTH])
case dir
when RIGHT:
p.x+=1
if (p.x==br.x)
dir = DOWN
ul.y++;
when DOWN
p.y+=1
if (p.y==br.y)
dir = LEFT
br.x--;
when LEFT:
//like RIGHT but -1 and adjust br.y upwards when done
when UP:
//like DOWN but -1 and adjust ul.x rightward when done
endwhile
The idea is to keep track of the virtual x and y to visit. Move the point to visit along the sides of the box defined by the start and end points. And adjust the sides inwards as you complete the visits.

Resources