How to keep track of recursive call on my function collatz? - matlab

I am trying to keep track of how many times the function call itself. I have tried setting up num as 0 and putting num = num+1 at the end but I keep getting 1. How do I fix this?
function [out num] = collatz(val)
num = 0;
if val == 1
out = 1;
elseif mod(val, 2) == 0
out = collatz(val/2);
else
out = collatz(3*val+1);
end
num = num+1;
end
Thank you.

A possible approach is to use a global variable to count the number of calls. You need to declare that variable as global
in the workspace from which you call collatz the first time; and
within the function.
The function is thus defined as:
function out = collatz(val)
global num %// declare as global within the function
num = num+1; %// increase call counter
if val == 1
out = 1;
elseif mod(val, 2) == 0
out = collatz(val/2);
else
out = collatz(3*val+1);
end
end
And then, from the command line:
>> clear all
>> global num %// declare as global in workspace
>> num = 0; %// initiallize to 0
>> collatz(5)
ans =
1
>> num %// see value of num
num =
6

When you recursively call collatz you should save num too.
[out,num] = collatz(val/2);

You can also avoid using global declarations by changing your recursive calls in collatz so that they output num as well. You'll also need to change the base case so that num = 0 when val = 1. Therefore, do this instead:
function [out,num] = collatz(val)
if val == 1
out = 1;
num = 0; %// Change
elseif mod(val, 2) == 0
[out,num] = collatz(val/2); %// Change
else
[out,num] = collatz(3*val+1); %// Change
end
num = num+1;
end
You can then use collatz so that num is also output when you call it in the command prompt. When I do this, and calling collatz with 5, I get:
[out,num] = collatz(5)
out =
1
num =
6

Related

Output 1, 0.5, or 0 depending if a matrix elements are prime, 1, or neither

I am sending a matrix to my function modifikuj, where I want to replace the elements of the matrix with:
1 if element is a prime number
0 if element is a composite number
0.5 if element is 1
I dont understand why it is not working. I just started with MATLAB, and I created this function:
function B = modifikuj(A)
[n,m] = size(A);
for i = 1:n
for j = 1:m
prost=1;
if (A(i,j) == 1)
A(i,j) = 0.5;
else
for k = 2:(A(i,j))
if(mod(A(i,j),k) == 0)
prost=0;
end
end
if(prost==1)
A(i,j)=1;
else
A(i,j)=0;
end
end
end
end
With
A = [1,2;3,4];
D = modifikuj(A);
D should be:
D=[0.5, 1; 1 0];
In MATLAB you'll find you can often avoid loops, and there's plenty of built in functions to ease your path. Unless this is a coding exercise where you have to use a prescribed method, I'd do the following one-liner to get your desired result:
D = isprime( A ) + 0.5*( A == 1 );
This relies on two simple tests:
isprime( A ) % 1 if prime, 0 if not prime
A == 1 % 1 if == 1, 0 otherwise
Multiplying the 2nd test by 0.5 gives your desired condition for when the value is 1, since it will also return 0 for the isprime test.
You are not returning anything from the function. The return value is supposed to be 'B' according to your code but this is not set. Change it to A.
You are looping k until A(i,j) which is always divisible by itself, loop to A(i,j)-1
With the code below I get [0.5,1;1,0].
function A = modifikuj(A)
[n,m] = size(A);
for i = 1:n
for j = 1:m
prost=1;
if (A(i,j) == 1)
A(i,j) = 0.5;
else
for k = 2:(A(i,j)-1)
if(mod(A(i,j),k) == 0)
prost=0;
end
end
if(prost==1)
A(i,j)=1;
else
A(i,j)=0;
end
end
end
end
In addition to #EuanSmith's answer. You can also use the in built matlab function in order to determine if a number is prime or not.
The following code will give you the desired output:
A = [1,2;3,4];
A(A==1) = 0.5; %replace 1 number with 0.5
A(isprime(A)) = 1; %replace prime number with 1
A(~ismember(A,[0.5,1])) = 0; %replace composite number with 0
I've made the assumption that the matrice contains only integer.
If you only want to learn, you can also preserve the for loop with some improvement since the function mod can take more than 1 divisor as input:
function A = modifikuj(A)
[n,m] = size(A);
for i = 1:n
for j = 1:m
k = A(i,j);
if (k == 1)
A(i,j) = 0.5;
else
if all(mod(k,2:k-1)) %check each modulo at the same time.
A(i,j)=1;
else
A(i,j)=0;
end
end
end
end
And you can still improve the prime detection:
2 is the only even number to test.
number bigger than A(i,j)/2 are useless
so instead of all(mod(k,2:k-1)) you can use all(mod(k,[2,3:2:k/2]))
Note also that the function isprime is a way more efficient primality test since it use the probabilistic Miller-Rabin algorithme.

Matlab recursion

Need a little help understanding what is happening in this function particularly line 7 [Fnm1,Fnm2] = fibrecurmemo(N-1); I don't understand how a new variable can be declared here with in the array. an example of what is happening would be appreciated.
function [Fn,Fnm1] = fibrecurmemo(N)
% Computes the Fibonacci number, F(N), using a memoized recursion
if N <= 2
Fn = 1;
Fnm1 = 1;
else
[Fnm1,Fnm2] = fibrecurmemo(N-1);
Fn = Fnm1 + Fnm2;
end
end
Say we start with:
fibrecurmemo(3) %// N is 3
The else statements run (since N > 2):
[Fnm1,Fnm2] = fibrecurmemo(2); %//statement 1
Fn = Fnm1 + Fnm2; %//statement 2
Before statement 2 can run, fibrecurmemo(2) must first run.
The if statements in fibrecurmemo(2) run (since N <= 2):
Fn = 1;
Fnm1 = 1;
As a result, fibrecurmemo(2) returns 1, 1.
Contininuing from statement 1 above,
[1,1] = fibrecurmemo(2); %//statement 1
Fn = 1 + 1; %//statement 2
Finally,
[2, 1] = fibrecurmemo(3);
The function returns two values.
function [xFive,yFive] = addFive(x,y)
xFive = x + 5;
yFive = y + 5;
end
xx = (addFive(3,4))
xx will be equal to 8 in this example
the syntax for assignment for multiple return values is
[a,b,c,...] = someFunc();
where someFunc() has output of [a,b,c,...]
[aa,bb] = addFive(3,4);
cc = addFive(3,4);
if you do it this way you would get
aa == 8
bb == 9
cc == 8
in the case of cc instead of [aa,bb] Then you will just get the first return value.
i.e. you could do
x = fibrecurmemo(5)
[y,z] = fibrecurmemo(5)
in this case x == y

Stopping the output of a for cycle in matlab

I'm facing an issue with this simple Fibonacci number generator program:
function f = fibonr(n)
f(1) = 1;
f(2) = 1;
for i = 3:n
f(i) = f(i-1) + f(i-2);
end
end
If I want to display only the n-th number of the sequence, what adjustments should I make?
function f = fibonr(n)
f = zeros(n,1); %//initialise the output array
f(1,1) = 1;
f(2,1) = 1;
for ii = 3:n
f(ii,1) = f(ii-1,1) + f(ii-2,1);
end
%//create a string with text and variables
str = sprintf('The %d th number in the Fibonacci sequence is %d',n,f(ii,1));
disp(str) %//display your output.
end
first up: don't use i as a variable. Secondly, I switched to using column vectors, since MATLAB processes them faster, as well as I initialised the array, which is way faster (hence the shiny orange wiggles below your f(i)= line).
Call your function:
output = fibonr(10);
The 10 th number in the Fibonacci sequence is 55
If you use e.g. n=20 and still want the 10th argument just call output(10)
if you want the specified output right away you can use nargin. This code will give you all of the sequence if you call fibonr(n), or you can specify a vector to get the fibonacy numbers at said positions. If you are interested in both, your specified output and all the numbers, you can call the function with:
[output, fibnumbers] = fibonr(n,v);
function [output,f] = fibonr(n,v)
f(1) = 1;
f(2) = 1;
for i = 3:n
f(i) = f(i-1) + f(i-2);
end
if nargin() > 1
output = f(v);
else
output = f;
end

Matlab programming error

I am trying out the questions in programming assignment of Coursera course on Matlab programming as an exercise. This is for my self-study.
Question:
Write a function called classify that takes one input argument x. That
argument will have no more than two dimensions. If x is an empty
matrix, the function returns -1. If x is a scalar, it returns 0. If x
is a vector, it returns 1. Finally, if x is none of these, it returns
2. Do not use the built-in functions isempty, isscalar, or isvector.
My code snippet:
function num = classify(x)
num = -1;
if(x == 3.14159265358979)
num = 0;
elseif(size(x, 2) == 3)
num = -1;
end
end
I got the below result on Matlab.
Problem 4 (classify):
Feedback: Your function performed correctly for argument(s) []
Feedback: Your function performed correctly for argument(s) zeros(1,0)
Feedback: Your function performed correctly for argument(s) zeros(0,4)
Feedback: Your function performed correctly for argument(s) 3.14159265358979
Feedback: Your function made an error for argument(s) [1 2 3]
Am I doing something wrong for arguments [1 2 3]?
If all you want is the code, I'll provide you with the answer, but I suggest you sit down and try to understand how and why this codes solves the problem, I'm guessing you want to learn something from it. Well, here's the code:
function [num] = classify(x)
if numel(x) == 0
num = -1;
return
end
num = sum(size(x) > 1);
end
You can most easily check if x is empty or a scalar by counting the number of elements (i.e. use the numel function). Then to determine if it is a vector or a higher dimensional matrix you need to check if the number of dimensions is less than 3 (this is because ndims returns 2 for both 1D and 2D matrices) and also verify that at least one of the first two dimensions has a size of 1:
function num = classify(x)
n = numel(x);
if n < 2
num = n-1;
else
if ndims(x) < 3 && any(size(x) == 1)
num = 1;
else
num = 2;
end
end
end
You should aim to write a generic function, your function would not work for example for any scalar input than pi.
Use the size function to determine the dimensions of the input, for example:
>> size([])
ans = 0 0
>> size(5)
ans = 1 1
>> size([5 6 7])
ans = 1 3
>> size([5;6;7])
ans = 3 1
Based on this, your function could looke like this:
function [num] = classify(x)
s = size(x);
if s == [0 0]
num = -1;
elseif s == [1 1]
num = 0;
elseif sort(s) == [1 3]
num = 1;
else
num = 2;
end
end
Yes, you tring to compare an array with a float.
It allows to do that (programaticalyl wrong) thing for [] because the array is empty
And for zeros, because the array is empty again: in the first case 0 columns, and in the second 0 rows
function i=classify(x)
[m, n]=size(x);
if n==1 && m==1
i=0;
elseif (m==0 && n==0)|| (m>=1 && n==0) || (m==0 && n>=1)
i=-1;
elseif (n>=1 && m==1) || (n==1 && m>=1)
i=1;
else i=2;
end
function y=classify(x)
[a b]=size(x);
%check for empty matrix
% Do not forget that an empty matrix can be size a x 0 or 0x a, where a can be
% arbitrary number
if (a>0)&&(b==0)||(a==0)&&(b>0)||(a==0)&&(b==0)
y=(-1);
%check for scalar
elseif (a==1)&&(b==1)
y=0;
%check for vector
elseif (a>=1)&&(b==1)||(a==1)&&(b>=1)
y=1;
%other case
else
y=2;
end

Extremely strange for loop behavior in Matlab

When attempting to write a for loop to increment from 1 to the end of an array, Matlab throws an error saying that I attempted to access the 0th array element, which doesn't exist. Here's the snippet in question:
function [adjMatNew] = delete(obj, adjMat)
[~, n] = size(adjMat);
adjMatNew = adjMat;
for i = 1:n
if adjMat(obj.number, i) ~= 0
adjList(i) = i
end
end
for j = 1:numel(adjList)
for k = 1:numel(adjList)
if j ~= k
adjMatNew(adjList(k), adjList(j)) = 1;
end
end
end
adjMatNew(obj.number, :) = 0;
adjMatNew(:, obj.number) = 0;
end
I can't think of any possible reason why, in the for loops above, the loop would start at 0. Changing the beginning increment variable from 1 to 2 fixed the issue and the function worked as intended, but it doesn't seem like the right fix. Does anybody have an explanation for this?
Without any help or comments, it's not very clear what you're actually attempting to do; however, in the line
adjMatNew(adjList(k), adjList(j)) = 1;
you implicitly assume that adjList is never zero. Since that is apparently the case, you get the error.
As suggested in other comments/answers, the issue is where you construct adjList.
for i = 1:n
if adjMat(obj.number, i) ~= 0
adjList(i) = i
end
end
Let's consider what happens in three different situations where n = 3:
1) If all of adjMat(obj.number, 1:3) are ~=0, each loop
adjList(1) = 1;
adjList(2) = 2;
adjList(3) = 3;
output: adjList = [1,2,3];
This case shouldn't throw an error.
2) If adjMat(obj.number, 3) is zero:
adjList(1) = 1;
adjList(2) = 2;
% adjList(3) not set
output: adjList = [1,2];
No error here, either.
3) If adjMat(obj.number, 2) is zero:
adjList(1) = 1;
% adjList(2) not set
adjList(3) = 3;
Since adjList(2) is not set, when calling adjList(3) = 3;, MATLAB needs there to be some value for adjList(2). By default, this is handled by filling with zeros to make the matrix the right size:
output: adjList = [1 0 3];
This causes the error.
As suggested in the comments by Notlikethat, adjList = find(adjMat(obj.number,:)) would be good way of replacing this loop. In this case, it only returns the positions of the non zero elements, so in the third case above, the output would be adjList = [1 3].