MATLAB - How do I find the first integer of an infinite set that satisfies this condition? - matlab

I want to find the smallest integer P, such that the number of primes in the set {1,2,..., P} is less than P/6.
I think have the answer via (long) trial and error but would like to know how to verify this through MATLAB.

You can use isprime to check if any value in an array is a prime number. If we want to check all integers up until the integer N we can do
% You can change this to the maximum number that you'd like to consider for P
N = 2000;
possible_P_values = 2:N; % We omit 1 here since it's not a prime number
primes = isprime(possible_P_values);
To determine how many primes have occured up to a given integer N we can use cumsum of this logical matrix (the cumulative sum)
nPrimes_less_than_or_equal_to_P = cumsum(primes);
Then we can divide possible_P_values by 6 and check where the number of primes up to a certain point is less than that number.
is_less_than_P_over_6 = nPrimes_less_than_or_equal_to_P < (possible_P_values ./ 6);
Then we can identify the first occurance with find
possible_P_values(find(is_less_than_P_over_6, 1, 'first'))
% 1081

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.

Mean value of each column of a matrix

I have a 64 X 64 matrix that I need to find the column-wise mean values for.
However, instead of dividing by the total number of elements in each column (i.e. 64), I need to divide by the total number of non-zeros in the matrix.
I managed to get it to work for a single column as shown below. For reference, the function that generates my matrix is titled fmu2(i,j).
q = 0;
for i = 1:64
if fmu2(i,1) ~= 0;
q = q + 1;
end
end
for i = 1:64
mv = (1/q).*sum(fmu2(i,1));
end
This works for generating the "mean" value of the first column. However, I'm having trouble looping this procedure so that I will get the mean for each column. I tried doing a nested for loop, but it just calculated the mean for the entire 64 X 64 matrix instead of one column at a time. Here's what I tried:
q = 0;
for i = 1:64
for j = 1:64
if fmu2(i,j) ~= 0;
q = q +1;
end
end
end
for i = 1:64
for j = 1:64
mv = (1/q).*sum(fmu2(i,j));
end
end
Like I said, this just gave me one value for the entire matrix instead of 64 individual "means" for each column. Any help would be appreciated.
For one thing, do not call the function that generates your matrix in each iteration of a loop. This is extremely inefficient and will cause major problems if your function is complex enough to have side effects. Store the return value in a variable once, and refer to that variable from then on.
Secondly, you do not need any loops here at all. The total number of nonzeros is given by the nnz function (short for number of non-zeros). The sum function accepts an optional dimension argument, so you can just tell it to sum along the columns instead of along the rows or the whole matrix.
m = fmu2(i,1)
averages = sum(m, 1) / nnz(m)
averages will be a 64-element array with an average for each column, since sum(m, 1) is a 64 element sum along each column and nnz(m) is a scalar.
One of the great things about MATLAB is that it provides vectorized implementations of just about everything. If you do it right, you should almost never have to use an explicit loop to do any mathematical operations at all.
If you want the column-wise mean of non-zero elements you can do the following
m = randi([0,5], 5, 5); % some data
avg = sum(m,1) ./ sum(m~=0,1);
This is a column-wise sum of values, divided by the column-wise number of elements not equal to 0. The result is a row vector where each element is the average of the corresponding column in m.
Note this is very flexible, you could use any condition in place of ~=0.

How to check my matrix if its divisible by 12

im new to matlab and i've run into a slight problem. I want to check my matrix that generated random number if they are divisible by 12. Then i want to list number of digit divisible by 12 and the total sum of those.
clc
clear
format compact
a=4
b=0
N=50+a
R=randi([100+a,159+b], 1, N) % generate random no. from 100+a to 159 on a matrix 1xN
s1=0
N1=0
for i = 1
for j= 1:N
if rem(R,12)==0
N1=N1+1;
s1=s1+R(i,j);
else
N1=N1+0;
s1=s1+0;
end
end
end
numberof1=N1
sum1=s1
Your code isn't working because your are calling rem(R, 12) (remainder of all elements) as opposed to the remainder of the specific element (rem(R(i,j), 12)).
The better approach though would be to remove the for loop and generate a logical matrix the size of R that is true when that number is divisible by 12 and false otherwise by passing the entire matrix to rem.
is_divisible_by_12 = rem(R, 12) == 0;
Then we can use this to compute the sum of these by using this logical array as an index into R
subset = R(is_divisible_by_12);
number = numel(subset);
s1 = sum(subset);

Calculating the product of all the odd numbers

So I am trying to create a script that calculates the product of all the odd numbers from 1 to 1000 (using MATLAB). The program runs but the product is not correct:
%Program is meant to calculate the product of all the odd numbers from 1 to 1000
% declare variable ‘product’ as zero
product = 0.;
% initialize counter, ‘n’, to 1000
n = 1000;
for i = 1:2:n
product = product + i;
end
fprintf('The product of all the odd numbers from 1 to %d is %d\n', n, product)
So I'm not really sure how to go about this and am looking for some guidance. Thanks!
Solution
Currently, your script is set to add all of the odd numbers from 1 to 1000.
To perform the product, you just need to change the starting value of product to 1 and multiply within the loop:
product = 1;
for i = 1:2:1000
product = product * i;
end
However, it is faster to create a vector and have the built-in prod function perform the multiplication:
product = prod(1:2:1000);
Problem
MATLAB does not by default have enough memory in the default 64-bit numbers to compute the exact value of this product.
The number is too large since this is essentially a factorial.
You'll find that MATLAB returns Inf for the 500 numbers you're multiplying, and it is only finite for up to 150 elements.
In fact, using floating point arithmetic, the number is only accurate up to 15 digits for the first 17 digits using floats (integers saturate at that level as well).
Using Mathematica (which can perform arbitrary digit arithmetic out-of-the-box since I'm feeling lazy), I can see that the answer needs at least 1300 digits of precision, which we can have MATLAB do through the Symbolic Toolbox's vpa function:
digits(1300);
p = vpa(1);
pint = vpa(1);
for k = 2:N
pint = pint*p(k);
end
disp(pint);
>> StackOverflow
100748329763750854004038917392303538250323418583550415705013777513334847930864905026212149922688916514224446856302103818809813965739969905602683824057028542369814437703275217182106137628427025253936696857063927677887236450311036887007989218384076420973974651860279864376153012567675767840733574225799002463604490891982796305162134708837541147007332276627034016790073315219533088052639255340728943149219519187498959529434982654113006616219355830114439411562650611374970334868978510289340267833632215930432706056111069583472778227977585526504938921664232801595705593340414168289146933191250605578218896799783237156997993612173843567447982392426109444012350386990916069363415575527636429080027392875413821124412782341957015410685185402984322002697631153866494712956244870206835064084512590679022924697003630949759950902438767963278695296882620493296103779237046934780464541286585179975172680371269700518965123152181467825566303777704391998857792627009043170482928030252033752456172692668989206857862233381387134495504231267039972111966329704875185659372569246229419619030694680808504265784672316785572965414328005856656944666840982779185954031239345256896720409853053597049715408663604581472840976596002762935980048845023622727663267632821809277089697420848324327380396425724029541015625.0

Matrix dimension must agree error in matlab?

I have adapted some existing code for my program but I am coming across an error that I do not know the cause for. I have data with N observations where my goal is to break up the data into increasing smaller subsamples and do calculations on each of the subsamples. To determine the how the subsample size will change, the program finds divisors of N and stores it into an array OptN.
dmin = 2;
% Find OptN such that it has the largest number of
% divisors among all natural numbers in the interval [0.99*N,N]
N = length(x);
N0 = floor(0.99*N);
dv = zeros(N-N0+1,1);
for i = N0:N,
dv(i-N0+1) = length(divisors(i,dmin));
end
OptN = N0 + find(max(dv)==dv) - 1;
% Use the first OptN values of x for further analysis
x = x(1:OptN);
% Find the divisors >= dmin for OptN
d = divisors(OptN,dmin);
function d = divisors(n,n0)
% Find all divisors of the natural number N greater or equal to N0
i = n0:floor(n/2);
d = find((n./i)==floor(n./i))' + n0 - 1; % Problem line
In function divisors is where the problem occurs. I have 'Error using ./ Matrix dimensions must agree.' However, this worked with input data of length 60, but when I try data of length 1058 it gives me the above error.
I think that with large dataset it's possible that find(max(dv)==dv) will returns multiple numbers. So OptN will become a vector, not a scalar.
Then the length of i (BTW not a good name for variable in MATLAB, it's also a complex number i) will be unpredictable and probably different from n causing the dimension error in the next statement.
You can try find(max(dv)==dv,1) instead to get only the first match. Or add a loop.