diff --git a/cipher/caesar_cipher.c b/cipher/caesar_cipher.c new file mode 100644 index 0000000000..f846cf653f --- /dev/null +++ b/cipher/caesar_cipher.c @@ -0,0 +1,96 @@ +/** + * @file + * @brief A [caesar cipher](https://en.wikipedia.org/wiki/Caesar_cipher) is a + * substitution cipher that replaces each letter in a text by another located + * a given number of positions along the alphabet. + * @author [Andrey Gonçalves Barreto Isidoro](https://github.com/agbi623) + */ + +#include /// for strcmp +#include /// for Input/Output +#include /// for isalpha, isupper and tolower +#include /// for assert + +/** + * @brief calculates the encrypted char for the encryption + * @param c the character to be used + * @param key the key to be used + * @returns the encrypted char (case-sensitive) + */ +int calculate_encrypted_char(char c, int key) +{ + int new_c; + + // calculates the offset + new_c = ((tolower(c) - 'a') + key) % 26; + + // (because the % operator doesn't handle negative left inputs) + // puts new_c back on the 0-26 range if it turned negative + if (new_c < 0) new_c += 26; + + return isupper(c) ? new_c + 'A' : new_c + 'a'; +} + +/** + * @brief encrypts the passed text by calling and assigning the return value + * of calculate_encrypted_char for each alphabetical character in the passed + * text string + * @param text the text to be encrypted + * @param key used for shifting a letter - shifts left when negative, right + * when positive + * @returns void + */ +void caesar_cipher(char *text, int key) +{ + for (int i = 0; text[i] != '\0'; i++) + { + if (isalpha(text[i])) + { + text[i] = calculate_encrypted_char(text[i], key); + } + } +} + +/** + * @brief tests the caesar_cipher function by passing some strings to it + * @returns void + */ +void test(void) +{ + char first[] = "ILOVETV"; + char second[] = "ILOVETV"; + char third[] = "The smoke... was blue."; + char fourth[] = "They think they are the fuckin big shot, like the world revolves around them. It\'s funny at times though x\'D"; + char fifth[] = "My compass was swallowed by the sea..."; + + caesar_cipher(first, 15); + assert(strcmp(first, "XADKTIK") == 0); + printf("First test OK\n"); + + caesar_cipher(second, -15); + assert(strcmp(second, "TWZGPEG") == 0); + printf("Second test OK\n"); + + caesar_cipher(third, 35); + assert(strcmp(third, "Cqn bvxtn... fjb kudn.") == 0); + printf("Third test OK\n"); + + caesar_cipher(fourth, -81); + assert(strcmp(fourth, "Qebv qefkh qebv xob qeb crzhfk yfd pelq, ifhb qeb tloia obslisbp xolrka qebj. Fq\'p crkkv xq qfjbp qelrde u\'A") == 0); + printf("Fourth test OK\n"); + + caesar_cipher(fifth, 0); + assert(strcmp(fifth, "My compass was swallowed by the sea...") == 0); + printf("Fifth test OK\n"); +} + +/** + * @brief main function; calls the test function + * @returns 0 if all tests pass + */ +int main(void) +{ + test(); + + return 0; +} diff --git a/numerical_methods/newton_raphson_root_2.c b/numerical_methods/newton_raphson_root_2.c new file mode 100644 index 0000000000..057ab4c2a2 --- /dev/null +++ b/numerical_methods/newton_raphson_root_2.c @@ -0,0 +1,156 @@ +/** + * @file + * + * + * @brief The [Newton-Raphson method](https://en.wikipedia.org/wiki/Newton%27s_method) + * is a root-finding algorithm which successively produces better + * approximations to the roots of a real-valued function. + * + * + * @author [Andrey Gonçalves Barreto Isidoro](https://github.com/agbi623) + */ + +#include // for Input/Output +#include // for fabs, sqrtf and logf +#include // for tolower +#include // for assert + +/** + * @brief Produces better approximations of the root of a. + * + * @details Assigns the absolute value of the a parameter to itself. Inside + * the loop, assigns the next approximation to x_nplus1. If the absolute + * difference between the next approximation and the current is less than + * or equal to the diff parameter, the for loop breaks. Else, the value of + * x_nplus1 gets assigned to x_n and the loop continues. If the visualize + * parameter is 1 (true), each approximation is printed. + * + * + * @param a the positive value to find the approximate root of + * + * @param diff the maximum deviation to be accepted + * + * @param visualize whether the user chose to visualize the process + * + * + * @returns the best approximation of the root + */ +double newtons_method(double a, double diff, int visualize) +{ + a = fabs(a); + + double x_n = a; + double x_nplus1; + + int i; + + if (visualize) printf("Start of approximations\n"); + + for (i = 1; i <= logf(a) * 20; i++) + { + if (visualize) printf("x_%d: %.12lf\n", i - 1, x_n); + + x_nplus1 = 0.5 * (x_n + a / x_n); + + if (fabs(x_nplus1 - x_n) <= diff) break; + + x_n = x_nplus1; + } + + if (visualize) printf("Final approximation (x_%d): %.12lf\n\n", i, x_nplus1); + + return x_nplus1; +} +/** + * @brief Tests if the implementation of the Newton-Raphson method is valid. + * + * @details Checks if the absolute difference between the return value of + * newtons_method and the square root is less than or equal to the passed + * deviation tolerance within the test[] parameter. + * + * + * @param test[] an array containing two values; the first is the number to + * get the root of and the second is the maximum deviation from the square + * root to be accepted + * + * @param visualize whether the user chose to visualize the process + * + * + * @returns whether the aforementioned check is true + */ +int individual_test(double test[], int visualize) +{ + double function_return = newtons_method(test[0], test[1], visualize); + double square_root = sqrtf(fabs(test[0])); + double abs_diff = fabs(function_return - square_root); + + return abs_diff <= test[1]; +} + +/** + * @brief Tests a given number of values. + * + * @details Iterates through the tests[] array and passes each element to + * individual_test(). Calculates the number of elements inside the tests[] + * array. Inside the loop, if the visualize parameter is 1 (true), the current + * test, the number to take the root of and the accepted deviation are + * printed. Then, the current element of the tests[] array and the visualize + * parameter are passed to the individual_test() function, in that order. If + * this function returns 0, the program halts because of assert. If not, the + * loop continues. + * + * + * @param visualize whether the user chose to visualize the process + * + * + * @returns void + */ +void test(int visualize) +{ + double test1[] = {625, 0.1}; + double test2[] = {2, 0.001}; + double test3[] = {1024, 0}; + double test4[] = {-25, 0}; + double test5[] = {4294967296, 0}; + + double *tests[] = {test1, test2, test3, test4, test5}; + + int tests_num = sizeof(tests) / sizeof(tests[0]); + + for (int i = 0; i < tests_num; i++) + { + if (visualize) + { + printf("-------------------\n"); + printf("Test %d\n", i + 1); + printf("a: %.12lf\n", tests[i][0]); + printf("Precision: %.12lf\n\n", tests[i][1]); + } + + assert(individual_test(tests[i], visualize)); + printf("Test %d OK\n", i + 1); + + if (visualize) printf("\n"); + } + + printf("\nAll tests passed\n"); +} + +/** + * @brief asks if the user would like to visualize then calls the test() function + * + * + * @returns 0 if all tests passed + */ +int main(void) +{ + int visualize = 0; + + printf("Would you like to see the process? (y/N) - "); + if (tolower(getchar()) == 'y') visualize = 1; + printf("\n"); + + test(visualize); + + return 0; +}