Calculation for Primes using square roots, and algorithm build inquiry - c++

Below is a calculation for primes. I was trying to deconstruct it to get a better understanding of loops. Also, I would like to tweak this function to find primes by comparing a number to its square root instead of this way:
(assume proper declarations are made before int main)
// Determines whether the number is prime
bool isPrime (long n)
{
int a;
if (n == 1)
{
return false;
}
for (a = 2; a <= (n / 2); a++)
{
if ((n % a) == 0)
{
return false;
}
}
return true;
}
However, observing this loop, I have a question to see if I am observing this function correctly to start with. From what I see, it looks like int a; is the counter and it is starting at 2 since 0 and 1 are not prime. n should be the formal variable. It states that for every number which is less than or equal to itself when divided by two, returns a true for bool if there is a remainder of more than zero. At the same time, if a number divides by two evenly (so no remainder) then it is not considered prime (the bool returns false). Does that sound about right? If not, please do let me know where I made a wrong turn. If I got it right, on to the second half of the program.
Now here, primeCount; is limited with primeCount (2, 50000); in main but The first function feeds into here:
// Counts and organizes the prime numbers using the isPrime function
long primeCount (long x, long y)
{
bool prime;
int b;
int c = 1000;
int counter = 0;
int totalSum = 0;
for (b = 1; b <= y; b++)
{
prime = isPrime (b);
if (prime == true)
{
counter++;
}
if (b == c)
{
cout << setw(10) << left << (b - 999) << setw(10) << left << b << setw(12) << counter << endl;
cout << fixed << showpoint << setprecision(2) << endl;
totalSum = totalSum + counter;
counter = 0;
c = c + 1000;
}
}
Now, I figure x and y are formal variables but I don't know what x is supposed to represent. Does it represent int c; ? The for loop in that function completely confused me. I don't understand it. Any light that can be shed on that would be appreciated.
As for the square root inquiry, would I need to use 3 nested for loops in order to get the primes?Like this:
for (a > m => b)
for (a==m => b==m)
for (a < m => b>m)
Would locating the primes this way be more or less complicated than the way illustrated here? I know this is a lot to tackle. IF you guys suggest that I break it into separate posts, I'll edit this one and post the second half in a different post. Thanks for the assist! Just a freshman C++ programmer trying to make heads and tails out of this stuff :)

The first function isPrime() does what it is supposed to. Returns true if a number is prime and returns false if it is not. The reason why the loop variable a runs only till n/2 is because any number n cannot have a factor that is greater than n/2 (apart from itself). EXAMPLES? 6 -- 1, 2, 3 and 6, 12 -- 1, 2, 3, 4, 6 and 12. The loop is just trying to see if a has any factors (numbers that divide it without leaving a remainder). If it does it is not a prime (return false) else it is (return true).
However I feel that primeCount() doesn't completely do what it is intended to.
From the definition of primeCount() I think it is meant to compute the total number of prime numbers from x to y (in your case 2 to 50000, since you mentioned main() calls primeCount(2, 50000)). However for it to do this the for loop must be changed to this
for (b = x; b <= y; b++)
The role of the variable c here is to keep a check for every thousandth value of the loop variable b.
Notice that on 1st run when b = 1000 i.e b == c the program prints the number of primes that it encountered until now (counter). After that the counter is reset to 0 and c is now 2000.Then, b goes on from 1001 to 2000 and the same thing repeats till b is 50000.
Overall, The idea is to print the number of primes that exist within each 1000 natural numbers from 2 to 50000.

for (a = 2; a <= (n / 2); a++)
{
if ((n % a) == 0)
{
return false;
}
}
This is the "for" loop you use. It checks the remainder of n when dividing by each "a", iterating from 2, up to n/(one half (integral division) of n). If ANY of these remainders is zero, then n is a composite, and there's no point continuing onward. We just return a false - the number is not prime.
It is safe to assume that if we have not found a divisor of n until (n/2), the number is a prime, so AFTER we try all possibile guesses for divisors, if we got that far, we return that the number IS prime.

Related

Given 3 positive integers, find max number of steps to reduce them to 0

I am solving this question from CodeForces:
We are given three values, r, g and b which represent number of Red, Green and Blue candies in three piles, respectively. Tanya can't eat two candies of the same color in a day i.e., each day she eats exactly two candies of different colors. Find the maximal number of days Tanya can eat candies.
I did it in a simple way as below:
int main() {
int t, r, g, b;
cin>>t;
while(t--) {
int counter=0;
cin >> r >> g >> b;
while(r && g) {
r--;
g--;
counter++;
}
while(g && b) {
g--;
b--;
counter++;
}
while(r && b) {
r--;
b--;
counter++;
}
cout<<counter<<"\n";
}
return 0;
}
However, it breaks on the inputs 7 4 10 and 8 2 8. My code returns 7 and 8 respectively, instead of 10 and 9 (I am unsure how 10 and 9 are the expected answers for the inputs). The editorial talks about sorting the input and checking if b <= r + g and returning (r+g+b)/2 if true and r+g otherwise. Suffice to say, I am unable to understand what the editorial says.
Could someone please point out why my logic is incorrect and what am I missing?
Thanks!
Even if your solution is corrected it may not pass all the tests on codeforces as its time complexity is proportional to values of your input numbers. But there exists a solution that has a constant running time regardless of the input numbers.
First, sort 3 input numbers. IF they are not sorted then on each iteration we would need to find maximum and minimum elements and then decrement them. If the numbers are sorted then we know right away where the largest and smallest numbers are and so we can decrement them immediately.
Now, after sorting let's consider possible cases for a,b,c: a<=b<=c:
0.if a is 0 (or a,b or a,b,c) then the number is obviously min(b,c).
1.For a, b, c: b = c, a > 0 it's always better to decrement a,b then a,c in turns as it yields to the maximum number of iterations. For instance, 2,3,3 -> 1,2,3 -> 0,2,2 -> 0,1,1 -> 0,0,0. If a = c and b = c then it' still true - 2,2,2 -> 1,1,2 -> 0,1,1 -> 0,0,0.
2.For a, b, c: a != b and b != c we should keep in mind case 1 that maximises the number of iterations. How to get there? Well, by decrementing c and a as long as either a becomes 0 (then case 1 isn't needed as we can already calculate the remaining steps as min(b, c - a)) or c becomes equal to b and then it's case 1. If we try to decrement any other pair of numbers then the numbers of iterations will decrease as b will be decreased for no good reason :). After this we can apply case 1.
3.This approach can be implemented in O(1) time complexity.
...
int main() {
int t;
std::cin >> t;
for (int i = 0; i < t; i++) {
std::vector<int32_t> array(3);
for (int32_t& value : array) {
std::cin >> value;
}
std::sort(array.begin(), array.end());
int32_t days = 0;
int32_t diff = array[2] - array[1];
days += (std::min(array[0], diff));
array[0] -= days;
array[2] -= days;
array[2] -= array[0] / 2;
days += (array[0] / 2);
array[1] -= array[0] / 2;
days += (array[0] / 2);
days += std::min(array[1], array[2]);
std::cout << days << std::endl;
}
return 0;
}
...
Because you need to find the optimal method for this problem.
For example, 1,1,10, the optimal way is to r & b, g & b. In your method, it is only 1 as the result.
Thus we need to sort the three values and always use the biggest number to reach the answer.

Accessing an uninitialized value, most probably in a vector

I am doing an exercise where I need to find a positive integers p and q which are factors of another natural number n.
Following the formula n=pq*q where p is a squarefree number.
However, for some instances of the program my compiler detects a memory error saying that I am accessing an uninitialized value.
The logic I tried is as follows. Firstly, I took the number that needs to be factored (name it n). Next I found all factors of the number n and placed them in a vector. After that, check if every element of that vector is squarefree. If true, put the element in another vector(a vector of squarefree factors of the number n). After that, go through every element of the vector of squarefree factors and solve the equation q=sqrt(n/p) where p is the squarefree factor from the vector. Additionally, I check the condition if(int(sqrt(n/p))==sqrt(n/p)) because the square root needs to be a positive integer.
#include <iostream>
#include <vector>
#include <cmath>
using namespace std;
// Function that checks if the number is squarefree
bool isSquareFree(int n)
{
if (n % 2 == 0)
n = n / 2;
if (n % 2 == 0)
return false;
for (int i = 3; i <= sqrt(n); i += 2)
{
if (n % i == 0)
{
n = n / i;
if (n % i == 0)
return false;
}
}
return true;
}
void Factorise_the_number(int n, int &p, int &q)
{
if (n <= 0)
return 0;
vector<int> factors(0); // vector of factors
vector<int> sqfree_factors(0); // vector of squarefree factors
int sqfree_number; // the number "p"
int squared; // is essentially the number "q"
for (int i = 1; i <= n / 2; i++)
{
if (n % i == 0)
factors.push_back(i); // takes all factors of the number "n"
}
for (int i = 0; i < factors.size(); i++)
{
if (isSquareFree(factors.at(i)))
sqfree_factors.push_back(factors.at(i));
} // checks if each factor is squarefree. if yes, put it in a separate vector
for (auto x : sqfree_factors)
{
if (int(sqrt(n / x)) == sqrt(n / x))
{ // if true, we found the numbers
squared = sqrt(n / x);
sqfree_number = x;
break;
}
}
p = sqfree_number;
q = squared;
}
int main()
{
int n, p = 0, q = 0;
cin >> n;
Factorise_the_number(n, p, q);
cout << p << " " << q;
return 0;
}
For example, my program works if I enter the number 99, but doesn't work if I enter 39. Can anyone give any insight?
Thanks!
As you said, for 39 it doesn't work. Have you checked what it's doing with 39? You should do it, as it is the best way to debug your program.
Let's have a look at it together. First it tries to find all the factors, and it finds 1, 3 and 13: this looks fine.
Then, it checks whether each of those numbers is squarefree, and they all are: this also looks correct.
Then, it checks whether any of the squarefree factors satisfy the equality you are looking for. None of them does (39 is 3 x 13, there's no way it can contain a squared factor). This means that if (int(sqrt(n / x)) == sqrt(n / x)) is never true, and that block is never run. What's the value of sqfree_number and squared at that point? It is never initialised. Using uninitialised values leads to "undefined behaviour", that is, your program can do anything. In this case, p and q end up containing random values.
How can you fix it? Consider this: if n doesn't satisfy your equation, that is, it can't be expressed as pq*q, what, exactly, should the program output? Would your output, as it is now, ever make sense? No. This means you have to modify your program so that it covers a case you hadn't considered.
A way is to add a bool found = false; just before your final for loop. When you find the factors, before breaking, set that variable to true. Then, outside the loop, check it: is it true? Then you can return the correct values. But if it's still false, it means the equality doesn't hold, and you can't return correct values. You have to find a way to signal this to the caller (which is your main function), so that it can print an appropriate message.
And how can you signal it? In general, you could change your Factorise_the_number (by the way, the name of functions should start with a lowercase letter; uppercase letters are usually used for classes) to return a bool. Or you could use a trick: return a special value for p and q that cannot be the result of the calculation. Like -1. Then, before printing, check: if the values are -1, it means the number can't be expressed as pq*q.

Checking whether "1" or "0" is at "x" position in powers of 10 sequence (1101001000...) C++

So I've got this problem to solve. Having a sequence of powers of 10 written one after another, the beginning would look like this: 1101001000... Check whether given number corresponds to "1" or "0" in this sequence.
First input: N number defining how many tests are there. Second input: N lines with a number to check. Output: N numbers that are either "1" or "0".
Example:
Input:
4
3
14
7
6
Output:
0 0 1 0
So I've got this:
#include <iostream>
using namespace std;
int main() {
int a, b;
cin >> a;
for (int k = 1; k <= a; k++){
cin >> b;
int flag = 0;
for (int s = 1; s <= b; s++){
if (((s * (s - 1)) / 2) + 1 == b){
flag = 1;
break;
}
}
if (flag == 1)
cout << "1" << endl;
else
cout << "0" << endl;
}
return 0;
}
and it should work, but the debugger/tester at my school says that time limit has been exceeded, either program takes too long or the program never ends and I'm clueless where's the error. Started programming a month ago so no fancy stuff please.
((s*(s-1))/2)+1 gives "1" places in the sequence.
You're solution is clever. Your idea is to jump over all 1's in the binary string by using a closed formula to get the position of the s-th 1 in the sequence. If the sequence has a 1 at b, you find that very quickly by iterating over s, since for some s, the conditition ((s * (s - 1)) / 2) + 1 == b becomes true. So far it is ok.
However, if the sequence has a 0 at b, that condition is never true. You never hit a 1, and you only check that in your condition. So if for one value of s, the formula is < b, and for the next it is > b, you jumped over b. But you continue the for-loop of s until s > b and that is way to much time to spend.
So in a nutshell, you need to check for > b. If this is the case, you know that the sequence has a 0 at b. Simply break; out of the loop in this case.
You can even improve that by inverting your formula to compute s directly from b. For this, solve the formula for s. That gives you s = 0.5*(sqrt(8*b-7)-1) (Note that the negative solution is irrelevant). This is a computation over the real numbers, so you are going to need floating point numbers for that, and the result is a floating point number, too.
If s turns out to be an integral number, you hit a 1, and 0 otherwise. But checking the result to be integral is error-prone (floating point arithmetic introduces some predictable but unavoidable rounding errors). So instead I'd recommend to use the forward formula (the one you already have) with the rounded-down and rounded-up results of this inverted formula. In other words, guess s using a floating point inverse formula, use this s to check two possible candidates for an integral s against your forward formula.
float guess_s = 0.5*(sqrt(8*b-7)-1);
int s1 = floor(guess_s); // rounded down
int s2 = s1 + 1; // rounded up
Then check s1 and s2 with your formula:
if ( ((s1 * (s1 - 1)) / 2) + 1 == b || ((s2 * (s2 - 1)) / 2) + 1 == b )
cout << "1" << endl;
else
cout << "0" << endl;

basic nestled loop calculate prime numbers between 1 - 239, inclusive

I am working on a program in which I must print out the number of primes, including 1 and 239, from 1 - 239 ( I know one and or two may not be prime numbers, but we will consider them as such for this program) It must be a pretty simple program because we have only gone over some basics. So far my code is as such, which seems like decent logical flow to me, but doesnt produce output.
#include <iostream>
using namespace std;
int main()
{
int x;
int n = 1;
int y = 1;
int i = 0;
while (n<=239)
{x = n % y;
if (x = 0)
i++;
if (y < n)
y++;
n++;
while (i == 2)
cout << n;
}
return 0;
}
The way I want this to work is to take n, as long as n is 239 or less, and preform modulus division with every number from 1 leading up to n. Every time a number y goes evenly into n, a counter will be increased by 1. if the counter is equal to 2, then the number is prime and we print it to the screen. Any help would be so greatly appreciated. Thanks
std::cout << std::to_string(2) << std::endl;
for (unsigned int i = 3; i<240; i += 2) {
unsigned int j = 3;
int sq = sqrt(i);
for (; j <= sq; j += 2) if (!(i%j)) break;
if (j>sq) std::cout << std::to_string(i) << std::endl;
}
first of all, the prime definition: A prime number (or a prime) is a natural number greater than 1 that has no positive divisors other than 1 and itself.
so you can skip all the even numbers (and hence ... i+=2).
Moreover no point to try to divide for a number greater than sqrt(i), because then it will have a divisor less than sqrt(i) and the code finds that and move to the next number.
Considering only odd numbers, means that we can skip even numbers as divisors (hence ... j+=2).
In your code there are clearly beginner errors, like (x = 0) instead of x==0. but also the logic doesn't convince. I agree with #NathanOliver, you need to learn to use a debugger to find all the errors. For the rest, good luck with the studies.
lets start with common errors:
first you want to take input from user using cin
cin>>n; // write it before starting your while loop
then,
if (x = 0)
should be:
if (x == 0)
change your second while loop to:
while (i == 2){
cout << n;
i++;
}

How can I find out if numbers can be made equal in an array using this?

This question was given to me in an interview and I couldn't really come up with a solution for this:
If I am given an array containing some numbers, and I can double or triple each of the numbers an infinite number of times, and I just have to find out if the numbers can be made equal to each other or not, how can I do it? What can be a possible algorithm for this?
Let's take two elements from that array, and call them a and b. Now let's double and triple both of them until they're equal:
a * 2^i * 3^j == b * 2^m * 3^n
From this we can conclude that this works if (by simple transformation of above equation)
a / (2^m * 3^n) == b / (2^i * 3^j)
At first, this might not seem helpful. But remember that every number can be represented as the product of its prime factors:
c = 2^u * 3^v * 5^w * 7^x * 11^y * ...
(u, v, w, ... may be 0)
Now applying that to the previous equation, if we make m and n equal to the number of 2s and 3s (uand v) all that remains from a would be the product of all its prime factors expect 2 and 3. Do the same with b and then compare the results.
Now putting that into an algorithm (and applying it to more numbers) isn't so difficult (though we need to take care because we surely don't want to compute all prime factors of all elements).
Take the first element
Divide by 2 until it's no longer dividable by 2
Same but for 3
Save that as value to compare against
Take the next element
Divide by 2 as long as it's dividable by 2
Same for 3
Compare result to saved value, if different return false
Else, if there are elements left, GOTO 5.
If no elements are left, return true
Do you mean least common multiple?
If the numbers aren´t huge, you could calculate the (prime) factorization for each,
remove all 2´s and 3´s, and compare the sorted rest.
Example 1:
Numbers: 2 12 6
Factorization: (2) (2*2*3) (2*3)
2 and 3 removed: () () ()
Everything equal: Yes, so this numbers can be made equal
Example 2:
Numbers: 4 14
Factorization: (2*2) (2*7)
2 and 3 removed: () (7)
Everything equal: No, so this numbers can´t be made equal
Basically, for each number you´re calulating the remainder if you divide it by 2 and/or 3
as often as possible. If The remainders are equal...
Take each number in the array and remove all factors 2 and 3 from it in O(n log n). Then check if all the numbers in the array are equal.
Example code:
#include <iostream>
using namespace std;
int remove2And3(int x) {
while(x%2==0) x/=2;
while(x%3==0) x/=3;
return x;
}
int main() {
int n;
while(cin >> n) {
int first; cin >> first;
first = remove2And3(first);
bool answer = true;
for(int i=1; i<n; i++) {
int other; cin >> other;
other = remove2And3(other);
answer &= first == other;
}
cout << (answer ? "YES" : "NO") << endl;
}
}
Try to divided every numbers until it divisible by 2 or 3 and put it on to set
and finally check set size is equal to 1 or not, if set size is 1 then yes otherwise no.
Here below is c++ solution:
#include <iostream>
#include <set>
int main()
{
int tc, num;
std::set<int> ss;
while (std::cin >> tc) {
for (int i = 0; i < tc; i++) {
std::cin >> num;
while (num%2 == 0 || num % 3 == 0) {
if (num % 2 == 0)
num /= 2;
else if (num % 3 == 0)
num /= 3;
}
ss.insert(num);
}
if (ss.size() == 1)
std::cout << "Yes" << std::endl;
else std::cout << "No" << std::endl;
ss.clear();
}
return 0;
}
The line, each item can be doubled or tripled implies that you can multiply every number any number of times by 2 and 3. The ramifications of this are that the prime factorization of the number won't change, except the powers of 2 and 3. The corollary from this is that if two numbers have the same prime factorization, differing only in the powers of 2 and 3, they can be made equal. To clarify, my interpretation of making two numbers equal is that those two numbers multiplied by different number of 2s and 3s can be made equal to each other.
A simple function to check this on two numbers is as follows:
bool check(int a, int b)
{
while (a%2 == 0)
a = a/2;
while (a%3 == 0)
a = a/3;
while (b%2 == 0)
b = b/2;
while (b%3 == 0)
b = b/3;
return (a == b);
}
You can easily extend this to checking for an entire array.
Isn't that common divider problem? Just see if you can find bigger number that can produce integer in division by any of given numbers.
So having {2,3,5} array you could say yes, for something like 30.
Divide the element by itself from second index to last and multiply by first element.
Ex: array [2, 3, 4, 7, ...]
So now [2, 3/3 *2, 4/4 * 2, 7 / 7 * 2...]
If element is zero don't divide just add first element.