I have this number x and i wanted to find all numbers which are relatively prime to it.
my code so far:
For i = 1 To x-1
if [number n is relatively prime to x] Then
ListBox1.Items.Add(x)
End If
Next
Thanks in advance
Two numbers are relatively prime if their greatest common divisor is 1. VB doesn't have the GCD function built-in, but the algorithm is simple enough (and about 2300 years old!):
function gcd(m, n)
while n > 0
m, n = n, m%n
return m
Note that m and n are assigned simultaneously. I'll leave it to you to complete the VB implementation. You might be interested in googling for the totient of a number and the list of its totatives, which is what you are calculating.
Assuming you want only numbers that are smaller than x, which are coprime with it - you could also take a generative approach, running a special kind of a sieve. When the multiples of each prime are generated, you'd see if that sequence "hits" your upper limit x or misses it, and mark all the numbers in it as non-coprimes if it does hit x.
Or in "pseudocode" (with Haskell syntax :) ),
coprimes n = go( [1..n-1], [2..n-1]) where
go( xs, [] ) = xs -- ' no more numbers to sieve - return xs
go( xs, p:ks ) = -- ' p is first in candidates, ks is the rest
let ms = [p, 2*p .. n-1] -- ' p's multiples
in
go( if ( (mod n p) == 0 ) -- ' is n a multiple of p ?
then (xs\\ms) -- ' yes: remove p's multiples
else xs, -- ' no: possible coprimes
ks\\ms ) -- ' candidates to sieve
Haskell's set difference \\ is very inefficient with unordered list representation of sets, but you would naturally encode this efficiently, on top of mutable arrays, in VB.
Related
Here are two 64-bit (signed) integers
p = 13776308150928489016
q = 16488138731131959619
and their product
n = 112488352363349635896748360565917156710
The bit-length of the product is floor ((log2 n) + 1) or 127.
Now here are another two 64-bit integers
p = 13275629912622491628
q = 16290498985329101221
and their product
n = 179030914337714357408535416678431567970
but this time the bit length is floor ((log2 n) + 1) or 128.
The reason is that there's a leading zero in the first integer, which makes the space needed to represent the integer in memory one bit smaller.
The problem this causes is that I can't determine the bit length of the keys accurately. For example, here are is a very short RSA key pair:
Public key : 7, 8371846783263706079
Private key : 2989945277626202443, 8371846783263706079
The modulus (8371846783263706079) is 63 bits, which the number I'm after is 64. The overcome this issue I have considered the following solutions:
Round up to the nearest 2^n
Store the key size in bits along with the key
Add some kind of padding to ensure all integers take up the same space (not sure how this would work in practice)
Which one is the correct solution?
As #r3mainer notes, the math needed here -- inequalities -- is not exotic. As to what tutorials say, well, they're just tutorials, they're trying to simplify as much as possible so they leave out some details.
What you are observing is the following:
you want two primes, p and q, to have the same bit length k and their product N to have a bit length of 2k.
By the definition of what it means to have a bit length of k, we have the following inequality:
1) 2(k-1) <= p, q < 2k.
However, when we multiply p and q we discover a problem:
2) 2(2k - 2) <= N < 22k
This means that N=p*q may end up having bit length of 2k-1 or 2k, but we don't want 2k-1.
In your example k=64.
To fix it, we need to tighten up the lower bound on p and q to the following:
3) sqrt(2(2k-1)) <= p, q < 2k.
Bearing in mind that all results are integers, we apply the ceiling function and get finally
4) ceiling(sqrt(2(2k-1))) <= p, q < 2k.
For k=64 this works out to:
13043817825332782213 <= p, q < 264
An even simpler formulation is make the bounds dynamic, as in the following:
first find p, of any size. Then we want
2(2k - 1) <= p*q < 22k, so
5) (2(2k - 1))/ p <= q < (22k)/p will do the trick.
For RSA, we actually do want both primes to be sufficiently large and entropic, and yet not be too close to each other. We can do that by choosing p to have length k-1 or k-2 and applying 5).
I have an integer, N.
I denote f[i] = number of appearances of the digit i in N.
Now, I have the following algorithm.
FOR i = 0 TO 9
FOR j = 1 TO f[i]
k = k*10 + i;
My teacher said this is O(N). It seems to me more like a O(logN) algorithm.
Am I missing something?
I think that you and your teacher are saying the same thing but it gets confused because the integer you are using is named N but it is also common to refer to an algorithm that is linear in the size of its input as O(N). N is getting overloaded as the specific name and the generic figure of speech.
Suppose we say instead that your number is Z and its digits are counted in the array d and then their frequencies are in f. For example, we could have:
Z = 12321
d = [1,2,3,2,1]
f = [0,2,2,1,0,0,0,0,0,0]
Then the cost of going through all the digits in d and computing the count for each will be O( size(d) ) = O( log (Z) ). This is basically what your second loop is doing in reverse, it's executing one time for each occurence of each digits. So you are right that there is something logarithmic going on here -- the number of digits of Z is logarithmic in the size of Z. But your teacher is also right that there is something linear going on here -- counting those digits is linear in the number of digits.
The time complexity of an algorithm is generally measured as a function of the input size. Your algorithm doesn't take N as an input; the input seems to be the array f. There is another variable named k which your code doesn't declare, but I assume that's an oversight and you meant to initialise e.g. k = 0 before the first loop, so that k is not an input to the algorithm.
The outer loop runs 10 times, and the inner loop runs f[i] times for each i. Therefore the total number of iterations of the inner loop equals the sum of the numbers in the array f. So the complexity could be written as O(sum(f)) or O(Σf) where Σ is the mathematical symbol for summation.
Since you defined that N is an integer which f counts the digits of, it is in fact possible to prove that O(Σf) is the same thing as O(log N), so long as N must be a positive integer. This is because Σf equals how many digits the number N has, which is approximately (log N) / (log 10). So by your definition of N, you are correct.
My guess is that your teacher disagrees with you because they think N means something else. If your teacher defines N = Σf then the complexity would be O(N). Or perhaps your teacher made a genuine mistake; that is not impossible. But the first thing to do is make sure you agree on the meaning of N.
I find your explanation a bit confusing, but lets assume N = 9075936782959 is an integer. Then O(N) doesn't really make sense. O(length of N) makes more sense. I'll use n for the length of N.
Then f(i) = iterate over each number in N and sum to find how many times i is in N, that makes O(f(i)) = n (it's linear). I'm assuming f(i) is a function, not an array.
Your algorithm loops at most:
10 times (first loop)
0 to n times, but the total is n (the sum of f(i) for all digits must be n)
It's tempting to say that algorithm is then O(algo) = 10 + n*f(i) = n^2 (removing the constant), but f(i) is only calculated 10 times, each time the second loops is entered, so O(algo) = 10 + n + 10*f(i) = 10 + 11n = n. If f(i) is an array, it's constant time.
I'm sure I didn't see the problem the same way as you. I'm still a little confused about the definition in your question. How did you come up with log(n)?
I have some difficulties in understanding the time complexity analysis for one solution for the Happy Number Question from Leet code, for my doubts on complexity analysis, I marked them in bold and really appreciate your advice
Here is the question:
Link: https://leetcode.com/problems/happy-number/
Question:
Write an algorithm to determine if a number is "happy".
A happy number is a number defined by the following process: Starting with any positive integer, replace the number by the sum of the squares of its digits, and repeat the process until the number equals 1 (where it will stay), or it loops endlessly in a cycle which does not include 1. Those numbers for which this process ends in 1 are happy numbers.
Example:
Input: 19
Output: true
Explanation:
1^2(square of 1) + 9^2 = 82
8^2 + 2^2 = 68
6^2 + 8^2 = 100
1^2 + 0^2 + 0^2 = 1
Here is the code:
class Solution(object):
def isHappy(self, n):
#getnext function will compute the sum of square of each digit of n
def getnext(n):
totalsum = 0
while n>0:
n,v = divmod(n,10)
totalsum+=v**2
return totalsum
#we declare seen as a set to track the number we already visited
seen = set()
#we stop checking if: either the number reaches one or the number was visited #already(ex.a cycle)
while n!=1 and (n not in seen):
seen.add(n)
n = getnext(n)
return n==1
Note: feel free to let me know if I need to explain how the code works
Time Complexity Analysis:
Time complexity : O(243 * 3 + logN + loglogN + log loglog N)...=O(logN).
Finding the next value for a given number has a cost of O(log n)because we are processing each digit in the number, and the number of digits in a number is given by logN.
My doubt: why the number of digits in a number is given by logN? what is N here? the value of a specific number or something else?
To work out the total time complexity, we'll need to think carefully about how many numbers are in the chain, and how big they are.
We determined above that once a number is below 243, it is impossible for it to go back up above 243.Therefore, based on our very shallow analysis we know for sure that once a number is below 243, it is impossible for it to take more than another 243 steps to terminate.
Each of these numbers has at most 3 digits. With a little more analysis, we could replace the 243 with the length of the longest number chain below 243, however because the constant doesn't matter anyway, we won't worry about it.
My doubt: I think the above paragraph is related to the time complexity component of 243*3, but I cannot understand why we multiply 243 by 3
For an n above 243, we need to consider the cost of each number in the chain that is above 243. With a little math, we can show that in the worst case, these costs will be O(log n) + O(log log n) + O(log log log N)... Luckily for us, the O(logN) is the dominating part, and the others are all tiny in comparison (collectively, they add up to less than logN), so we can ignore them. My doubt: what is the reasoning behind O(log log n) O(log log log N) for an n above 243?
Well, my guess for the first doubt is that the number of digits of a base 10 number is given by it's value (N) taken to the logarithm at base 10, rounded down. So for example, 1023 would have floor(log10(1023)) digits, which is 3. So yes, the N is the value of the number. the log in time complexity indicates a logarithm, not specifically that of base 2 or base e.
As for the second doubt, it probably has to do with the work required to reduce a number to below 243, but I am not sure. I'll edit this answer once I work that bit out.
Let's say N has M digits. Than getnext(N) <= 81*M. The equality happens when N only has 9's.
When N < 1000, i.e. at most 3 digits, getnext(N) <= 3*81 = 243. Now, you will have to call getnext(.) at most O(243) times to figure out if N is indeed happy.
If M > 3, number of digits of getnext(N) must be less than M. Try getnext(9999), getnext(99999), and so on [1].
Notes:
[1] Adding a digit to N can make it at most 10*N + 9, i.e. adding a 9 at the end. But the number of digits increases to M+1 only. It's a logarithmic relationship between N and M. Hence, the same relationship holds between N and 81*M.
Using the Leetcode solution
class Solution {
private int getNext(int n) {
int totalSum = 0;
while (n > 0) {
int d = n % 10;
n = n / 10;
totalSum += d * d;
}
return totalSum;
}
public boolean isHappy(int n) {
Set<Integer> seen = new HashSet<>();
while (n != 1 && !seen.contains(n)) {
seen.add(n);
n = getNext(n);
}
return n == 1;
}
}
}
O(243*3) for n < 243
3 is the max number of digits in n
e.g. For n = 243
getNext() will take a maximum of 3 iterations because there are 3 digits for us to loop over.
isHappy() can take a maximum of 243 iterations to find a cycle or terminate, because we can store a max of 243 numbers in our hash set.
O(log n) + O(log log n) + O(log log log N)... for n > 243
1st iteration + 2nd iteration + 3rd iteration ...
getNext() will be called a maximum of O(log n) times. Because log10 n is the number of digits.
isHappy() will be called a maximum of 9^2 per digit. This is the max we can store in the hash set before we find a cycle or terminate.
First Iteration
9^2 * number of digits
O(81*(log n)) drop the constant
O(log n)
+
Second Iteration
O(log (81*(log n))) drop the constant
O(log log n)
+
Third Iteration
O(log log log N)
+
ect ...
What is the time Complexity for below code:
1)
function(values,xlist,ylist):
sum =0
n=0
for r from 0 to xlist:
for c from 0 to ylist:
sum+= values[r][c]
n+1
return sum/n
2)
function PrintCharacters():
characters= {"a","b","c","d"}
foreach character in characters
print(character)
According to me the 1st code has O(xlist*ylist) complexity and 2nd code has O(n).
Is this right?
Big O notation to describe the asymptotic behavior of functions. Basically, it tells you how fast a function grows or declines
For example, when analyzing some algorithm, one might find that the time (or the number of steps) it takes to complete a problem of size n is given by
T(n) = 4 n^2 - 2 n + 2
If we ignore constants (which makes sense because those depend on the particular hardware the program is run on) and slower growing terms, we could say "T(n)" grows at the order of n^2 " and write:T(n) = O(n^2)
For the formal definition, suppose f(x) and g(x) are two functions defined on some subset of the real numbers. We write
f(x) = O(g(x))
(or f(x) = O(g(x)) for x -> infinity to be more precise) if and only if there exist constants N and C such that
|f(x)| <= C|g(x)| for all x>N
Intuitively, this means that f does not grow faster than g
If a is some real number, we write
f(x) = O(g(x)) for x->a
if and only if there exist constants d > 0 and C such that
|f(x)| <= C|g(x)| for all x with |x-a| < d
So for your case it would be
O(n) as |f(x)| > C|g(x)|
Reference from http://web.mit.edu/16.070/www/lecture/big_o.pdf
for r from 0 to xlist: // --> n time
for c from 0 to ylist: // n time
sum+= values[r][c]
n+1
}
function PrintCharacters():
characters= {"a","b","c","d"}
foreach character in characters --> # This loop will run as many time as there are characters suppose n characters than it will run time so O(n)
print(character)
Big O Notation gives an assumption when value is very big outer loop
will run n times and inner loop is running n times
Assume n -> 100 than total n^2 10000 run times
Let's say we have a set : {1, 2, ..., n}.
How many subsets of order R exist S = {a_i1, a_i2, ...a_iR} that sum up to a certain number S?. What is the recursion for this problem?
Just define method to solve original problem. Parameters it receives are:
max number to use (n),
subset size (R),
subset sum (S),
and returns number of combinations.
To implement this method, first we have to check is it possible to make this request. It is not possible to fulfill task if:
subset size is larger than number of possible elements (R > n)
maximal possible sum is smaller than S. n + (n-1) + ... + (n-R+1) < S => R*((n-R) + (R+1)/2) < S
After that it is enough to try all possibilities for larger element that will go in subset. In python style it should be implemented like:
def combinations(n, R, S):
if R > n or R*((n-R) + (R+1)/2) < S:
return 0
c = 0
for i in xrange(R, n+1): # try i as maximal element in subset. It can go from R to n
# recursion n is i-1, since i is already used
# recursion R is R-1, since we put i in a set
# recursion S is S-i, since i is added to a set and we are looking for sum without it
c += combinations(i-1, R-1, S-i)
return c