How does this prime number generation method work? - matlab

I want to figure out what the background of this code is, specifically, the reason of the commands written. I understand everything until the first line of the for loop, but then I got lost with the second line:
N= input('Enter your number: ');
primes = 2:N;
p=2;
while (p <= N)
for i = 2*p:p:N
primes(i - 1) = 0;
end;
p = p + 1;
end
primes = primes(primes > 0)
Can someone help me to understand this code please?

The code implements the Sieve of Eratosthenes to find the primes numbers.
It generated the array primes which contains the integer numbers from 2 to N
primes = 2:N
The while loop iterates across the integer values
while (p <= N)
At each iteration of the while loop in the for loop, the multiples of the current value of p are generated within the definition of the set of values of the loop index variable i
2*p:p:N
at each iteration of the for loop the element of the primes array in the position i is set to 0
At the end of the for loop, all the multiples of the current value of p are then set to 0
primes(i - 1) = 0;
The process is then repeated for all the integers values between 2 and N by the while loop.
At the end of the while loop the array primes will contains the prime numbers between 2 and N.
primes = primes(primes > 0)
This instruction finds the numbers different from 0 in the array primes and re-defines the array itself by assigning to it all all the numbers different from 0 or, that is the same. it removes from the array primes all of the 0s.
By definition the multiple of a given number is not a prime number.
Hope this helps.

Related

Find all numbers which are equal to the sum of the factorial of their digits

How can Find all numbers (e.g. 145= 1! + 4! + 5! = 1 + 24 + 120 = 145.)
which are equal to the sum of the factorial of their digits, by MATLAB?
I want to chop off digits, add the factorial of the digits together and compare it with the original number. If factorial summation be equal to original number, this numbers is on of the solution and must be keep. I can't code my idea, How can I code it? Is this true?
Thanks
The main reason that I post this answer is that I can't leave the use of eval in the previous answer without a decent alternative
Here is a small function to check this for any given (integer) n:
isFact = #(n) n==sum(factorial(int2str(n)-'0'));
Explanation:
int2str(n)-'0': "chop off digits"
sum(factorial(...)): "add the factorial of the digits together"
n==...: "compare it with the original number"
You can now plug it in a loop to find all the numbers between 1 to maxInt:
maxInt = 100000; % just for the example
solution = false(1,maxInt); % preallocating memory
for k = 1:maxInt
solution(k) = isFact(k);
end
find(solution) % find all the TRUE indices
The result:
ans =
1 2 145 40585
The loop above was written to be simple. If you look for further efficiency and flexibility (like not checking all the numbers between 1 to maxInt and checking array in any shape), you can change it to:
% generating a set of random numbers with no repetitions:
Vec2Check = unique(randi(1000,1,1000)); % you can change that to any array
for k = 1:numel(Vec2Check)
if isFact(Vec2Check(k))
Vec2Check(k) = Vec2Check(k)+0.1;
end
end
solution = Vec2Check(Vec2Check>round(Vec2Check))-0.1
The addition of 0.1 serves as a 'flag' that marks the numbers that isFact returns true for them. We then extract them by comparing the vector to it's rounded vertsion.
You can even go with a one-line solution:
solution = nonzeros(arrayfun(#(n) n.*(n==sum(factorial(int2str(n)-'0'))),Vec2Check))
The following snippet finds the numbers up to 1000 satisfying this condition.
numbers = [];
for i=1:1000
number_char = int2str(i);
sum = 0;
for j=1:length(number_char)
sum = sum+ factorial(eval(number_char(j)));
end
if (sum == i)
numbers(end+1) = i;
end
end
disp(numbers)
This should yield:
1 2 145
Note that if (log10(n)+1)*9! is less than n, then there is no number satisfying the condition larger than n.

MATLAB: copy zero-entries in array

I got a large vector vec of size n x 1 (with n a huge number). All values in vec are 0 or 1. The vector consists out of blocks of size m and in each block, only one of these two values shall be included.
So as to ensure this condition, I loop over each start element within an block and copy this value into all the entries of the respective block:
for i = 1:m:n
if vec(i) == 1
vec(i:i+m-1) = 1;
else
vec(i:i+m-1) = 0;
end
end
How can I achieve this without loosing a loop so as to better use MATLABs vectorization parallelization? Thanks in advance
You can use repelem:
vec = repelem(vec(1:m:n), m);

Matlab recursion. Sum off all odd numbers in a vector

I am trying to implement a recursive function to add the odd numbers in a vector v.
So far this is my attempt
function result = sumOdd(v)
%sum of odd numbers in a vector v
%sumOdd(v)
n = 1;
odds = [];
if length(v) > 0
if mod(v(n),2) == 1
odds(n) = v(n);
v(n) = [];
n = n + 1;
sumOdd(v)
elseif mod(v(n),2) == 0
v(n) = [];
n = n + 1;
sumOdd(v)
end
else
disp(sum(odds))
end
end
This does not work and returns a value of zero. I am new to programming and recursion and would like to know what I'm doing wrong.
Thank you.
There is a better way to solve this in MATLAB:
function result=summOdd(v)
odd_numbers=v(mod(v,2)); % Use logical indexing to get all odd numbers
result=sum(odd_numbers); % Summ all numbers.
end
To give a recursive solution:
When implementing a recursive function, there is a pattern you should always follow. First start with the trivial case, where the recursion stops. In this case, the sum of an empty list is 0:
function result = sumOdd(v)
%sum of odd numbers in a vector v
%sumOdd(v)
if length(v) == 0
result=0;
else
%TBD
end
end
I always start this way to avoid infinite recursions when trying my code. Where the %TBD is placed you have to put your actual recursion. In this case your idea was to process the first element and put all remaining into the recursion. First write a variable s which contains 0 if the first element is even and the first element itself when it is odd. This way you can calculate the result using result=s+sumOdd(v)
function result = sumOdd(v)
%sum of odd numbers in a vector v
%sumOdd(v)
if length(v) == 0
result=0;
else
if mod(v(1),2) == 1
s=v(1);
else
s=0;
end
v(1) = [];
result=s+sumOdd(v);
end
end
Now having your code finished, read the yellow warning the editor gives to you, it tells you to replace length(v) == 0 with isempty(v).
Instead of keeping 'n', you can always delete the first element of v. Also, you need to pass 'odds' as an argument, as you're initializing it as an empty array at each time you call the function (hence the zero output).
The following example seems to do the job:
function result = sumOdd(v,odds)
%sum of odd numbers in a vector v
%sumOdd(v)
if ~isempty(v)
if mod(v(1),2) == 1
odds = [odds;v(1)];
v(1) = [];
sumOdd(v,odds)
elseif mod(v(1),2) == 0
v(1) = [];
sumOdd(v,odds)
end
else
disp(sum(odds))
end
end

Find the number of pairs whose sum is divisible by k?

Given a value of k. Such that k<=100000
We have to print the number of pairs such that sum of elements of each pair is divisible by k.
under the following condition first element should be smaller than second, and both element should be less than 109.
I've found a solution, let a and b numbers such that (a+b)%k=0 then we have to find that pairs (a,b), where a<b, so let's count how many pairs (a,b) satisfy the condition that a+b=k, for example if k=3 0+3=3, 1+2=3, 2+1=3, 3+0=3 there are 4 pairs but only 2 pairs which is (K+1)/2 (integer division) so similar for find the pairs (a,b) which sum is 2k, 3k,.. nk, and the solution will be (k+1)/2 + (2k+1)/2 + (3k+1)/2 + ... + (nk+1)/2, and that is equal to (k*n*(n+1)/2 + n)/2 with time complexity O(1), take care in the case if n*k=2*10^9, because a can't be more than 10^9 for the given constraint.
Solution in O(N) time and O(N) space using hash map.
The concept is as follows:
If (a+b)%k=0 where
a=k*SOME_CONSTANT_1+REMAINDER_1
b=k*SOME_CONSTANT_2+REMAINDER_2
then (REMAINDER_1 +REMAINDER_2 )%k will surely be 0
so for an array (4,2,3,31,14,16,8) and k =5 if you have some information like below , you can figure out which all pairs sum %k =0
Note that, Bottom most row consist of all the remainders from 0 to k-1 and all the numbers corresponding to it.
Now all you need to do is move both the pointer towards each other until they meet. If both the pointers locations have number associated with it their sum%k will be 0
To solve it, you can keep track of all the remainder you have seen so far by using hash table
create a hash map Map<Integer, List>.
Pre-populate its keys with 0 to k-1;
iterate over array and put remainder of each number in the map with Key = remainder and put the actual number in the list,
Iterate over the key set using two pointers moving each other. And sum += listSizeAsPointedByPointer1 * listSizeAsPointedByPointer2
One way is brute force:
int numPairs = 0;
for (i = 0; i < 10e9; i++)
{
for (j = i+1; j < 10e9; j++)
{
int sum = i + j;
if (sum % k == 0) numPairs++;
}
}
return numPairs;
I'll leave it up to you to optimize this for performance. I can think of at least one way to significantly speed this up.
Some psuedo-code to get you started. It uses the brute-force technique you say you tried, but maybe something was wrong in your code?
max = 1000000000
numberPairs = 0
for i = 1 to max - 2 do
for j = i + 1 to max - 1 do
if (i + j) mod k = 0 then
numberPairs = numberPairs + 1
end if
end do
end do

MatLab assigning only the first two variables in

I am trying to write a MatLab function to compute Fibonacci numbers. below is what I have but it comes up with an error about F(0).
??? Attempted to access F(0); index must be a positive integer or logical.
Error in ==> fibonacci at 11
F(0) = 0;
How do I tell matlab that the first two values in the array are 0 and 1??
function F = fibonacci( n )
%A fibonacci sequence is where the next term in the series is given by the
%sum of the pervious two terms
%Only valid if n is greater than or equal to 2
if n >= 2 ;
%Make an array with n terms
F = zeros (1,n);
%run a for loop from 2 to n
for i = 2:n;
F(0) = 0;
F(1) = 1;
F(i) = F(i-1) + F(i-2)
end
end
end
Your formatting is a bit off, but it seems like you are assigning a value to the zero-index of an array. As far as I know MatLab uses 1 as the index of the first item in an array.
If you change your if n>=2 to if >=3 and set the 1 and 2 index items instead of the 0 and 1 items you should be well on your way.
See also Is zero based indexing available in MATLAB
MATLAB uses 1-based indexing, which means you should rewrite indices to reflect this shift, by replacing your n variables with n+1. This starts the fibonacci at 0, but indexed to 1, 1 at 2, 1 at 3, 2 at 4, 3 at 5, and so on to your "n"th term, now be indexed at n+1.