Check if number is perfect prime recursively c++ - c++

I've been assigned to write a program that checks if a number is perfect prime or not (the sum of its digits is prime, the sum of the sum of its digits is prime...). I've stumbled upon two extreme cases that break my program:
INPUT: 20328307 OUTPUT: true (expected false)
INPUT: 587899597 OUTPUT: true (expected false)
The code:
#include <iostream>
using namespace std;
bool is_prime(int n) {
if (n == 0 or n == 1) return false;
if (n == 2) return true;
if (n % 2 == 0) return false;
for (int i = 3; i * i == n; i += 2) {
if (n % i == 0) return false;
}
return true;
}
int sum_of_digits(int n) {
int sum = 0;
while (n > 0) {
sum += n % 10;
n /= 10;
}
return sum;
}
bool is_perfect_prime(int n) {
if (sum_of_digits(n) >= 10) is_perfect_prime(sum_of_digits(n)); //cas recursiu
return is_prime(n); //cas base
}
int main() {
int n;
while (cin >> n) cout << (is_perfect_prime(n) ? "true" : "false") << endl;
}
I can't see where this script fails for these two values, and why it doesn't fail for smaller numbers.

First of all your for loop is incorrect, it should be instead:
for (int i = 3; i * i <= n; i += 2) {
if (n % i == 0) return false;
}
otherwise you return true almost on every non even number. Second you ignore result of recursive call, possible solution is:
bool is_perfect_prime(int n) {
if ( n >= 10 and not is_perfect_prime(sum_of_digits(n)) )
return false;
return is_prime(n); //cas base
}

Finally I've got it to work. The problem was in the is_prime() for loop and in the recursive case of is_perfect_prime(). This is what I've come up with:
bool is_prime(int n) {
if (n == 0 or n == 1) return false;
if (n == 2) return true;
if (n % 2 == 0) return false;
for (int i = 3; i * i <= n; i += 2) {
if (n % i == 0) return false;
}
return true;
}
int sum_of_digits(int n) {
int sum = 0;
while (n > 0) {
sum += n % 10;
n /= 10;
}
return sum;
}
bool is_perfect_prime(int n) {
if (n < 10) return is_prime(n);
if (! is_prime(n)) return false;
return is_perfect_prime(sum_of_digits(n));
}
Thanks for your answers.

Related

Floating point exception: 8 on Smith number check

So I have written a code to check if a long int number is Smith, but I keep getting Floating point exception: 8, no matter what size do I fix my variables in. Not quite sure what I am missing.
#include <iostream>
bool isPrime(long int k) {
if (k == 1) return false;
for (long int i = 2; i*i < k; i++)
if (k % i == 0)
return false;
return true;
}
int main(){
long int n;
std::cin >> n;
long int sumPr = 0, sumCif = 0;
while (n > 0) {
sumCif += n % 10;
n = n/10;
}
for (long int i = 0; i*i<=n/2; i++) {
if (isPrime(i)) {
while (n % i == 0){
long int p = i;
while (p > 0) {
sumPr += (p % 10);
p = p/10;
}
n = n/i;
}
}
}
if (sumPr == sumCif) std::cout << "1" ; else std::cout << "0";
return 0;
}
The limits of this loop appear to be flawed:
for (long int i = 0; i*i<=n/2; i++) {
Possibly partly due to copy and paste from isPrime(). But the larger problem is you need to modularize this code so that you can properly test each component. And reuse modules (e.g. you implement sum of digits of a number twice in your code.) Code duplication is a potential source of error.
#include <iostream>
bool isPrime(long number) {
if (number < 2) {
return false;
}
if (number % 2 == 0) {
return (number == 2);
}
for (long divisor = 3; divisor * divisor <= number; divisor += 2) {
if (number % divisor == 0) {
return false;
}
}
return true;
}
long sum_digits(long number) {
long sum = 0;
while (number > 0) {
sum += number % 10;
number /= 10;
}
return sum;
}
long sum_prime_factor_digits(long number) {
long sum = 0;
for (long divisor = 2; divisor <= number; divisor++) {
if (isPrime(divisor)) {
while (number % divisor == 0) {
sum += sum_digits(divisor);
number /= divisor;
}
}
}
return sum;
}
bool is_smith(long number) {
if (isPrime(number)) {
return false; // only composites can play this game
}
return sum_digits(number) == sum_prime_factor_digits(number);
}
int main() {
long number;
std::cin >> number;
if (is_smith(number)) {
std::cout << "1";
} else {
std::cout << "0";
}
std::cout << "\n";
return 0;
}
TESTS
> ./a.out
4
1
> ./a.out
5
0
> ./a.out
6
0
> ./a.out
22
1
> ./a.out
4937775
1
> ./a.out
15966114
1
>
Writing clean code isn't something you do after the fact, it's what you do to help you in the debugging process.

How to check if number has a repeating digit using recursion?

I need to know if a number has a repeating digit using recursion and return 'yes' or 'no'. I am not allowed to use loops or arrays. This is what I've done untill now with 10 global variables and it works, but I think there is a better way.
#include <iostream>
using namespace std;
int counter0 = 0;
int counter1 = 0;
int counter2 = 0;
int counter3 = 0;
int counter4 = 0;
int counter5 = 0;
int counter6 = 0;
int counter7 = 0;
int counter8 = 0;
int counter9 = 0;
bool check(int k) {
int p = k % 10;;
if (k < 10) {
return false;
} else {
if (p == 0) {
counter0++;
} else if (p == 1) {
counter1++;
} else if (p == 2) {
counter2++;
} else if (p == 3) {
counter3++;
} else if (p == 4) {
counter4++;
} else if (p == 5) {
counter5++;
} else if (p == 6) {
counter6++;
} else if (p == 7) {
counter7++;
} else if (p == 8) {
counter8++;
} else if (p == 9) {
counter9++;
}
if(counter1>1 || counter2>1 || counter3>1 || counter4>1 || counter5>1 || counter6>1 || counter7>1 || counter8>1 || counter9>1)
{
return true;
}
k=k/10;
check(k);
}
}
int main() {
//cout << "Hello, World!" << std::endl;
int n;
cin >> n;
cout << (check(n) ? "yes" : "no") << endl;
//cout << n/10;
return 0;
}
#include <iostream>
using namespace std;
bool hasRepeatingDigit(int n, int mask)
{
// base case: if we have checked all the digits and didn't find any duplicates, return false
if (n == 0)
return false;
/*
p is the place of the last digit in n (n%10).
A digit can range from 0 to 9.
The place of 0 will be 1 << 0 which is 1.
The place of 1 will be 1 << 1 which is 2.
The place of 2 will be 1 << 2 which is 4.
...
...
The place of 9 will be 1 << 9 which is 512.
*/
int p = 1 << (n % 10);
// if place of p has already been marked then it's a duplicate
if (mask&p)
return true;
// otherwise scrap the last digit (n/10), mark place p and recurse on the remaining digits
return hasRepeatingDigit(n / 10, mask|p);
}
int main()
{
int n;
cin >> n;
cout << hasRepeatingDigit(n, 0) << endl;
}
Recursion problems always have a base case and an recursive case.
The base case is simple: k<11 has no repeated digits.
For the recursive case, k has repeated digits if either:
the lower two digits of k are equal, or
k/10 has repeated digits.
So:
bool check(int k) {
if (k < 11)
return false;
int digit = k % 10;
int next = k / 10;
int digit2 = next % 10;
if (digit == digit2)
return true;
else
return check(next);
// Or in one expression:
// return (digit == digit2) || check(next);
}
first, the code is incorrect...
if you enter n=11 it says 'no' but 1 repeated twice. you can fix it by changing the if statement from if(k < 10) to if(k == 0)
you can get down to the bits level but I can't see how much is useful...
in conclusion, this is the best you can do without arrays...
BUT: if you need to find if a digit repeated twice or more in a row the other answer is perfect

Prime testing algorithm not working properly

I have a prime testing algorithm, which I got from Project Euler, but it returns false when 43 is passed as input. The pseudo code was given in the overview, which I converted into c++ code. I may have made a mistake in converting the pseudo code. What is the actual problem with the algorithm?
#include <iostream>
#include <cmath>
using namespace std;
bool is_prime(int n)
{
if(n <= 1)
{
return false;
}
else if(n < 4)
{
return true;
}
else if(n % 2 == 0)
{
return false;
}
else if(n < 9)
{
return true;
}
else if(n % 3 == 0)
{
return false;
}
else
{
int r = sqrt(n);
int f = 5;
while(f <= r)
{
if(n % f == 0)
{
return false;
}
if((n + 2) % f == 0)
{
return false;
}
f = f + 6;
}
return true;
}
}
int main()
{
cout << is_prime(43);
system("PAUSE");
return 0;
}
Your algorithm is right but here is following mistake
if((n + 2) % f == 0) //wrong
{
return false;
}
should be
if(n%(f+2) == 0) //Right
{
return false;
}
You have an algorithm error. Instead of
(n+2)%f
it should read
n%(f+2)
Others have pointed out your error. You can simplify your code somewhat, reducing all those if statements:
bool is_prime(int n)
{
if(n <= 1)
{
return false;
}
if(n % 2 == 0)
{
return n == 2;
}
if(n % 3 == 0)
{
return n == 3;
}
// Check for factors of 5, 7, ...

Checking if a number is a Simber

A simber is defined as a positive integer in which any odd digit, if present, occurs an odd number of times, 1414414 is a simber. 4 is even and it appears four time and 1 is odd and it appears 3 times.
Here are my variables:
int is_simber(int n)
{
int numberOfTimes = 0, length = 1, x = n;
bool answer;
vector <int> nmbrs = vector <int>();
//get how many digits are in the integer
do
{
x /= 10;
length++;
}
while(x != 0)
//get the digits in the integer
for(int i = 0; i<length; i++)
{
nmbrs.push_back(((n/10^i) % 10);
}
//checking how many times a digit occurs and also testing to see if the digits
//meet the requirements
for(int i = 0; i<length; i++)
{
for(int j = 0; j<length; j++)
{
if (nmbrs.at(i) == nmbrs.at(j))
{
numberOfTimes++;
}
}
if (nmbrs.at(i) % 2 == 0 && numberOfTimes % 2 == 0)
{
answer = true;
}
else if(nmbrs.at(i) % 2 == 1 && numberOfTimes % 2 == 1)
{
answer = true;
}
else if(nmbrs.at(i) % 2 == 0 && numberOfTimes % 2 == 1)
{
answer = false;
break;
}
else if(nmbrs.at(i) % 2 == 1 && numberOfTimes % 2 == 0)
{
answer = false;
break;
}
}
return answer;
}
Your code has compilation errors.
^ is Binary XOR Operator. You can't expect it to produce pow(10,i). So replace nmbrs.push_back(((n/10^i) % 10); with nmbrs.push_back(((n/pow(10,i)) % 10);
When I was able to remove the compilation errors, i realized your code has logical errors too. As your given definition of simber, int is_simber(int n) should be fair and simple.
bool is_simber( int n )
{
if ( n<0 ) return false; // simber is a positive integer
int digitCount[10] = {}; // initializing all with 0;
// digitCount array holds the number of occurance of a digit
// so d[1] holds the number of times 1 occurred
// d[2] holds the number of times 2 occurred and so on ...
while( n ){
int d = n%10;
n /= 10;
digitCount[d]++;
}
// we just have to check
// any odd digit, if present, occurs an odd number of times
for( int i=1; i<=9; i= i+2) // Attention i=i+2, to iterate over just odd numbers
{
if( digitCount[i] != 0 && digitCount[i]%2 == 0 ) return false;
}
return true;
}
My definition of is_simber
inline bool is_even(int n) { return n % 2 == 0; }
bool is_simber(int n) {
if (n < 0) return false;
int digits[10] = {0};
for (; n; n /= 10) ++digits[n % 10];
for (int i = 0; i < 10; i += 2)
if (!is_even(digits[i]) && is_even(digits[i + 1])) return false;
return true;
}
LIVE DEMO

Project Euler 10 exercise

What is the sum of all the primes below 2000000?
Example of sum below 10 is 2+3+5+7 = 17
I wrote this code, but still getting the wrong answers:
I tested for numbers lower than a few hundreds, and it has shown the correct answers.
#include <iostream>
#include <math.h>
using namespace std;
bool isPrime(long n)
{
if (n < 2)
return false;
if (n == 2)
return true;
if (n == 3)
return true;
int k = 3;
int z = (int)(sqrt(n) + 1); // square root the n, because one of the product must be lower than 6, if squared root of 36
if (n % 2 == 0)
return false;
while (n % k != 0)
{
k += 2;
if (k >= z)
return true;
}
return false;
}
long primeSumBelow(long x)
{
long long total = 0;
for (int i = 0; i < x; i++) // looping for times of prime appearing
{
if (isPrime(i) == true)
total += i;
if (isPrime(i) == false)
total += 0;
}
cout << "fd" << endl;
return total;
}
int main()
{
cout << primeSumBelow(20) << endl;
cout << primeSumBelow(2000000) << endl;
system("pause");
return 0;
}
The total counter's type is correctly long long. Unfortunately the function primeSumBelow returns only long so, depending on the platform, the correctly calculated result is truncated when it's returned from this function.