// # CS1 u8_palindrome.c
// Jonas Altrock <ew20b126@technikum-wien.at>
//
// [To overview](../).
//
// [The whole source file `u8_palindrome.c`.](./u8_palindrome.c)
//
// [`man ascii` ftw](https://man7.org/linux/man-pages/man7/ascii.7.html)

/* Compile with `clang -std=c99 -Wall -o u8_palindrome u8_palindrome.c` */
/* Test with `../checkproject u8_palindrome` */

// Include C-libraries for input/output.
#include <stdio.h>
#include <stdlib.h>

// Exercise 8: Exercise strings, palindrome
// ========================================
//
// Read a string and find out whether it is a palindrome.
//
// ## Detailed exercise
// A palindrome is a word or a sentence which reads the same backward and
// forward. Read a line with at most 80 characters (if it is longer, use the
// first 80 characters). Please, do not use helper functions of the string
// library! This is to make sure that you completely understand how strings
//  are represented in C and how to handle them.
//
// ### Hints
// * To read the line, use fgets with the appropriate arguments.
// * To find out whether a character is a lower case letter, remember that
//   characters are numbers and therefore, comparisons like ch >= 'A' are
//   possible.
// * To convert lower case letters to upper case letters subtract 32
//   (see ASCII table).
// * You can use a loop with a left and a right index and make sure to step
//   over symbols like commas and dots.
// * You can save a lot of time by implementing some procedures, for instance
//   to check whether a character is a letter or a symbol.
//
// ### Example 1
// Input:
// ```
// This is not a palindrome!
// ```
// Output:
// ```
// not a palindrome
// ```
// ### Example 2
// Input:
// ```
// A man, a plan, a canal, Panama!
// ```
// Output:
// ```
// palindrome
// ```
// ### Example 3
// Comment: Empty lines or lines only containing one letter are considered to
// be palindromes.
// Input:
// ```
// !
// ```
// Output:
// ```
// palindrome
// ```

// ## Constants
// `#define` makes a C pre-processor constant. The compiler will replace all
// occurrences of this name with the value.
#define MAX_CHARS_WITH_NUL 81

// ## main()
int main() {
    // `calloc` is like `malloc`, but initializes the memory to all 0s, so we
    // always have a NUL-terminated string.
    //
    // Alternatively, one could use
    // ```
    // char buffer[MAX_CHARS_WITH_NUL] = {0};
    // ```
    // But that is CS2 material ;)
    char *buffer = calloc(MAX_CHARS_WITH_NUL, sizeof(char));
    char c;
    int length = 0;

    // Read until newline or max length. `getchar` only reads a single byte.
    while ((c = getchar()) != '\n' && length < MAX_CHARS_WITH_NUL) {
        // Read only a-z, A-Z. Because characters are just numbers, we can
        // compare them with greater than and less than no problem.
        if ((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z')) {
            // Lowercase by adding 32.
            if ((c >= 'A' && c <= 'Z')) {
                c += 32;
            }

            // Store the character in the buffer.
            buffer[length] = c;
            length += 1;
        }
    }

    // By default we have a palindrome (empty input).
    int is_palindrome = 1;

    // Iterate through half the indices (until the middle), and look from
    // the front and the back if there is the same character.
    for (int j = 0; j <= length / 2; j++) {
        if (buffer[j] != buffer[length - j - 1]) {
            is_palindrome = 0;
            break;
        }
    }

    // Print the result.
    if (is_palindrome) {
        printf("not a palindrome\n");
    } else {
        printf("palindrome\n");
    }

    // Don't forget to free the allocated buffer.
    free(buffer);

    // Return code 0 for everything OK.
    return 0;
}
