Can someone thoroughly explain this IsItPrime Function? - c++

This is the function I found on CodeReview site, it determines if a number is a prime, while also handling negative numbers. There are few things I can't really catch up with.
1) Why is the first condition <= 3 when it's supposed to deal with negatives?
2) What does return n > 1 actually returns? And does it, in any way, affect other conditions?
bool IsItPrime(int n)
{
if(n <= 3) {
return n > 1;
} else if(n % 2 == 0 || n % 3 == 0) {
return false;
} else {
for(int i(5); i * i <= n; i += 6) {
if(n % i == 0 || n % (i + 2) == 0) {
return false;
}
}
return true;
}
}

if(n <= 3) {
return n > 1;
}
Is clever if not the easiest thing to reason out. First you enter the if body if you have a number of 3 or less. This covers the first 2 prime numbers plus all negative numbers, 0, and 1. Then it goes on to return n > 1; this means that if n is greater than 1 you will return true, otherwise false. So, if n is 2 or 3 the function will return true. It is is less than 2 then it returns false. It would be the same as
if (n <= 1) return false;
else if (n == 2 || n == 3) return true
else if ...
But as you can see that is more typing and adds an if statement.

according to wikipedia:
A prime number (or a prime) is a natural number greater than 1
return n > 1 means return true for any number greater than 1, (i.e. 2 or 3, because this appears after the test if n<=3). 0, 1 or a negative number will make it return false.

1) Why is the first condition <= 3 when it's supposed to deal with
negatives? 2) What does return n > 1 actually returns?
These questions are linked:
The function can take a negative argument, but as you can see the first set of conditions tests if the argument is between 1 and 3. 2,3 being prime, it will return true, if the argument is 1,0 or negative, it will return false (so it doesn't really work with negative numbers).

if(n <= 3) {
return n > 1;
}
This will return false for all numbers less than or equal to 3, except for 2 and 3. This handles negative numbers as well (any negative number will be less than 3).
else if(n % 2 == 0 || n % 3 == 0) {
return false;
}
This does a modulus operation on your argument, and returns false if the number is divisible by 2 or 3 (which would also make it not prime). We're safe to call this even though 2 and 3 are divisible since they're are handled above.
else {
for(int i(5); i * i <= n; i += 6) {
if(n % i == 0 || n % (i + 2) == 0) {
return false;
}
}
return true;
}
This handles all other digits by looping until you're above the square root of a number. It also does modulus operations, this time with 5, 7, and all values n + 6, n + 8 (<11, 13>, <17, 19>, etc). We can iterate by 6 since we're doing the 2 and 3 modulus operations above.

Related

why the iteration is done by i+6 every time and why the condition is i*i<=n for this prime testing function?

https://www.geeksforgeeks.org/primality-test-set-1-introduction-and-school-method/
// A optimized school method based C++ program to check
// if a number is prime
#include <bits/stdc++.h>
using namespace std;
bool isPrime(int n)
{
// Corner cases
if (n <= 1) return false;
if (n <= 3) return true;
// This is checked so that we can skip
// middle five numbers in below loop
if (n%2 == 0 || n%3 == 0) return false;
for (int i=5; i*i<=n; i=i+6)
if (n%i == 0 || n%(i+2) == 0)
return false;
return true;
}
When you search for primes you can loop through all the numbers between 2 and your number to see if they divide into your number.
for (int i=2; i < n; i=i+1)
if (n%i == 0)
return false;
But that checks a lot of number you don't need to.
The first observation (optimization) is that any multiple of 2 (even number) is already checked by simply doing a divide by 2 check once.
So now we do a check for 2 and then skip every other even character.
if (n%2 == 0 ) return false;
for (int i=3; i < n; i=i+2)
if (n%i == 0)
return false;
The next observation (optimization) is that you can do nearly the same thing for three. So the first test covers all combinations of 2 and three. Now in the loop you skip every 6 numbers (2*3) and do some tests to cover all numbers that are not multiples of 2 or 3 that happen in between.
if (n%2 == 0 || n%3 == 0) return false;
for (int i=5; i<n; i=i+6)
if (n%i == 0 || n%(i+2) == 0)
return false;
So this is simply an optimization that means you do not have to try every number.
The next observation we make is that you don't need to try numbers greater than the square root of n (these will never divide into n). So you can limit your loop to i*i < n as i*i is faster than sqrt(n).
if (n%2 == 0 || n%3 == 0) return false;
for (int i=5; i*i<=n; i=i+6)
if (n%i == 0 || n%(i+2) == 0)
return false;
Though personally I would do sqrt() once rather than i*i every time around the loop. But that may be slower for small values of n.
Any number that is composite will have at least one factor that is less than or equal to its square root. Why? Because if it has only a single factor (other than itself or one), that will be equal to its square root. If it has two or more, the smallest one will have to be less than its square root. So no need to check numbers greater than the square root -- if it wasn't prime, we would have already found a factor.
The code checks for 2 or 3 as a factor early. After that, we only need to check for factors that aren't multiples of two or three. So after we check 5 and 7, we don't need to check 6, 8, 9, or 10. So out of every six numbers we only need to check the two that aren't multiples of two or three.

Recursive function to counting specific digit

I need to create a recursive function that counts the 2 and 6 from the number a user inputs.
For example if the user enters 26827 the count is 3.
It works with certain numbers and certain numbers it doesn't. Can someone please modify my function making sure its recursive and using very basic C++ language as I have used. Thank you! (I believe something is wrong with return type.)
int count(int n) {
static int count = 0;
if (n == 2 || n == 6) count++;
if ((n % 10 == 2) || (n % 10 == 6)) {
count++;
count(num / 10);
}
else return count;
}
One liner for fun.
int f(int n) {
return n == 0 ? 0 : (n%10==2 || n%10==6) + f(n/10);
}
int count(int n) {
if(n <= 0) return 0; // Base Condition
int countDig = 0; // Initalizing Count of digits
if(n % 10 == 2 || n % 10 == 6) // Checking whether the LSB is 2 or 6
countDig ++; // If it is then incrementing the countDig
countDig += count(n / 10); // Calling the recurive function by sending the number except its LSB
//And incrementing counter according to it
return countDig; // Returning the final count
}
you don't need to have a static value counter. It can be easily done as above. Please refer to comments given. Second the error in your code is you only calling the recursion if the LSB is 2 or 6. The recursion should be put outside the if condition in your code. Why are you using num variable. I think it should be n
You don't need statics
This should work (note return c + count(n / 10) line. That's the main recursion here)
int count(int n)
{
int c = 0;
if(n % 10 == 2 || n % 10 == 6)
c = 1;
if(n < 10)
return c;
return c + count(n / 10);
}
If you want to make it with recursion , another procedure you can apply using string manipulation.
PseudoCode:
Function ( int n):
1. Make n as a string. ( Convert Number to string)
2. Collect the first character (char C) of the string and remove the character from the string.
3. Make the main string again as a number n. ( Convert String to Number).
4. Check the character C , which is number 2 or 6 or not, count it with a flag.
5. Enter base case for which the recursion will stop.
6. return the number n , inside the Function (n) for recursion.

How to determine, how many number of digits 3 is in variable

I have a variable which contains this numbers
int n = 6396339;
I need to determine how many digits 3 is in variable.
So far i trued like this:
int n = 6396339, counter = 0;
while (n > 0)
{
if ((n % 10) % 3 == 0) {
counter++;
}
n /= 10;
}
cout << counter << endl;
But this algorithm is not working correctly. Could you please help me to solve problem.
(n % 10) % 3 == 0
is true for any digit that is divisible by three, i.e. 0, 3, 6 and 9. Just check whether the digit is equal to 3:
(n % 10) == 3
You could print the number to a string, then traverse the string and check each character whether it is '3'.

Reaching the number 42 by recursion

I am trying to create a bear game where the user enters a number (n), and the program will see if it can reach the number 42 by doing some specified steps. If it can't, then it notifies the user that number can't reach the goal.
These are the rules:
If n is even, then you may give back exactly n/2 bears.
If n is divisible by 3 or 4, then you may multiply the last two digits of n and give back this
many bears.
If n is divisible by 5, then you may give back exactly 42 bears.
Here's an example:
Start with 250 bears
Since 250 is divisible by 5, you may return 42 of the bears, leaving you with 208 bears.
Since 208 is even, you may return half of the bears, leaving you with 104 bears.
Since 104 is even, you may return half of the bears, leaving you with 52 bears.
Since 52 is divisible by 4, you may multiply the last two digits (resulting in 10) and return
these 10 bears. This leaves you with 42 bears.
You have reached the goal!
Here's what I have so far:
#include <iostream>
using namespace std;
bool bears(int n);
int main(){
int number;
do{
cout<<"enter the amount of bears (press 0 to stop the program): ";
cin>>number;
if (bears(number)){
cout<<"you have reached the goal!"<<endl;
}
else{
cout<<"sorry, you have not reached the goal."<<endl;
}
}while(number != 0);
}
bool bears(int n){
if (n < 42){
return false;
}
else if (n == 42){
return true;
}
else{
if (n % 5 == 0){
return bears(n - 42);
}
else if(n % 2 == 0){
return bears(n / 2);
}
else if(n % 4 == 0|| n % 3 == 0)
{
int one;
int two;
one=n%10;
two=(n%100)/10;
return bears(n - one * two);
}
}
}
My program has the basic rules, but when I type in 250 bears it says it can't reach the goal. I understand what's happening in the code and why it can't reach the specified goal, but how do I make it universal so it'll work not just for the number 250, but for other numbers like: 84.
#Corristo's answer is good, but a similar depth first search algorithm can be used with minimal changes to your code. I've removed the redundant ifs and elses (since we're returning in every condition).
What this function does is instead of using a greedy approach like your solution does, it tests all cases till it finds an answer. Your code tests the second condition only if the first condition (divisibility by 5) is not satisfied, and so on.
bool bears(int n){
if (n < 42)
return false;
if (n == 42)
return true;
// Moves on if condition isn't satisfied
if ((n % 5 == 0) && bears(n - 42)) return true;
if ((n % 2 == 0) && bears(n / 2)) return true;
if(n % 4 == 0|| n % 3 == 0)
{
int one;
int two;
one=n%10;
two=(n%100)/10;
return one * two != 0 && bears(n - one * two);
}
return false;
}
You can try optimizing it further by using a cache (std::map) where you store the results and return the stored result if you have computed it before, but it'll only help in very few cases.
Since we don't have any a priori knowledge about which rule we need to choose for a particular number, the easiest way is to try all of them by exploring the entire state space. You can think of it as a reachability problem in an implicitly given graph.
One way to solve such a reachability problem is by using breath-first or depth-first search, which can be implemented recursively.
For your game this can be done by modifying your bears function to take a std::vector of integers for which it checks if it contains at least one number from which 42 can be reached.
With a depth-first search it might look as follows:
bool bears(std::vector<int> ns) {
// first remove all numbers < 42 since the goal cannot be reached from them
ns.erase(std::remove_if(std::begin(ns), std::end(ns),
[] (auto const& n) { return n < 42; }),
std::end(ns));
if (ns.empty()) {
return false;
} else if (std::any_of(std::cbegin(ns),
std::cend(ns),
[] (auto const& n) { return n == 42; })) {
return true;
} else {
auto possible_number_of_bears = std::vector<std::vector<int>>{};
std::transform(std::cbegin(ns),
std::cend(ns),
std::back_inserter(possible_number_of_bears),
[] (auto const& n) {
auto after_possible_rules = std::vector<int>{};
if (n % 5 == 0) {
after_possible_rules.emplace_back(n - 42);
}
if (n % 2 == 0) {
after_possible_rules.emplace_back(n / 2);
}
if (n % 4 == 0 || n % 3 == 0) {
int one;
int two;
one = n % 10;
two = (n % 100) / 10;
// avoid infinite recursion by only adding
// the new number if it is different from n
if (one * two != 0) {
after_possible_rules.emplace_back(n - one * two);
}
}
return after_possible_rules; });
return std::any_of(std::cbegin(possible_number_of_bears),
std::cend(possible_number_of_bears),
bears);
}
}
Now you only need to adjust the calling code to
if (bears({number})) {
std::cout << "you have reached the goal!" << std::endl;
} else {
std::cout << "sorry, you have not reached the goal." << std::endl;
}
and modify the forward declaration of bears accordingly.

Is required to only check up to (num/2+1) to determine if a number if prime?

I have successfully coded such a program to complete this task, however my friend and I are currently having a debate over one of the values.
Here is HIS loop function:
for (int iii = 2; iii < (num / 2 + 1); iii++)
{
if (num%iii == 0)
{
return false;
}
}
return true;
My question to him is, "Why do you need "2+1"?" Can't he just use his declared variable "num"?
You only need to check up to sqrt(num), which is less than or equal num/2 for num >= 4. This is because if a number n > sqrt(num) divides num, then num/n < sqrt(num) divides num.
Proof of that claim:
The square root of a positive number n is defined as the unique positive real number x for which x * x == n holds. Now consider you have a divisor d of n such that d > n. Then there is (because d is a divisor) a natural number d2 such that d * d2 == n. It is obvious that d2 := n / d is such a number. From x * x == n, d * d2 == n and d > x one can conclude d2 < x. That means that if a number greater than x divides n, there also is a number less than x that also divides day. So in conclusion, if no number less or equal x divides n, n is prime.
That means the function is correct for all values greater or equal 2. For num >= 4 this follows immediately from the above. For num <= 1 your function will alway return true because the loop never executes. For 2 <= num <=3 the loop returns true correctly because again, the loop is never entered. (Technically, you need the +1 to proof 5 is prime because 5/2=2 < sqrt(5) because of integer division).
Some improvement:
You could test with 2, and avoid all the other even numbers.
You only need to test until sqrt(number), already explained in other answer.
Code:
#include <cmath>
bool is_prime(unsigned long number) {
if (number % 2 == 0 && number != 2)
return false;
unsigned long sqrt_number = static_cast<unsigned long>(std::sqrt(number));
for (unsigned long i = 3; i <= sqrt_number; i += 2) {
if (number % i == 0)
return false;
}
return true;
}
Your code is implementing a "prime number" test. A number is prime if it is not divisible by any whole number other than itself and 1.
This problem space has some well known parameters/factors.
a) The maximum value that any given number, N, can be divided by to produce an integer value is N/2.
b) If N is divisible by an even number, it will also be divisible by 2, i.e. it must be even.
is_prime(N) {
if is_even(N) {
// if N is 2, it's prime, otherwise
// any even number is divisible by
// 2 and thus not prime.
return (N == 2)
}
md = max_divisor(N)
// we've eliminated even numbers, so we need only
// test odd numbers.
// all numbers are divisible by 1, so start at 3.
for (divisor = 3; divisor <= md; divisor += 2) {
// determine whether divisor divides into N
// without remainder indicating non-prime N
remainder = (N % divisor)
if (remainder != 0)
return false
}
return true
}
The max divisor is a number that, when divided into N, will produce 2.
max_divisor * 2 = N ->
max_divisor = N / 2
So simply:
max_divisor(N) return N / 2
What about checking for even numbers? We can do this one of two ways. We can modulo 2, but many people trying to optimize there code will remember their binary logical and realize they just have to test if the lowest bit (bit 1) is set or not.
0001 = 1 (odd)
0010 = 2 (even)
0011 = 3 (odd)
0100 = 4 (even)
0101 = 5 (odd)
0110 = 6 (even)
0111 = 7 (odd)
very simple:
is_even(N) (N % 2) == 0
or
is_even(N) (N & 1) == 0
And converting to C:
static inline bool isEven(unsigned int number) {
return (number & 1) == 0;
}
static inline unsigned int maxDivisor(unsigned int number) {
return (number / 2);
}
unsigned int isPrime(unsigned int number) {
if (isEven(number)) {
// if N is 2, it's prime, otherwise
// any even number is divisible by
// 2 and thus not prime.
// fluffy expanded version
return (number == 2) ? true : false;
// compact version
// return (number == 2);
}
const unsigned int md = maxDivisor(number);
// we've eliminated even numbers, so we need only
// test odd numbers.
// all numbers are divisible by 1, so start at 3.
for (unsigned int divisor = 3; divisor <= md; divisor += 2) {
// determine whether divisor divides into number
// without remainder indicating non-prime number
const unsigned int remainder = (number % divisor);
if (remainder != 0)
return false;
// compact version:
//if (number % divisor)
// return false;
}
return true;
}
Your friend's "(N / 2) + 1" is because he is using a less-than rather than a <=, you could remove the "+1" in his code by writing the following:
for (int iii = 2; iii <= (num / 2); iii++)