Index exceeds the number of array elements (9) in MATLAB - arrays

So I am getting an error where I believe n1 is larger than the array after n becomes n = 3, which is giving the error in ma. Premise of the code is to take 1 2, 3 4 5, 6 7 8 9, etc. and average each group. Pretty sure I have to change the length but not sure how to go about it. What should I do? Here is the code:
clear all
mdata = [1 2 3 4 5 6 7 8 9];
n1 = 1;
k = 1;
for n = 1:length(mdata)
ma(n) = (1/(k + 1)) * sum(mdata(n1:n1 + k));
n1 = ((n1 + k) + 1);
k = k + 1;
std_ma = std(mdata);
end
Error message:
Index exceeds the number of array elements (9).
Error in untitled22 (line 11)
ma(n) = (1/(k + 1)) * sum(mdata(n1:n1 + k));

The issue is that you are replacing the value of n1 with n1+k+1 on each step through the loop. At the start of the 4th iteration, n1=10 and k=4, meaning you are trying to take the sum of elements 10:14 but the array only has 9 elements.
It is not clear from your question exactly what averages you are trying to calculate through all of the iterations of the loop and so it is difficulty to say more. But, most likely, you do not need to manually calculate the average yourself. Just define the subset of the data you want to work with on that iteration and take the mean of that.
I am also guessing that you want to modify the assignment of std_ma at the end of your loop to only perform the std on the subset of data you are working with. Currently you are doing the calculation over all values in mdata and repeating that same calculation 9 times.

Related

How to iterate through a circular array multiple times in python?

I want to circle through the array multiple times. When I reach the last index, the next index should be the first one.
For example, I have an array of 6 elements
array1 = [1,2,3,4,5,6]
and I have K = 4. K will be the number of elements that I will skip.
In the above example, I will start from array1[0] and skip K elements including the array1[0] element.
So if I skip 4 elements, I will reach array1[4]. If I skip K elements once more, I should skip array1[4], array1[5], array1[0] and array1[1] and reach array1[2]. This process will repeat itself N times.
I tried searching for the solution online because I cannot think of a way to move through the array in circle. I found one solution that says to use modulo operator like this
print a[3 % len(a)]
but I cannot understand this since I am just starting out with python.
Understanding what modulo is will be helpful https://en.wikipedia.org/wiki/Modulo
To sum up, in this exercise you don't care how many times you went through the array. You only care about "at which position of the current iteration you are" lets say. Therefore, a modulo operation using the length of the array as modulo will give you the remainder of such division, which is exactly what you are looking for.
Example:
arr = [1,2,3,4,5]
k = 27
arrlength = len(arr) # 5
reminder = k % arrlength # 27 % 5 = 2
arr[reminder] # 3
So, the modulo operator returns the remainder from the division between two numbers.
Example:
6 % 2 = 0 # because 6/2 = 3 with no remainder
6 % 5 = 1 # because 6/5 = 1 (integer part) plus remainder 1
6 % 7 = 6 # because 7 doesn't fit in 6, so all the dividend goes into the remainder
So your problem can be solved by something like this:
arr = [1,2,3,4,5,6]
N = 5
step = 4
for i in range(5):
print(arr[(i+1)*step%len(arr)])
where N is the number of elements you want to print
This is the same as creating an extended list such as:
b = arr * 1000
and print each element in range(step,(N+1)*step,step).
Of course this method is not optimal since you don't now how many arrays arr you have to concatenate in order not to go out of bounds.
Hope it helped

For what cases will this logic of this code fail?

In a coding site I came across a question which seem to be very easy. But when I implement a solution it gives me wrong answers for the hidden test cases. I tried to find for what cases it failed but I just couldn't get any.
The question goes as follows
Construct an N×M matrix with entries having positive integers such that
If M>1, ith row is strictly increasing from left to right with a fixed common difference di
for all 1≤i≤N.
If N>1, jth column is strictly increasing from top to bottom with a fixed common difference cj
for all 1≤j≤M.
All the common differences should be distinct.
In the case of multiple answers, find an arrangement that minimizes the maximum element of the
matrix.
The code with the logic
#include<stdio.h>
#include<stdlib.h>
int main(){
int t=0,n=0,m=0,d=0;
scanf("%d",&t);
while(t--){
scanf("%d%d",&n,&m);
if(n>=m){
d=2;
for(int i=0;i<n;i++){
for(int j=0;j<m;j++){
printf("%d ",(i+1) + j*d);
}
d+=2;
printf("\n");
}
}
else{
d=1;
for(int i=0;i<n;i++){
for(int j=0;j<m;j++){
printf("%d ",(2*i+1) + j*d);
}
d+=2;
printf("\n");
}
}
}
return 0;
}
Sample input
3
3 3
1 2
1 1
Sample Output
1 2 3
3 6 9
5 10 15
1 2
1
Simple logic I tried was, check if the rows are more or the columns, whichever is more increment that by even number C.D (from 2,4,6....) and the other in odd number C.D(from 1,3,5...)
For example: for 2X3
The matrix will be
1 3
2 6
3 9
This logic seems to be correct and while discussing with my friends even they say its right. But I get wrong answers while submitting to the hidden cases.
What logic error might have I done? Could you give me a example for which this code will fail?
The matrix shown in the question for the 2×3 case is:
1 3
2 6
3 9
However, a better solution is:
1 4
2 6
3 8
We see this satisfies the constraints:
Each row and each column is strictly increasing.
Each row has a fixed difference: 3, 4, and 5.
Each column has a fixed difference: 1 and 2.
All those differences are distinct.
A general solution follows.
Let the matrix be Ai, j. It is clear A0, 0 should be 1. Let A0, 1, A1, 0, and A1, 1 be 1+a, 1+b, and 1+c, respectively. Then simple algebra and induction shows that Ai, j is 1 + (1−i)ja + i(1−j)b + ijc.
The common difference in column j is b+j(c−a−b), and the common difference is row i is a+i(c−a−b). These form two arithmetic series with the same step size, c−a−b, so they do not intersect only if they either interleave (for example, c−a−b could be 2 and one of a or b can be odd while the other is even) or one series is entirely less than the other (for example, c−a−b could be 1). We will consider these cases below.
Let I and J be the maximum subscripts in the array, m−1 and n−1, respectively. (These are introduced for brevity, as m−1 and n−1 appear repeatedly below.) The maximum element in the array, AI,J, is 1 + (1−I)Ja + I(1−J)b + IJc = 1 + IJ(c−a−b) + Ja + Ib. Observe the derivative with respect to c is positive, so, once a and b are chosen, the minimum value for AI,J is obtained by making c as small as the constraints allow, hence either c = a+b+1 (for the case when one series is entirely less than the other) or c = a+b+2 (for the case when the series interleave). For the former, AI,J = 1 + IJ + Ja + Ib. For the latter, AI,J = 1 + 2IJ + Ja + Ib. This reveals we also wish to minimize a and b subject to the constraints.
The smallest a and b can be is 1 and 2 (in either order). So in the interleaving case, we have either AI,J = 1 + 2IJ + J + 2I or AI,J = 1 + 2IJ + 2J + I. To obtain the lesser of these, we choose a = 1, b = 2 if J < I and a = 2, b = 1 otherwise. Combinging these, the maximum is 1 + 2IJ + I + J + min(I, J). Restoring m and n from I and J and doing a little algebra gives us a maximum of 2mn − max(m, n).
For the non-interleaving case, we could have a = 1, the largest row difference (generally a+i(c−a−b)) of 1+I•1 = 1+I, so b = 2+I to start the column differences (generally b+j(c−a−b)) with b + 0(c−a−b) = 2+I. Conversely, we could have b = 1 and a = 2+J. Then we have AI,J = 1+ IJ + J + I(2+I) or 1 + IJ + J(2+J) + I, or, equivalently, mn+m2−m or mn+n2−n. The former is less when m < n and vice-versa.
Note than when m ≤ n, the interleaved case gives us a maximum of 2mn − n = mn + m2 + (m−1)(n−m) − m. Since (m−1)(n−m) is non-negative, that is at least as large as mn+m2−m, which is the maximum for the non-interleaved case. The analogous result holds for n ≤ m. Therefore, the interleaved case never has any advantage. The minimum is always obtained with the non-interleaved case with either a = 1, b = 2+I = m+1 or a = 2+J = n+1, b = 1, according to which of m and n is smaller.

How to find a sum 3 elements in array?

I have an array A=[a1,a2,a3, ..., aN] I would like to take a product of each 3 elements:
s1=a1+a2+a3
s2=a4+a5+a6
...
sM=a(N-2)+a(N-1)+aN
My solution:
k=size(A);
s=0;
for n=1:k
s(n)=s(n-2)+s(n-1)+s(n);
end
Error: Attempted to access s(2); index out of bounds because numel(s)=1.
Hoe to fix it?
If you want to sum in blocks, for the general case when the number of elements of A is not necessarily a multiple of the block size, you can use accumarray:
A = [3 8 5 8 2 3 4 7 9 6 4]; % 11 elements
s = 3; % block size
result = accumarray(ceil((1:numel(A))/s).', A(:));
If you want a sliding sum with a given block size, you can use conv:
A = [3 8 5 8 2 3 4 7 9 6 4]; % 11 elements
s = 3; % block size
result = conv(A(:).', ones(1,s), 'valid');
You try to calculate sby using values from s. Dont you mean s(n)=A(n-2)+A(n-1)+A(n);? Also size returns more than one dimension on its own.
That being said, getting the 2 privous values n-2 and n-1 doenst work for n=1;2 (because you must have positive indices). You have to explain how the first two values should be handeled. I assume either 0 for elements not yet exisiting
k=size(A,2); %only the second dimension when A 1xn, or length(A)
s=zeros(1,k); %get empty values instead of appending each value for better performance
s(1)=A(1);
s(2)=A(2)+A(1);
for n=3:k %start at 3
s(n)=A(n-2)+A(n-1)+A(n);
end
or sshoult be 2 values shorter than A.
k=size(A,2);
s=zeros(1,k-2);
for n=1:k-2
s(n)=A(n)+A(n+1)+A(n+2);
end
You initialise s as a scalar with s = 0. Then you try and index it like an array, but it only has a single element.
Your current logic (if fixed) will calculate this:
s(1) = a(1)+a(2)+a(3)
s(2) = a(2)+a(3)+a(4)
...
% 's' will be 2 elements shorter than 'a'
So we need to be a bit wiser with the indexing to get what you describe, which is
s(1) = a(1)+a(2)+a(3)
s(2) = a(4)+a(5)+a(6)
...
% 's' will be a third as big as 'a'
You should pre-allocate s to the right size, like so:
k = numel(A); % Number of elements in 'A'
s = zeros( 1, k/3 ); % Output array, assuming 'k' is divisible by 3
for n = 0:3:k-3
s(n/3+1) = a(n+1) + a(n+2) + a(n+3);
end
You could do this in one line by reshaping the array to have 3 rows, then summing down each column, this assumes that the number of elements in a is divisible by 3, and that a is a row vector...
s = sum( reshape( a, 3, [] ) );

loop to remove repeated elements of a vector and add corresponding elements of another vector

I am using MATLAB to write a code that multiplies polynomials. Most parts of my code work however there is one part where I have two row vectors a and b. I want to remove repeated elements of a and then add the corresponding elements of b. This is what I have written
c=length(a);
d=length(b);
remove=[];
for i=1:c
for j=i+1:c
if (a(i)==a(j))
remove=[remove,i];
b(j)=b(i)+b(j);
end
end
end
a(remove)=[];
b(remove)=[];
The problem with this is if there is an element in a that appears more than twice, it doesn't work properly.
For example if a=[5,6,8,9,6,7,9,10,8,9,11,12] and b=[1,7,1,-1,3,21,3,-3,-4,-28,-4,4]
then once this code is run a becomes [5,6,7,10,8,9,11,12] which is correct but b becomes [1,10,21,-3,-3,-27,-4,4] which is correct except the -27 should be a -26.
I know why this happens because the 9 in a(1,4) gets compared with the 9 in a(1,7) so b(1,7) becomes b(1,7)+b(1,4) and then a(1,4) gets compared with the 9 in a(1,10). and then later the a(1,7) compares with a(1,10) and so the new b(1,7) adds to the b(1,10) however the b(1,4) adds to the b(1,10) too. I somehow need to stop this once one repeated element has been found because here b(1,4) has been added twice when it should only be added once.
I am not supposed to use any built in functions, is there a way of resolving this easily?
I would prefer using built in functions, but assuming you have to stick to your own approach, you can try this:
a=[5,6,8,9,6,7,9,10,8,9,11,12];
b=[1,7,1,-1,3,21,3,-3,-4,-28,-4,4];
n = numel(a);
remove = zeros(1,n);
temp = a;
for ii = 1:n
for jj = ii+1:n
if temp(ii) == temp(jj)
temp(ii) = NaN;
remove(ii) = ii;
b(jj) = b(jj) + b(ii);
end
end
end
a(remove(remove>0)) = []
b(remove(remove>0)) = []
a =
5 6 7 10 8 9 11 12
b =
1 10 21 -3 -3 -26 -4 4
It's not much different from your approach, except for changing the iith value of a if it is found later. To avoid overwriting the values in a with NaN, I'm using a temporary variable for this.
Also, as you can see, I'm avoiding remove = [remove i], because this will create a growing vector, which is very slow.
It can be solved in a vectorized manner with the following indexing nightmare (perhaps someone will come up with a simpler approach):
a = [5,6,8,9,6,7,9,10,8,9,11,12];
b = [1,7,1,-1,3,21,3,-3,-4,-28,-4,4];
[sa, ind1] = sort(a);
[~, ii, jj] = unique(sa);
[ind2, ind3] = sort(ind1(ii));
a = a(ind2);
b = accumarray(jj(:),b(ind1)).';
b = b(ind3);
Anyway, to multiply polynomials you could use conv:
>> p1 = [1 3 0 2]; %// x^3 + 3x^2 + 1
>> p2 = [2 -1 4]; %// 2x^2 - x + 4
>> conv(p1,p2)
ans =
2 5 1 16 -2 8 %// 2x^5 + 5x^4 + x^3 + 16x^2 - 2x + 8

matlab: eliminate elements from array

I have quite big array. To make things simple lets simplify it to:
A = [1 1 1 1 2 2 3 3 3 3 4 4 5 5 5 5 5 5 5 5];
So, there is a group of 1's (4 elements), 2's (2 elements), 3's (4 elements), 4's (2 elements) and 5's (8 elements). Now, I want to keep only columns, which belong to group of 3 or more elements. So it will be like:
B = [1 1 1 1 3 3 3 3 5 5 5 5 5 5 5 5];
I was doing it using for loop, scanning separately 1's, 2's, 3's and so on, but its extremely slow with big arrays...
Thanks for any suggestions how to do it in more efficient way :)
Art.
A general approach
If your vector is not necessarily sorted, then you need to run to count the number of occurrences of each element in the vector. You have histc just for that:
elem = unique(A);
counts = histc(A, elem);
B = A;
B(ismember(A, elem(counts < 3))) = []
The last line picks the elements that have less than 3 occurrences and deletes them.
An approach for a grouped vector
If your vector is "semi-sorted", that is if similar elements in the vector are grouped together (as in your example), you can speed things up a little by doing the following:
start_idx = find(diff([0, A]))
counts = diff([start_idx, numel(A) + 1]);
B = A;
B(ismember(A, A(start_idx(counts < 3)))) = []
Again, note that the vector need not to be entirely sorted, just that similar elements are adjacent to each other.
Here is my two-liner
counts = accumarray(A', 1);
B = A(ismember(A, find(counts>=3)));
accumarray is used to count the individual members of A. find extracts the ones that meet your '3 or more elements' criterion. Finally, ismember tells you where they are in A. Note that A needs not be sorted. Of course, accumarray only works for integer values in A.
What you are describing is called run-length encoding.
There is software for this in Matlab on the FileExchange. Or you can do it directly as follows:
len = diff([ 0 find(A(1:end-1) ~= A(2:end)) length(A) ]);
val = A(logical([ A(1:end-1) ~= A(2:end) 1 ]));
Once you have your run-length encoding you can remove elements based on the length. i.e.
idx = (len>=3)
len = len(idx);
val = val(idx);
And then decode to get the array you want:
i = cumsum(len);
j = zeros(1, i(end));
j(i(1:end-1)+1) = 1;
j(1) = 1;
B = val(cumsum(j));
Here's another way to do it using matlab built-ins.
% Set up
A=[1 1 1 1 2 2 3 3 3 3 4 4 5 5 5 5 5];
threshold=2;
% Get the unique elements of the array
uniqueElements=unique(A);
% Count haw many times each unique element occurs
counts=histc(A,uniqueElements);
% Write which elements should be kept
toKeep=uniqueElements(counts>threshold);
% Make a logical index
indexer=false(size(A));
for i=1:length(toKeep)
% For every unique element we want to keep select the indices in A that
% are equal
indexer=indexer|(toKeep(i)==A);
end
% Apply index
B=A(indexer);

Resources