#include <iostream>
#include <cmath>
using namespace std;

// Serie di macro per trasformare rispettivamente i valori booleani 1 (true) e 0 (false) in "Yes" o "No"
#define AUTOMORPHIC(isAutomorphic) ((isAutomorphic) ? "Yes" : "No")
#define PERFECT(isPerfect) ((isPerfect) ? "Yes" : "No")
#define PALINDROMO(isPalindromo) ((isPalindromo) ? "Yes" : "No")
#define PRIME(isPrime) ((isPrime) ? "Yes" : "No")

bool isAutomorphic(int x); // Prototipo della funzione che definisce se il numero dato in input è automorfico
bool isPerfect(int x); // Prototipo della funzione che definisce se il numero dato in input è perfetto
bool isPalindromo(int x); // Prototipo della funzione che definisce se il numero dato in input è palindromo
bool isPrime(int x); // Prototipo della funzione che definisce se il numero dato in input è primo

int main(void) {
    int num;

    cout << "Enter a number: ";
    cin >> num;
    
    // Nella chiamata delle nostre funzioni ci serviamo appunto anche delle macro sopra scritte per restituire "Yes" o "No"
    cout << "Automorphic number? " << AUTOMORPHIC(isAutomorphic(num)) << endl; // Chiamata della funzione che definisce se il numero dato in input è automorfico
    cout << "Perfect number? " << PERFECT(isPerfect(num)) << endl; // Chiamata della funzione che definisce se il numero dato in input è perfetto
    cout << "Palindromic number? " << PALINDROMO(isPalindromo(num)) << endl; // Chiamata della funzione che definisce se il numero dato in input è palindromo
    cout << "Prime number? " << PRIME(isPrime(num)) << endl; // Chiamata della funzione che definisce se il numero dato in input è primo

    return 0;
}

// Definizione della funzione che definisce se il numero dato in input è automorfico
bool isAutomorphic(int x) {
    int square = x * x;
    int numberDigits = 0;
    int temp = x;
    
    while (temp > 0) {
        numberDigits++;
        temp = temp / 10;
    }
    
    int potenza = pow(10, numberDigits);
    int lastDigits = square % potenza;

    return lastDigits == x;
}

// Definizione della funzione che definisce se il numero dato in input è perfetto
bool isPerfect(int x) {
    int sum = 0;
    
    for (int i = 1; i <= x / 2; i++) {
        if (x % i == 0) {
            sum += i;
        }
    }
    return sum == x;
}

// Definizione della funzione che definisce se il numero dato in input è palindromo
bool isPalindromo(int x) {
    int originalNumber = x;
    int reverseNumber = 0;
    
    while (x != 0) {
        int digit = x % 10;
        reverseNumber = reverseNumber * 10 + digit;
        x = x / 10;
    }
    return originalNumber == reverseNumber;
}

// Definizione della funzione che definisce se il numero dato in input è primo
bool isPrime(int x) {
    if (x <= 1) {
        return false;
    }

    int root = sqrt(x);
    
    for (int i = 2; i <= root; i++) {
        if (x % i == 0) {
            return false;
        }
    }
    return true;
}