Skip to content

Commit a5919ba

Browse files
committed
Starting to add samples.
1 parent e858e67 commit a5919ba

File tree

4 files changed

+321
-0
lines changed

4 files changed

+321
-0
lines changed

Diff for: README.md

+1
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,7 @@
5757

5858
* [Εισαγωγή στους Pointers](https://www.youtube.com/watch?v=tH2JW8HsPNw)
5959
* [Ενδεικτικές λύσεις για τα εργαστήρια](https://github.com/dimskomex/ip-labs-solutions)
60+
* [Ενδεικτικά README/Σχόλια](./samples/README.md)
6061

6162
## Εργασίες
6263

Diff for: samples/README.md

+4
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
# Παραδείγματα README και λύσεις ασκήσεων
2+
3+
1. [mirror README (1)](./mirror1/README.md)
4+
1. [mirror code (1)](./mirror1/mirror.c)

Diff for: samples/code/mirror1/README.md

+131
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,131 @@
1+
*****
2+
# This programme finds all the non-palindromic prime square mirrors in a given range.
3+
******
4+
### These are the libraries used:
5+
1. **stdio.h** This library is included for the function **printf**, so we can output the results to __STDOUT__.
6+
2. **stdlib.h** This library is included for the function **strtoll**, so we can covert the command line arguments to **long long** datatype numbers.
7+
3. **math.h** This library is included for the function **pow**, so we can calculate the square of numbers; the function **sqrt**, so we can calculate square roots; the function **floor** so we can take the floor of a number, and the function **ceil**n so we can take the ceiling of a number.
8+
4. **stdbool.h** This library is included for the datatype **bool**, so we can handle more easily true/false statements.
9+
5. **errno.h** This library is included for the variable **errno**, which can be set from other functions in the c library, in this case **strtoll**, so we can detect errors (in this case whether the conversion was successful, or there was overflow/undeflow).
10+
***********
11+
12+
## Build
13+
14+
15+
This programme can be compiled with the command:
16+
```shell
17+
gcc -O3 -Wall -Wextra -Werror -pedantic -o mirror mirror.c -lm
18+
```
19+
20+
## Usage
21+
22+
And it must be executed in this manner:
23+
```shell
24+
./mirror low high
25+
```
26+
where low is the lower bound and high is the higher bound.
27+
***************
28+
29+
## Demo
30+
31+
```sh
32+
$ ./trolley
33+
lkjsdflk sjlkj
34+
```
35+
36+
## Functions
37+
#### isPrime
38+
```c
39+
bool isPrime(unsigned int n){ //works for n > 2
40+
if((n % 2) == 0){
41+
return false;
42+
}
43+
44+
45+
for(int i = 3; i < (floor(sqrt(n)) + 1); i += 2){
46+
if((n % i) == 0){
47+
return false;
48+
}
49+
}
50+
51+
return true;
52+
53+
}
54+
```
55+
This function tests if a number above 2 is prime or not.
56+
This function employs a basic primality testing algorithm. It first checks if the input number is divisible by 2, and if so, returns false. Then, it
57+
iterates through odd numbers starting from 3 up to the square root of the input number. If the input number is divisible by any of these odd numbers,
58+
the function returns false. If no divisors are found, the function concludes that the input number is a prime number and returns true.
59+
This primality test works, because if a number is not prime it has at least one divisor apart from 1 and itself.
60+
Therefore, if $n$ isn't prime and has a divisor $a$ it can be written such as $s = a \cdot b$, where $b$ is the result of the division of $n$ by $a$.
61+
Then either $\sqrt{n} \geq a$ or $\sqrt{n} \geq b$. Otherwise $a \ge \sqrt{n}$ and $b > \sqrt{n}$ so $a \cdot b > {\sqrt{n}}^2 = n \xRightarrow[]{n = a \cdot b} n > n$
62+
which cannot be true. Therefore if $n$ isn't prime it has one divisor smaller or equal then the $\sqrt{n}$.
63+
(Also we take the ceiling of the square root of n beacuse one check is really cheap computationally and can't hurt.)
64+
65+
***********
66+
#### mirror
67+
```c
68+
unsigned long long mirror(unsigned long long n){
69+
70+
unsigned long long rslt = 0;
71+
72+
while(n){ //works beacuse MIN low is 1
73+
rslt = ((n % 10) + (rslt * 10));
74+
n /= 10;
75+
}
76+
77+
return rslt;
78+
79+
}
80+
```
81+
This function takes an unsigned long long integer as input and returns a new integer with its digits reversed. It uses a while loop to iterate through
82+
the digits of the input number, extracting the last digit in each iteration and appending it to the result after shifting the result to the left by one
83+
decimal place and then shifhting the number $n$ by ne decimal place to the right so that in the next iteration we will get th next digit.
84+
The loop continues until the input number becomes zero due to divisions by 10.
85+
86+
***********
87+
88+
## main
89+
1. First, we check that the correct number of arguments is provided; otherwise, the programmme terminates with exit code 1.
90+
```c
91+
if(argc != 3){
92+
return 1;
93+
}
94+
```
95+
2. **errno** is set to 0 (as required by its documentation), so if **strtod** sets it to a non-zero value, we can be certain this value is due to an error.
96+
3. Then we parse the command-line arguments corresponding to the higher and lower bound of our range.
97+
```c
98+
long long low = strtoll(argv[1], NULL, 10);
99+
long long high = strtoll(argv[2], NULL, 10);
100+
```
101+
4. Then we check whether **errno** has a non-zero value, thus indicating that there was overflow/underflow during a conversion from **string** to **long long**.
102+
5. Afterwards, we check that range we are given is valis.
103+
```c
104+
if((low > high) || (high > 1E15) || (low < 1)){
105+
return 1;
106+
}
107+
```
108+
6. Then we generate 2 new bounds for a loop ```l_low``` and ```l_high``` which correspond to the square root of the smallest and largest perefect square in our range (we use **seil** and **floor** to ensure that we dont include numbers outside our range).
109+
```c
110+
int l_low = ceil(sqrt(low));
111+
int l_high = floor(sqrt(high)) + 1;
112+
```
113+
7. Then we further adjust the lower boound ```l_low``` so that in case it is smaller than 5 it is to 5 as it is the smallest odd number and its square has more than one digit,
114+
as signle digit numbers are palindromes which we want to exclude. Also if ```l_low``` is even we increment by one, due to the fact that even nubers cannot prime (with the exception of 2),
115+
so we can have step 2 in our loop so we only check odd numbers for primality.
116+
```c
117+
if(l_low < 5){ l_low = 5; }
118+
else if((l_low % 2) == 0 ){ ++l_low; }
119+
```
120+
8. Then we iterate from ```l_low``` to ```l_high``` with step 2, so that we can go through all the square roots of the perfect squares in our given range. Thus we generate the perfect squares instead of checking if all numbers whether they are a perfect square.
121+
1. First we generate the perfect square ```square```.
122+
2. Then we generate its mirror ```mirr```.
123+
3. Then in case the square is the same as the mirror the number is a palindrome and so we skip to the next iteration.
124+
4. If the mirror divided by 2 has a remainder zero then it's odd. Therefore even if it is a perfect square its square root will be odd and therefore not prime (as the only odd prime is 2 and its square 4 is a palindrome, as it a one digit number), so we skip to the next iteration.
125+
5. If the square root of the mirror ```mirr_sqrt``` has a non zero decimal part then the mirror isn't a perfect square hence it's root can't be prime as primes are natural numbers. So we skip to the next iteration.
126+
6. If the square root of the mirror ```mirr_sqrt``` or the square root of the perfect square ```i```, which was used to generate the mirror, isn't a prime we skip to the next iteration as this number doesn't satisfy the given definition.
127+
7. If all the above tests were passed then ```square``` meets all of our criteria and therefore we add it to the total sum.
128+
129+
8. Last we print the total sum of all the prime square mirrors and terminate the programme with exit code 0.
130+
131+

Diff for: samples/code/mirror1/mirror.c

+185
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,185 @@
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

Comments
 (0)