can't understand for nested loop - nested-for-loop

I am new to programming, I ran into this pattern problem which I am confused of the solution.
Output:
1
2 2
3 3 3
4 4 4 4
5 5 5 5 5
Input(correct solution):
rows = 6
for i in range(rows):
for j in range(i):
print(i, end=' ')
print('')
What I think the process of the code will be like:
In 1st iteration - i is 0; j is 0; print i; therefore, 0 is printed
In 2nd iteration - i is 1; j is 0, 1; the action is to print i; therefore, 1 is printed
In 3rd iteration - i is 2; j is 0, 1,2; the action is to print i; therefore, 2 is printed
I am sure my idea is wrong but can anyone point out what is wrong and correct me?
Thank you very much

welcome!
for i in range(rows):
for j in range(i):
The first time through, i is 0, so for j in range(i): runs zero times.
The second time, i is 1, so for j in range(i) prints 1 1 time.
The third time, i is 2, so for j in range(i) prints 2 2 times… and so on.

well, i is the iteration for changing the number (0 to 5), j is the iteration for repeating this number "i" times. so:
In 1st iteration - i is 0; j is 0; 0 is printed 0 times (none)
In 2nd iteration - i is 1; j is 0-1; prints 1 one time
In 3rd iteration - i is 2; j is 0-2; prints 2 two times
In 4th iteration - i is 3; j is 0-3; prints 3 three times

Related

How to generate continuous numbers with repetitive increment in matlab

I would like to generate a continuous number with repetitive increment, for example,from 1 to 3. with a repetitive increment of 1 (x 5). so the output will be.
output =
[1
1
1
1
2
2
2
2
2
3
3
3
3
3]
five repetition of 1, then five repetition of 2 and so on.
I tried this code:
a = [1:1:3]
for i = a(:,1:end)
disp(i+zeros(5,1))
end
I got the same result, however, I can't put the output in one column. Thanks for the help.
Let
n = 3; % number of distinct numbers
s = 2; % starting number
m = 5; % number of repetitions of each number
A couple of options are
output = repelem(s:s+n-1,m);
or
output = ceil(s-1+1/m:1/m:s+n-1);

How to do following in Matlab?

Suppose I have a sequence of n numbers
e=[5,4,45,63,22,22,1,12,3,2,2,16,14,14,16,17,1,19,21,15,32,32,27,27,43,41,7,8,13,23,23]
then for first 10 numbers i.e.
[5,4,45,63,22,22,1,12,3,2]
count numbers other than 1 to 5 and then divide by 10, i.e.
[45,63,22,22,12]
total 5, so result should be 5/10,now for first 20 numbers i.e.
[5,4,45,63,22,22,1,12,3,2,2,16,14,14,16,17,1,19,21,15]
then
[45,63,22,22,12,16,14,14,16,17,19,21,15]
total = 13, so 13/20, like this for 10, 20, 30,... up to n numbers
and then plot figure with x axis points 0 10 20 30 ... n and y axis with 5/10, 13/20, ... how to do this
I tried by this
for e=10:10:400
for u=1:length(e)
d=(numel(u)>5)
h=d/u
end
end
but it shows different.
Try this
e= [5,4,45,63,22,22,1,12,3,2,2,16,14,14,16,17,1,19,21,15,32,32,27,27,43,41,7,8,13,23,23];
bins = 10:10:numel(e);
counts = NaN(1,numel(bins)); %// pre-allocation. I'm pre-allocating with NaN here instead of zeros because 0 is a valid result for an element of counts and thus could make us miss errors should something go wrong
for k = 1:numel(bins)
counts(k) = sum(e(1:bins(k)) > 5)/bins(k);
end
plot(bins, counts) %// or you might prefer bar(bins, counts)
Here e(1:bins(k)) will be the first 10 elements of e in the first iteration of the loop, the first 20 in the second and so on. sum(... > 10) just counts how many elements are greater than 5. To understand how this works, consider x = [3 4 5 6 7 8 5 1 2]. Now x > 5 will return the logical array [0 0 0 1 1 1 0 0 0], so sum(x>10) is the same as sum([0 0 0 1 1 1 0 0 0]) which is 3 i.e. the count of elements in x greater than 5. Now you just need to store this count in a different element of counts at each iteration hence we have counts(k) = ... and not counts = ... as the latter (i.e. how your code has it) just overrides counts with the scalar count at each iteration rather than creating a vector that records each count at each iteration.
In MATLAB you can often do away with loops and you can do so in this case as well:
counts = cumsum(e > 5)./(1:numel(e));
h = counts(10:10:end);
Hope, this can help you
n=30 % this because of the 'e' size
Lim = 5 % your limit
Steps = 10 %
xValues = Steps:Steps:n
PlotSeries = NaN(size(e,2)/Steps,2)
for x = 1:1:size(e,2)/Steps
PlotSeries(x,:) = [xValues(x),size(e(e(1:xValues(x))>Lim),2)/xValues(x)]
end
plot(PlotSeries)

multichoice Matlab for loops [closed]

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 8 years ago.
Improve this question
Can anyone tell me how I would work this out manually?
Consider the following MATLAB function:
function Anew = mystery( A )
N=5;
for ii=2:N
Anew(ii)= A(ii-1);
end
end
If we define v = [0,1,2,3,4,5,6,7,8,9,10]. What would be the output of x = mystery(v) be?
a) x = [1 2 3 4 5 6 7 8 9 10]
b) x = [1 2 3 4 5 6]
c) x = [0 1 2 3 4 5]
d) x = [0 0 1 2 3]
OK, let's step through this code line by line.
The first line:
N = 5;
This basically creates a variable called N and stores the value of 5 in it. No biggie.
Next line:
for ii = 2 : N
This is a for loop, and each time the loop iterates, the value of ii will change by 1. The first time the loop runs, ii = 2, then the next time it starts again, ii = 3 up to ii = 5, then the loop stops.
So, let's start at the beginning with ii = 2. The statement inside the loop is equivalent to:
Anew(2) = A(2-1);
This simplifies to:
Anew(2) = A(1);
If you look at the code, Anew was never defined up until this point. When you try to assign a value to a location in an array that was not previously declared, MATLAB will fill up the values that are before the location of where you assigned to be zero automatically. As such, if you did:
Anew(8) = 9; %// For example
Anew would look like this:
Anew =
0 0 0 0 0 0 0 9
The 8th position has the value of 9, while the other positions before the 8th one are all zero. Therefore, by doing Anew(2) = A(1);, the first position of Anew is zero, while the second position of Anew gets the first value of A and puts it here. As such, Anew currently looks like:
Anew =
0 0
Let's do ii = 3. This means that in your loop, the statement simplifies to:
Anew(3) = A(3-1);
.... which is:
Anew(3) = A(2);
This means that the third position of Anew gets the second element of A copied over here. Note that the original size of Anew was 2. By doing Anew(3) = A(2);, MATLAB will automatically adjust the size of Anew, and then put what A(2) is into the third position of Anew. Therefore, Anew looks like:
Anew =
0 0 1
As a little test, if we were to do Anew(6) = A(2);, this is what it would look like:
Anew =
0 0 0 0 0 1
Note that we previously had Anew = [0 0]; before this point. By doing Anew(6) = A(2);, the 3rd, 4th and 5th positions of Anew get filled with 0, and the 6th position gets the value of 1, which is A(2).
You can probably see a pattern now. Each position of Anew gets the element of A shifted to the left by 1. Therefore, for ii = 4:
Anew(4) = A(3);
What it looks like now is:
Anew =
0 0 1 2
Finally for ii = 5, we get:
Anew(5) = A(4);
What it looks like now is:
Anew =
0 0 1 2 3
After the end of this loop, Anew gets returned as the output of mystery.
Therefore, the answer is (d): x = [0 0 1 2 3];.
Hope this helps!

Generate random non-repeating integers from a small range

What I'm trying to accomplish is the following:
I wish to create a vector of integers, from a relatively small range, and ensure that none of the integers will be followed by the same integer.
i.e., This is a "legal" vector:
[ 1 3 4 2 5 3 2 3 5 4 ]
and this is an "illegal" vector (since 5 follows 5):
[ 1 3 4 2 5 5 2 3 5 4 ]
I've experimented with randi, and all sorts of variations with randperm, and I always get stuck when i try to generate a vector of around 100 elements, from a small range (i.e., integers between 1 and 5).
The function just runs for too long.
Here's one of the attempts that i've made:
function result = nonRepeatingRand(top, count)
result = randi(top, 1, count);
while any(diff(result) == 0)
result = randi(top, 1, count);
end
end
Any and all help will be much appreciated. Thanks !
The kind of sequence you are looking for can be defined by generating differences from 1 to top - 1 and then computing the cumulative sum modulus top, starting from a random initial value:
function result = nonRepeatingRand(top, count)
diff = randi(top - 1, 1, count);
result = rem(cumsum(diff) + randi(1, 1, count) - 1, top) + 1;
end
On my machine, this generates a non-repeating sequence of 10 million numbers out of 1:5 in 0.58 seconds.
you can use the following code for generate Non Repeating Random Numbers from 1 to M
randperm(M);
and for K Non Repeating Random Numbers from 1 to M
randperm(M, K);
enjoy
Do not regenerate the sequence every time, but fix the repetitions. E.g.:
function result = nonRepeatingRand(top, count)
result = randi(top, 1, count);
ind = (diff(result) == 0);
while any(ind)
result(ind) = [];
result(end + 1 : count) = randi(top, 1, count - numel(result));
ind = (diff(result) == 0);
end
end
On my machine, this generates a non-repeating sequence of 10 million numbers out of 1:5 in 1.6 seconds.
Taking the idea from A. Donda but fixing the implementation:
r=[randi(top,1,1),randi(top - 1, 1, count-1)];
d=rem(cumsum(r)-1,top)+1;
The first element of r is a randomly chosen element to start with. The following elements of r randomly choose the difference to the previous element, using modulo arithmetic.
How this?
top = 5;
count = 100;
n1 = nan;
out = [];
for t = 1: count
n2 = randi(top);
while n1 == n2
n2 = randi(top);
end
out = [out, n2];
n1 = n2;
end

MATLAB - Efficient methods for populating matrices using information in other (sparse) matrices?

Apologies for the awkward title, here is a more specific description of the problem. I have a large (e.g. 10^6 x 10^6) sparse symmetric matrix which defines bonds between nodes.
e.g. The matrix A = [0 1 0 0 0; 1 0 0 2 3; 0 0 0 4 0; 0 2 4 0 5; 0 3 0 5 0] would describe a 5-node system, such that nodes 1 and 2 are connected by bond number A(1,2) = 1, nodes 3 and 4 are connected by bond number A(3,4) = 4, etc.
I want to form two new matrices. The first, B, would list the nodes connected to each node (i.e. each row i of B has elements given by find(A(i,:)), and padded with zeros at the end if necessary) and the second, C, would list the bonds connected to that node (i.e. each row i of C has elements given by nonzeros(A(i,:)), again padded if necessary).
e.g. for the matrix A above, I would want to form B = [2 0 0; 1 4 5; 4 0 0; 2 3 5; 2 4 0] and C = [1 0 0; 1 2 3; 4 0 0; 2 4 5; 3 5 0]
The current code is:
B=zeros(length(A), max(sum(spones(A))))
C=zeros(length(A), max(sum(spones(A))))
for i=1:length(A)
B(i,1:length(find(A(i,:)))) = find(A(i,:));
C(i,1:length(nonzeros(A(i,:)))) = nonzeros(A(i,:));
end
which works, but is slow for large length(A). I have tried other formulations, but they all include for loops and don't give much improvement.
How do I do this without looping through the rows?
Hmm. Not sure how to vectorize (find returns linear indices when given a matrix, which is not what you want), but have you tried this:
B=zeros(length(A), 0);
C=zeros(length(A), 0);
for i=1:length(A)
Bi = find(A(i,:));
B(i,1:length(Bi)) = Bi;
Ci = nonzeros(A(i,:));
C(i,1:length(Ci)) = Ci;
end
I made two changes:
removed call to spones (seems unnecessary; the performance hit needed to expand the # of columns in B and C is probably minimal)
cached result of find() and nonzeros() so they're not called twice
I know it's hard to read, but that code is a vectorized version of your code:
[ i j k ] = find(A);
A2=(A~=0);
j2=nonzeros(cumsum(A2,2).*A2);
C2=accumarray([i,j2],k)
k2=nonzeros(bsxfun(#times,1:size(A,2),A2));
B2=accumarray([i,j2],k2);
Try it and tell me if it works for you.