|
| 1 | +/** |
| 2 | + * @file mirror.c |
| 3 | + * @author Chavatzoglou Lazaros |
| 4 | + * @brief Find (non palindromic) prime square mirrors within a given range. |
| 5 | + */ |
| 6 | + |
| 7 | +#include <stdio.h> |
| 8 | +#include <stdlib.h> |
| 9 | +#include <math.h> |
| 10 | +#include <stdbool.h> |
| 11 | +#include <errno.h> |
| 12 | + |
| 13 | + |
| 14 | +// Global variable to store the sum of prime square mirrors. |
| 15 | +unsigned long long sq_sum = 0; |
| 16 | + |
| 17 | + |
| 18 | +/** |
| 19 | + * @brief Check if a given number is a prime number. |
| 20 | + * @param n The number to check for primality. |
| 21 | + * |
| 22 | + * @note This function assumes that the input number (n) is greater than 2. |
| 23 | + * The behavior for n less than or equal to 2 is not defined. |
| 24 | + * |
| 25 | + * @return true if the number is prime, false otherwise. |
| 26 | + */ |
| 27 | +bool isPrime(unsigned int n){ |
| 28 | + if((n % 2) == 0){ |
| 29 | + return false; |
| 30 | + } |
| 31 | + |
| 32 | + |
| 33 | + for(int i = 3; i < (floor(sqrt(n)) + 1); i += 2){ |
| 34 | + if((n % i) == 0){ |
| 35 | + return false; |
| 36 | + } |
| 37 | + } |
| 38 | + |
| 39 | + return true; |
| 40 | + |
| 41 | +} |
| 42 | + |
| 43 | + |
| 44 | +/** |
| 45 | + * @brief Generate the mirror image of a given unsigned long long integer. |
| 46 | + * @param n The number for which to generate the mirror image. |
| 47 | + * |
| 48 | + * @note This function assumes that the input is positive and works only for |
| 49 | + * positive numbers, hence the unsigned datatype. |
| 50 | + * |
| 51 | + * @return The mirror image of the given number. |
| 52 | + */ |
| 53 | + |
| 54 | +unsigned long long mirror(unsigned long long n){ |
| 55 | + |
| 56 | + unsigned long long rslt = 0; |
| 57 | + |
| 58 | + while(n){ |
| 59 | + rslt = ((n % 10) + (rslt * 10)); |
| 60 | + n /= 10; |
| 61 | + } |
| 62 | + |
| 63 | + return rslt; |
| 64 | + |
| 65 | +} |
| 66 | + |
| 67 | + |
| 68 | + |
| 69 | +/** |
| 70 | + * @brief Main function to find (non palindromic) prime square mirrors within |
| 71 | + * a given range. |
| 72 | + * @param argc The number of command-line arguments. |
| 73 | + * @param argv An array of strings containing the command-line arguments. |
| 74 | + * |
| 75 | + * @section DESCRIPTION: |
| 76 | + * The program takes two command-line arguments representing the lower and |
| 77 | + * upper bounds of the range. It then iterates from the ceiling of square root |
| 78 | + * of the lower bound to the floor of the square root of the upper bound, but |
| 79 | + * only through the odd numbers (this is done by adjusting the lower bound so |
| 80 | + * it is odd and by incrementing counter by 2), generating the square roots of |
| 81 | + * the all perfect squares in the given range. In each iterationa perfect |
| 82 | + * square is genrated and then its mirror. And we check whether these numbers |
| 83 | + * meet our criteria and if so we add them to the sum. |
| 84 | + * |
| 85 | + * @section OUTPUT: |
| 86 | + * Last but not least the programme outputs the total sum of all the prime |
| 87 | + * square mirrors found (given that the programme did not terminate due to the |
| 88 | + * input not meeting the technical specifications). |
| 89 | + * |
| 90 | + * |
| 91 | + * @note The programme iterates only through odd numbers because we are |
| 92 | + * interested in these numbers being prime and odd numbers aren't (with the |
| 93 | + * exception of 2 which is the root of 4 which only has one digit therefore a |
| 94 | + * palindrome which excludes it from excluding it from our interest). |
| 95 | + * |
| 96 | + * |
| 97 | + * @return 0 if successful, 1 if an incorrect number of arguments is provided, |
| 98 | + * or genrally the technical specifications describbed in |
| 99 | + * https://progintro.github.io/resources/hw1.pdf concerning the input of the |
| 100 | + * programme mirror are not met. |
| 101 | + */ |
| 102 | + |
| 103 | + |
| 104 | +int main(int argc, char **argv){ |
| 105 | + |
| 106 | + // Check if the correct number of command-line arguments is provided. |
| 107 | + if(argc != 3){ |
| 108 | + return 1; |
| 109 | + } |
| 110 | + |
| 111 | + // Set errno to 0. |
| 112 | + errno = 0; |
| 113 | + |
| 114 | + // Parse command-line arguments and set the range. |
| 115 | + long long low = strtoll(argv[1], NULL, 10); |
| 116 | + long long high = strtoll(argv[2], NULL, 10); |
| 117 | + // CHeck whether an error occured during the the conversions using strtoll |
| 118 | + // (overflow/underflow). |
| 119 | + if(errno != 0) { return 1; } |
| 120 | + |
| 121 | + // Validate the range. |
| 122 | + if((low > high) || (high > 1E15) || (low < 1)){ |
| 123 | + return 1; |
| 124 | + } |
| 125 | + |
| 126 | + // Generate a new low which coresponds to the root of the smallest |
| 127 | + // perfect square within range. |
| 128 | + int l_low = ceil(sqrt(low)); |
| 129 | + // Gnerate a new high which coresponds to the root of the largest |
| 130 | + // perfect square within range. |
| 131 | + int l_high = floor(sqrt(high)); |
| 132 | + |
| 133 | + // Adjust the lower bound so it skips all numbers with single digit squares (as they |
| 134 | + // are plindromes) and set it to the first odd number 5 so we can iterate |
| 135 | + // with step 2 only through odd numbers as even ones above 10 aren't |
| 136 | + // canditates for prime numbers. |
| 137 | + if(l_low < 5){ l_low = 5; } |
| 138 | + // Adjust the lower bound to skip one number if the current one is even so |
| 139 | + // we can iterate with step 2 and check only even numbers for primality as |
| 140 | + // odds above 11 aren't prime. |
| 141 | + else if((l_low % 2) == 0 ){ ++l_low; } |
| 142 | + |
| 143 | + // Iterate through all odd numbers which are square roots of perfect |
| 144 | + // squares in the range. |
| 145 | + for(int i = l_low; i <= l_high; i += 2){ |
| 146 | + |
| 147 | + // Generate the perfect square. |
| 148 | + unsigned long long square = pow(i, 2); |
| 149 | + // Generate the mirror |
| 150 | + unsigned long long mirr = mirror(square); |
| 151 | + |
| 152 | + // Check if the mirror of the square and the square are equal which |
| 153 | + // means it's a palindrome, therefore we skip the current iteration |
| 154 | + if(square == mirr) { continue; } |
| 155 | + // Check if the mirror is even in which case even if it is a perfect |
| 156 | + // square the square root will be even therefore not prime, therefore |
| 157 | + // we skip to the next iteration. |
| 158 | + if((mirr % 2) == 0) { continue; } |
| 159 | + // Generate the square root of the mirror. |
| 160 | + double mirr_sqrt = sqrt(mirr); |
| 161 | + // Check if the square root has a non zero decimal part threrfore not |
| 162 | + // an integer and subsequently not a prime, so we skip to the next |
| 163 | + // iteration. |
| 164 | + if(fmod(mirr_sqrt, 1.0) != 0) { continue; } |
| 165 | + |
| 166 | + // Check if the the current square root i has stored and the square |
| 167 | + // root of the mirror aren't prime, in which case you guessed it we |
| 168 | + // skip to the next iteration. |
| 169 | + if(!isPrime(i)){continue; } |
| 170 | + if(!isPrime(mirr_sqrt)) {continue; } |
| 171 | + |
| 172 | + // If i passed all the above tests it fits all our criteria and |
| 173 | + // therefore is the square root of a prime perefect square mirror, so |
| 174 | + // we add the corespondindg square to the sum. |
| 175 | + sq_sum += square; |
| 176 | + } |
| 177 | + |
| 178 | + |
| 179 | + // Print the total sum of prime square mirrors to STDOUT. |
| 180 | + printf("%llu\n", sq_sum); |
| 181 | + |
| 182 | + return 0; |
| 183 | + |
| 184 | +} |
| 185 | + |
0 commit comments