Count permutation with duplicates and restriction - arrays

I want to count the permutations with duplicates and only 3 different signs 0,1,2 and the restriction that no 0 follows directly after a 1.
Example:
Valid: 01202212
Invalid: 10...
I though the count of these subset of permutations
is (3^count(0))*(2^count(1))*(3^count(2)) but this is wrong. If not how can i compute the exakt count?

It is clear that:
-valid sequence of length K ending with 1 might be composed
adding 1 to any valid sequence of length K-1
-valid sequence of length K ending with 2 might be composed
adding 2 to any valid sequence of length K-1
-valid sequence of length K ending with 0 might be composed
adding 0 to valid sequences of length K-1 ending with 0 or 2
So simple Python program
def valid123(n):
a = [[0]*3 for _ in range(n)]
a[0][0] = 1
a[0][1] = 1
a[0][2] = 1
summ = 3
for i in range(1, n):
a[i][0] = summ - a[i-1][1]
a[i][1] = summ
a[i][2] = summ
summ = sum(a[i])
return summ
for i in range(1,10):
print(i, valid123(i))
gives
1 3
2 8
3 21
4 55
5 144
6 377
7 987
8 2584
9 6765
Corresponding OEIS sequence has simple recurrent representation a(n) = 3*a(n-1) - a(n-2) - subset of Fibonacci, and some closed formula does exist:
a(n) = (ap^n - am^n)/(ap-am), with ap := (3+sqrt(5))/2, am := (3-sqrt(5))/2

Related

Rank and unrank fibonacci bitsequence with k ones

For positive integers n and k, let a "k-fibonacci-bitsequence of n" be a bitsequence with k 1 where the 1 on index i describe not Math.pow(2,i) but Fibonacci(i). These positive integers that add up to n, and let the "rank" of a given k- fibonnaci-bitsequence of n be its position in the sorted list of all of these fibonacci-bitsequences in lexicographic order, starting at 0.
For example, for the number 39 we have following valid k-fibonacci-bitsequences, k <=4. The fibonacci numbers behind the fibonacci-bitsequence in this example are following:
34 21 13 8 5 3 2 1
10001000 k = 2 rank = 0
01101000 k = 3 rank = 0
10000110 k = 3 rank = 1
01101100 k = 4 rank = 0
So, I want to be able to do two things:
Given n, k, and a k-fibonacci-bitsequence of n, I want to find the rank of that k-fibonacci-bitsequence of n.
Given n, k, and a rank, I want to find the k-fibonacci-bitsequence of n with that rank.
Can I do this without having to compute all the k-fibonacci-bitsequences of n that come before the one of interest?
Preliminaries
For brevity lets say »k-fbs of n« instead of »k-fibonacci-bitsequences of n«.
Question
Can I do this without having to compute all the k-fbs of n that come before the one of interest?
I'm not sure. So far I still have to compute some of fbs. However, you might have thought we had to start from 00…0 and count up – this is not the case. We can do it the other way around and start from the highest fbs and work our way down very efficiently.
This is not a complete answer. However, there are some observations that could help you:
Zeckendorf
In the following pseudo-code we use the data-type fbs which is basically an array of bools. We can read and write individual bits using mySeq[i] where bit i represents the Fibonacci number fib(i). Just as in your question, the bits myFbs[0] and myFbs[1] do not exist. All bits are initialized to 0 by default. An fbs can be used without [] to read the represented number (n). The helper function #(fbs) returns the number of set bits (k) inside an fbs. Example for n = 7:
fbs meaning representation helper functions
1 0 1 0
| | | `— 0·fib(2) = 0·1 ——— myFbs[2] = 0 #(myFbs) == 2
| | `——— 1·fib(3) = 1·2 ——— myFbs[3] = 1 myFbs == 7
| `————— 0·fib(4) = 0·3 ——— myFbs[4] = 0
`——————— 1·fib(5) = 1·5 ——— myFbs[5] = 1
For any given n we can easily compute the lexicographical maximum (across all k) fbs of n as this fbs happends to be the Zeckendorf representation of n.
function zeckendorf(int n) returns (fbs z):
1 int i := any (ideally the smallest) number such that fib(start) > n
2 while n-z > 0
3 | if fib(i) < n
4 | | z[i] := 1
5 | i := i - 1
zeckendorf(n) is unique and the only fbs of n with k=#(zeckendorf(n)). Therefore zeckendorf(n) has rank=0. Also, there exists no k'-fbs of n with k'<#(zeckendorf(n)).
Transformation
Any k-fbs of n can be transformed into a (k+1)-fbs of n by replacing the bit sequence 100 by 011 anywhere inside the fbs. This works because fib(i)=fib(i-1)+fib(i-2).
If our input k-fbs of n has rank=0 and we replace the right-most 100 then our resulting (k+1)-fbs of n also has rank=0. If we replace the second-right-most 100 our resulting (k+1)-fbs has rank=1 and so on.
You should be able answer both of your questions using repeated transformations starting at zeckendorf(n). For the first question it might even be sufficient to only look at the k-stable transformations 011…100→100…011 and 100…011→011…100 of the given fbs (think about what these transformations do to the rank).

Increment value of every element in an array in a particular range

There's an array A[] having n elements. There's another array B[] of the same size n with every element initialized to zero. For every i in range 1 to n, elements of B[] in the range i-A_i to i+A_i (inclusive) need to be increased by 1.
I've already tried an O(n^2) solution using nested loop method. I cannot really figure out an O(n) solution if existent.
i=1;
while(i<=n)
{
start=(i-A[i]<1)?1:i-A[i];
end=(i+A[i]>n)?n:i+A[i];
while(start<=end)
{
B[start]+=1;
start+=1;
}
i+=1;
}
A naive implementation is to to increment each range per item in A, but you do not need to do taht. You can first "prepare" your array by adding 1 where the increment should start, and -1 where the increment should stop. Next you can calculate the cummulative sum of the array. Like:
def fill_list(la):
lb = [0]*len(la)
n1 = len(la)-1
for i, a in enumerate(la, 1):
xf, xt = i-a, i+a+1
lb[max(0, i-a)] += 1
if xt <= n1:
lb[xt] -= 1
c = 0
for i, b in enumerate(lb):
c += b
lb[i] = c
return lb
or if you want to return the range from 1 to n:
def fill_list1(la):
n1 = len(la)
lb = [0]*(n1+1)
for i, a in enumerate(la, 1):
xf, xt = i-a, i+a+1
lb[max(0, i-a)] += 1
if xt <= n1:
lb[xt] -= 1
c = 0
for i, b in enumerate(lb):
c += b
lb[i] = c
return lb[1:]
We can then for example generate a list with:
>>> fill_list([1,4,2,5,1,3,0,2])
[4, 4, 4, 5, 5, 5, 4, 3]
>>> fill_list1([1,2,3,4,5])
[5, 5, 4, 4, 3]
This thus has ranges for:
-3 -2 -1 0 1 2 3 4 5 6 7 8 9 10 11
--*--*--*--*--*--*--*--*--*--*--*--*--*--*--*--
|-----|
|-----------------------|
|-----------|
|-----------------------------|
|-----|
|-----------------|
|
|-----------|
--*--*--*--*--*--*--*--*--*--*--*--*--*--*--*--
0 1 1 1 1 0 0 1 0 0 -1 -1 -1 -2 -1
--*--*--*--*--*--*--*--*--*--*--*--*--*--*--*--
0 1 2 3 4 4 4 5 5 5 4 3 3 1 0
The increments that are done before the start of the range (so with an index less than 0) are just placed at index 0 such that we take these into account. The ones that are done after the window (so with an index larger than or equal to n are simply ignored).
In the image the first row shows the indices, next we denote the ranges that arise from the same input, next we show the increments and decrements that would be put on an infinite tape, and next we show the cummulative sum.
The algorithm works in O(n): first we iterate over la in linear time, and increment and decrement the corresponding elements in b. Next we iterate over b, again in O(n) to calcuate the cummulative sum.

Shuffle array while spacing repeating elements

I'm trying to write a function that shuffles an array, which contains repeating elements, but ensures that repeating elements are not too close to one another.
This code works but seems inefficient to me:
function shuffledArr = distShuffle(myArr, myDist)
% this function takes an array myArr and shuffles it, while ensuring that repeating
% elements are at least myDist elements away from on another
% flag to indicate whether there are repetitions within myDist
reps = 1;
while reps
% set to 0 to break while-loop, will be set to 1 if it doesn't meet condition
reps = 0;
% randomly shuffle array
shuffledArr = Shuffle(myArr);
% loop through each unique value, find its position, and calculate the distance to the next occurence
for x = 1:length(unique(myArr))
% check if there are any repetitions that are separated by myDist or less
if any(diff(find(shuffledArr == x)) <= myDist)
reps = 1;
break;
end
end
end
This seems suboptimal to me for three reasons:
1) It may not be necessary to repeatedly shuffle until a solution has been found.
2) This while loop will go on forever if there is no possible solution (i.e. setting myDist to be too high to find a configuration that fits). Any ideas on how to catch this in advance?
3) There must be an easier way to determine the distance between repeating elements in an array than what I did by looping through each unique value.
I would be grateful for answers to points 2 and 3, even if point 1 is correct and it is possible to do this in a single shuffle.
I think it is sufficient to check the following condition to prevent infinite loops:
[~,num, C] = mode(myArr);
N = numel(C);
assert( (myDist<=N) || (myDist-N+1) * (num-1) +N*num <= numel(myArr),...
'Shuffling impossible!');
Assume that myDist is 2 and we have the following data:
[4 6 5 1 6 7 4 6]
We can find the the mode , 6, with its occurence, 3. We arrange 6s separating them by 2 = myDist blanks:
6 _ _ 6 _ _6
There must be (3-1) * myDist = 4 numbers to fill the blanks. Now we have five more numbers so the array can be shuffled.
The problem becomes more complicated if we have multiple modes. For example for this array [4 6 5 1 6 7 4 6 4] we have N=2 modes: 6 and 4. They can be arranged as:
6 4 _ 6 4 _ 6 4
We have 2 blanks and three more numbers [ 5 1 7] that can be used to fill the blanks. If for example we had only one number [ 5] it was impossible to fill the blanks and we couldn't shuffle the array.
For the third point you can use sparse matrix to accelerate the computation (My initial testing in Octave shows that it is more efficient):
function shuffledArr = distShuffleSparse(myArr, myDist)
[U,~,idx] = unique(myArr);
reps = true;
while reps
S = Shuffle(idx);
shuffledBin = sparse ( 1:numel(idx), S, true, numel(idx) + myDist, numel(U) );
reps = any (diff(find(shuffledBin)) <= myDist);
end
shuffledArr = U(S);
end
Alternatively you can use sub2ind and sort instead of sparse matrix:
function shuffledArr = distShuffleSparse(myArr, myDist)
[U,~,idx] = unique(myArr);
reps = true;
while reps
S = Shuffle(idx);
f = sub2ind ( [numel(idx) + myDist, numel(U)] , 1:numel(idx), S );
reps = any (diff(sort(f)) <= myDist);
end
shuffledArr = U(S);
end
If you just want to find one possible solution you could use something like that:
x = [1 1 1 2 2 2 3 3 3 3 3 4 5 5 6 7 8 9];
n = numel(x);
dist = 3; %minimal distance
uni = unique(x); %get the unique value
his = histc(x,uni); %count the occurence of each element
s = [sortrows([uni;his].',2,'descend'), zeros(length(uni),1)];
xr = []; %the vector that will contains the solution
%the for loop that will maximize the distance of each element
for ii = 1:n
s(s(:,3)<0,3) = s(s(:,3)<0,3)+1;
s(1,3) = s(1,3)-dist;
s(1,2) = s(1,2)-1;
xr = [xr s(1,1)];
s = sortrows(s,[3,2],{'descend','descend'})
end
if any(s(:,2)~=0)
fprintf('failed, dist is too big')
end
Result:
xr = [3 1 2 5 3 1 2 4 3 6 7 8 3 9 5 1 2 3]
Explaination:
I create a vector s and at the beggining s is equal to:
s =
3 5 0
1 3 0
2 3 0
5 2 0
4 1 0
6 1 0
7 1 0
8 1 0
9 1 0
%col1 = unique element; col2 = occurence of each element, col3 = penalities
At each iteration of our for-loop we choose the element with the maximum occurence since this element will be harder to place in our array.
Then after the first iteration s is equal to:
s =
1 3 0 %1 is the next element that will be placed in our array.
2 3 0
5 2 0
4 1 0
6 1 0
7 1 0
8 1 0
9 1 0
3 4 -3 %3 has now 5-1 = 4 occurence and a penalities of -3 so it won't show up the next 3 iterations.
at the end every number of the second column should be equal to 0, if it's not the minimal distance was too big.

How can I count the specific values of an array in MATLAB?

Here is a 10x10 array arr.
This arr has 100 elements. And it has distribution from -10 to 10 and there are 5 0-value.
I did this code because I wanted to know the number of 0.
count = 0;
for i = 1: 10
     for j = 1: 10
         if (arr (i, j) == 0)
             count = count +1;
end
     end
end
Logically, count should be 5 in MATLAB's workspace. and i and j are 10.
However, when I run the code, count is 0.
This code can not count the numbers.
How can I count the numbers?
You can just use nnz to get the number of non-zero elements in a logical array, so the number of elements in arr with the value 0 is
count = nnz( arr == 0 );
Please read Why is 24.0000 not equal to 24.0000 in MATLAB? for information about comparisons of floating point numbers, you may need to do
tol = 1e-6; % some tolerance on your comparison
count = nnz( abs(arr) < tol ); % abs(arr - x) for values equal to x within +/-tol
correct me if I'm wrong but it sounds like you want the number of occurrences of the numbers in your vector, here's an alternative if that is the case:
arr=[1 2 2;3 3 3;5 0 0;0 0 0]; % example array where 1,2,3 occur 1x,2x,3x and 5=>1x, 0=>5x
[x(:,2),x(:,1)]=hist(arr(:),unique(arr(:)));
outputs sorted category as first column, occurrences as 2nd column:
x =
0 5
1 1
2 2
3 3
5 1

How can I get no. of Swap operations to form the 2nd Array

I have got two arrays with same elements... (But in different order)
e.g 1 2 12 9 7 15 22 30
and 1 2 7 12 9 20 15 22
how many swaps operations are needed to form the 2nd array from the first.?
I have tried taking no. of different elements for each index and dividing the result by 2 but that isn't fetching me the right answer...
One classic algorithm seems to be permutation cycles (https://en.m.wikipedia.org/wiki/Cycle_notation#Cycle_notation). The number of swaps needed equals the total number of elements subtracted by the number of cycles.
For example:
1 2 3 4 5
2 5 4 3 1
Start with 1 and follow the cycle:
1 down to 2, 2 down to 5, 5 down to 1.
1 -> 2 -> 5 -> 1
3 -> 4 -> 3
We would need to swap index 1 with 5, then index 5 with 2; as well as index 3 with index 4. Altogether 3 swaps or n - 2. We subtract n by the number of cycles since cycle elements together total n and each cycle represents a swap less than the number of elements in it.
1) re-index elements from 0 to n-1. In your example, arrayA becomes 0..7 and arrayB becomes 0 1 4 2 3 7 5 6.
2) sort the second array using your swapping algorithm and count the number of operations.
A bit naive, but I think you can use recursion as follows (pseudo code):
function count_swaps(arr1, arr2):
unless both arrays contain the same objects return false
if arr1.len <= 1 return 0
else
if arr1[0] == arr2[0] return count_swaps(arr1.tail, arr2.tail)
else
arr2_tail = arr2.tail
i = index_of arr1[0] in arr2_tail
arr2_tail[i] = arr2[0]
return 1+count_swaps(arr1.tail, arr2_tail)
Here's a ruby implementation:
require 'set'
def count_swaps(a1, a2)
raise "Arrays do not have the same objects: #{a1} #{a2}" unless a1.length == a2.length && Set[*a1]==Set[*a2]
return count_swap_rec(a1, a2)
end
def count_swap_rec(a1, a2)
return 0 if a1.length <= 1
return count_swaps(a1[1..-1], a2[1..-1]) if a1[0] == a2[0]
a2_tail = a2[1..-1]
a2_tail[a2_tail.find_index(a1[0])] = a2[0]
return 1 + count_swaps(a1[1..-1], a2_tail)
end

Resources