1

I have a problem where in a range of numbers L to R I should check how many of them are both palindroms (read the same forward and backward) OR divisible by all of its digits. Now, I have started a program which doesn't really work well, I made a few functions but I have a problem where in line 30 the compiler calls an error saying:

Main.cpp:30:41: error: in evaluation of 'operator%=(int, __gnu_cxx::__promote_2::__type {aka double})'
   palindrom_check %= pow(10, upper);
   ^

Here are examples of input and output given in the problem:

  • Input: 1 15
  • Output: 12

Explanation: In the interval of 1 to 15, the numbers are 1, 2, 3, 4, 5, 6, 7, 8, 9, 11, 12, 15 - therefore the output is 12.

  • Input: 303 304
  • Output: 1

I am pretty sure I'm not using the pow() correctly. I hope anyone can give me a way to continue or edit my code to fix it and make it work.

#include <iostream>
#include <cmath>

using namespace std;

int digits = 1;
int check_dig = 0;

int Digit(int n) {
    digits = 1;
    check_dig = n;
    while (check_dig > 10) {
        check_dig /= 10;
        digits++;
    }
}

int exponent = 1;
int front_check = 0;
int back_check = 0;
bool palindrom = false;
int palindrom_check = 0;
int upper = digits - 1;

int Palindrom(int n) {
    palindrom = false;
    exponent = (int)pow(10, upper);
    front_check = n;
    palindrom_check = n;
    while (palindrom_check > 0) {
        back_check += (palindrom_check % 10) * exponent;
        palindrom_check %= exponent;
        exponent /= 10;
    }
    if (back_check == front_check) {
        palindrom = true;
    }
}

bool divisible = false;
int divisible_check = 0;

int Divisibility(int n) {
    divisible_check = n;
    while (divisible_check > 0) {
        if (divisible_check % (divisible_check % 10) == 0) {
            divisible_check /= 10;
            divisible = true;
            continue;
        } else {
            divisible = false;
            break;
        }
    }
}

int main() {

    int L, R;
    cin >> L >> R;
    int result = 0;

    for (int i = L; i <= R; i++) {
        Digit(i);
        Palindrom(i);
        Divisibility(i);
        if (palindrom || divisible) {
            result++;
        }
    }

    cout << result;

    return 0;
}

Edit:

#include <iostream>
#include <cmath>

using namespace std;

int digits = 1;
int check_dig = 0;

void Digit(int n) {
    digits = 1;
    check_dig = n;
    while (check_dig > 10) {
        check_dig /= 10;
        digits++;
    }
}

int front_check = 0;
int back_check = 0;
int palindrom_check = 0;
int upper = digits - 1;

bool palindrom(int n) {
    front_check = n;
    back_check = 0;
    palindrom_check = n;
    while (palindrom_check > 0) {
        back_check = (back_check * 10) + (palindrom_check % 10);
        palindrom_check /= 10;
    }
    if (back_check == front_check) {
        return true;
    }
}

int divisible_check = 0;

bool divisible(int n) {
    divisible_check = n;
    while (divisible_check > 0) {
        if (divisible_check % (divisible_check % 10) == 0) {
            divisible_check /= 10;
            return true;
        } else {
            return false;
            break;
        }
    }
}

int main() {

    int L, R;
    cin >> L >> R;
    int result = 0;

    for (int i = L; i <= R; i++) {
        Digit(i);
        palindrom(i);
        divisible(i);
        if (palindrom || divisible) {
            result++;
        }
    }

    cout << result;

    return 0;
}
NutCracker
  • 11,485
  • 4
  • 44
  • 68
N.T.
  • 99
  • 6
  • 1
    Please note that you should *return* (and possibly *use*) something from all your functions. You may also want to investigate the differences between *local* and *global* variables. – Bob__ Mar 21 '19 at 17:09
  • Please explain your expectation of what happens at this `Divisibility(i);`. – Yunnosch Mar 21 '19 at 19:19
  • Please explain your understanding of what the first `int` means in this `int Divisibility(int n)` and how it related to a possible `return`. – Yunnosch Mar 21 '19 at 19:20
  • @Yunnosch It’s basically checking if it’s divisible with all of the digits... I guess my problem is in the palindrom loop I probably have the wrong algorhithm there. – N.T. Mar 21 '19 at 19:22
  • Turns out I have that algorhithm messed up too, the divisibility one... Well. – N.T. Mar 21 '19 at 19:23
  • Try compiling with strict warnings, you will be surprised how much a compiler will tell you about your "perfectly fine" code. – Yunnosch Mar 21 '19 at 19:26
  • https://ericlippert.com/2014/03/05/how-to-debug-small-programs/ https://stackoverflow.com/questions/2069367/how-to-debug-using-gdb – Yunnosch Mar 21 '19 at 19:26
  • @Yunnosch I guess it should check my 'divisibility' and 'palindrom' bools if they're true or not for each 'i' number, I guess? – N.T. Mar 21 '19 at 21:01
  • I edited it a bit, I edited my post with the new piece of code but it's still not displaying anything on-screen. – N.T. Mar 21 '19 at 21:06
  • What insights did you get from debugging? – Yunnosch Mar 22 '19 at 04:52

2 Answers2

0

It looks to me as though this line:

palindrom_check %= pow(10, upper);

will be unhappy as pow(10,upper) is coming out as a double, not an int. The modulus operator % doesn't really make sense for double precision numbers. The error you have can be fixed by typecasting this to an integer:

palindrom_check %= (int)pow(10, upper);
Hoog
  • 2,280
  • 1
  • 14
  • 20
  • Yes, you're right! It was the data type that's making the problem, I can now compile it but... My program still keeps endlessly looping, any help? – N.T. Mar 21 '19 at 17:06
  • Maybe. Which loop is it stuck in? what are the variable inputs for that loop? – Hoog Mar 21 '19 at 17:10
  • 2
    Also worth adding a reminder to folks that `double`s are imprecise and you can easily get truncation errors converting the result of `pow` to an `int`. It's safer (and probably faster) to multiply or use a look-up table. – user4581301 Mar 21 '19 at 17:55
  • @Hoog No idea, my problem is that I don't know where my mistake is - the code seems perfectly fine to me. – N.T. Mar 21 '19 at 18:14
  • I suggest using a debugger with breakpoints to find where your code gets into an infinite loop. You can tell it to stop inside each loop and you can check what all the variables are when it does stop until you find something that is not what you think it should be. Otherwise you could toss some `printf("Loop1");`, `printf("Loop2");` statements and see which ones won't stop printing, but using the debugger will help you much more as you progress. – Hoog Mar 21 '19 at 19:18
0

In C++, a function defined as

bool divisible(int n) { /* … */ }

Is a function that accepts an integer value passed as an argument when called and returns a bool. A properly instructed compiler would complain (among other things) if there exist at least one path that the execution could take which doesn't return anything.

bool divisible(int n) {
    divisible_check = n;           // No need for that variable to be global.
    while (divisible_check > 0) {  // If it's 0, the loop (which isn't a loop) is not executed.
        if ( /* ... */ ) {
            // ...
            return true;
        } else {
            return false;
            break;                 // <- Useless.
        }
    }
    // And now what?
}

The same applies to the other function, that could be implemented like so:

bool is_divisible_by_all_of_its_digits(int n)
{
    int tmp = n;
    while (tmp > 0)
    {
        int digit = tmp % 10;
        // We want to prevent n % 0 which would cuase a floating point exception
        if ( digit == 0  ||  n % digit != 0)
        {
            return false;
        }
        tmp /= 10;         
    }
    return true;
}

The returned value can be used directly in the condition

// ...
for (int i = L; i <= R; i++) {
    if ( is_palindrome(i)  ||  is_divisible_by_all_of_its_digits(i)) {
        result++;
    }
}
Bob__
  • 12,361
  • 3
  • 28
  • 42