#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#include <string.h>
#include <assert.h>

bool est_lettre(char c)
{
  return ('a' <= c && c <= 'z') || ('A' <= c && c <= 'Z');
}

char lower(char c)
{
  if ('A' <= c && c <= 'Z') return (char) ((int) c + (int) 'a' - (int) 'A');
  else return c;
}

bool palindrome2(char* str)
{
  int n = strlen(str);
  int deb = 0;
  int fin = n-1;
  while (deb < fin)
  {
    // deb < fin ET
    // (<- de 0 à deb exclu, les lettres rencontrées sont les lettres rencontrées de fin exclu à n-1 lues à l'envers
    // et il y avait le même nombre de lettres de chaque côté
    // Autrement dit, str[:deb] + str[fin+1:] limité aux lettres et sans tenir compte de la casse est un palindrome
    // de taille paire dont la gauche est str[:deb] et la droite est str[fin+1:].)
    while (deb < fin && !est_lettre(str[deb]))
    {
      deb += 1;
    }
    // <-> deb <= fin ET
    // (de 0 à deb exclu, les lettres rencontrées sont les lettres rencontrées de fin exclu à n-1 lues à l'envers
    // et il y avait le même nombre de lettres de chaque côté
    // et str[deb] est une lettre OU deb = fin.
    // Autrement dit, str[:deb] + str[fin+1:] limité aux lettres et sans tenir compte de la casse est un palindrome
    // de taille paire dont la gauche est str[:deb] et la droite est str[fin+1:]
    // et str[deb] est une lettre OU deb = fin.)
    while (deb < fin && !est_lettre(str[fin]))
    {
      fin -= 1;
    }
    // <-> deb <= fin et
    // (de 0 à deb exclu, les lettres rencontrées sont les lettres rencontrées de fin exclu à n-1 lues à l'envers
    // et il y avait le même nombre de lettres de chaque côté
    // et str[deb] et str[fin] sont des lettres OU deb = fin.
    // Autrement dit, str[:deb] + str[fin+1:] limité aux lettres et sans tenir compte de la casse est un palindrome
    // de taille paire dont la gauche est str[:deb] et la droite est str[fin+1:]
    // et str[deb] et str[fin] sont des lettres OU deb = fin.)
    if (lower(str[deb]) != lower(str[fin]))
    {
      // <- de 0 à deb inclus, les lettres rencontrées NE sont PAS les lettres rencontrées de fin inclus à n-1 lues à l'envers
      // malgré le fait que les tailles soient les mêmes,
      // donc str ne peut pas être un palindrome
      return false;
      // -> La fonction est correcte dans ce scénario !
    }
    // -> On est déjà partis OU deb <= fin ET
    // (de 0 à deb inclus, les lettres rencontrées sont les lettres rencontrées de fin inclus à n-1 lues à l'envers
    // et il y avait le même nombre de lettres de chaque côté
    // Autrement dit, str[:deb+1] + str[fin:] limité aux lettres et sans tenir compte de la casse est un palindrome
    // de taille paire dont la gauche est str[:deb+1] et la droite est str[fin:].)
    deb += 1;
    fin -= 1;
    // -> deb <= fin + 2 ET
    // (de 0 à deb exclu, les lettres rencontrées sont les lettres rencontrées de fin exclu à n-1 lues à l'envers
    // et il y avait le même nombre de lettres de chaque côté
    // Autrement dit, str[:deb] + str[fin+1:] limité aux lettres et sans tenir compte de la casse est un palindrome
    // de taille paire dont la gauche est str[:deb] et la droite est str[fin+1:].)
  }
  // -> (deb = fin OU (deb = fin+2) OU (deb = fin+1 ET il y a deux lettres identiques à la casse près en deb et en fin)) ET
  // -> de 0 à deb exclu, les lettres rencontrées sont les lettres rencontrées de fin exclu à n-1 lues à l'envers
  // et il y avait le même nombre de lettres de chaque côté
  // Autrement dit, str[:deb] + str[fin+1:] limité aux lettres et sans tenir compte de la casse est un palindrome
  // de taille paire dont la gauche est str[:deb] et la droite est str[fin+1:].
  // Par déduction, str limité aux lettres et sans tenir compte de la casse est un palindrome.
  return true;
  // -> La fonction est correcte dans ce scénario !
}

int main()
{
  if (palindrome2("a2e4t6u8y7u5t3e2a")) printf("Ceci est un palindrome.\n");
  else printf("Ceci n'est pas un palindrome.\n");
}
