DEV Community

Matheus 🇧🇷
Matheus 🇧🇷

Posted on

CS50: S2 | Readability e a Complexidade Textual

Introdução

Esse exercício visa utilizar o readability como medida de complexidade textual. Um exemplo de aplicativo do dia a dia que utiliza um sistema de readability para dizer se o seu texto está fácil de ser compreendido ou não, é o Hemingway Editor. Eles utilizam algum algoritmo que analisa quantos advérbios, se faz uso ou não da voz passiva e por aí vai.

Nesta atividade será algo bem mais simples, iremos analisar a quantidade de letras, palavras e sentenças, assim conseguiremos utilizar o index de Coleman-Liau projetado exatamente para a lingua inglesa, para descobrir a complexidade do texto.

A fórmula utilizada é: index = 0.0588 * L - 0.296 * S - 15.8

Sem mais delongas, vamos começar o exercicio.

Quebrando o código

  • Headers utilizados
#include <cs50.h>
#include <stdio.h>
#include <string.h>
#include <math.h>
Enter fullscreen mode Exit fullscreen mode
  • Prototipos declarados
int numberOfLetters(string text);
int numberOfWords(string text);
int numberOfSentences(string text);

float indexL(int letters, int words);
float indexS(int sentences, int words);
float colemanLiau(float L, float S);

void showGrade(float index);
Enter fullscreen mode Exit fullscreen mode
  • função Main
int main(void)
{
    string text = get_string("Text: ");
    int number_of_letters = numberOfLetters(text);
    int number_of_words = numberOfWords(text);
    int number_of_sentences = numberOfSentences(text);

    float L = indexL(number_of_letters, number_of_words);
    float S = indexS(number_of_sentences, number_of_words);

    float indexGrade = colemanLiau(L, S);

    showGrade(indexGrade);
}
Enter fullscreen mode Exit fullscreen mode

Gostaria de aproveitar esse ponto para dizer que não existe uma só forma de resolver o problema, e provavelmente você pode ter feito algo completamente diferente do que eu fiz, e está tudo bem.

Contando letras

Na aula 2 vimos que as strings (textos) são arrays de caracteres. E todo essa resolução ela gira em torno desse conceito muito importante!

int numberOfLetters(string text) {
    int counter = 0;
    for(int i = 0; i < strlen(text); i++) {
        if(text[i] >= 'a' && text[i] <= 'z') {
            counter++;
        } else if(text[i] >= 'A' && text[i] <= 'Z') {
            counter++;
        }
    }

    return counter;
}
Enter fullscreen mode Exit fullscreen mode
  • Temos um contador que inicialmente tem valor 0.

Pois nenhuma letra foi contada até agora, durante a sua inicialização.

  • Monta-se a estrutura do loop, mas dessa vez o nosso limitador é strlen().

No Manual do CS50 temos na biblioteca string.h a função strlen.
É por isso que incluimos o string.h no nosso header. Para que possamos ter acesso a função strlen().
E o que ela faz? Ela retorna o tamanho dessa string(texto).

  • Começam as condicionais

Como iremos de letra em letra, utilizando as bracket notations. Caso não se lembre, reveja a parte da aula que fala sobre Arrays.
E iremos comparar se a letra está entre a a z, minúscula, ou A a Z, maiúscula.

  • Caso estejam, adicionará um ao nosso contador e pulará para a próxima letra.

  • Ao final, retorna o valor desse contador.

int number_of_letters = numberOfLetters(text);
Enter fullscreen mode Exit fullscreen mode

Com esse valor retornado, eu armazeno esse valor dentro de uma variável para ser usada mais tarde.

Contando palavras

O conceito é o mesmo de cima, a diferença agora é que farei uso da Tabela ASCII e só irei procurar pelo valor correspondente ao espaço.

int numberOfWords(string text) {
    int counter = 1;
    for(int i = 0; i < strlen(text); i++) {
        if( (int) text[i] == 32) {
            counter++;
        }
    }

    return counter;
}
Enter fullscreen mode Exit fullscreen mode
  • Faço um type casting em relação a letra.

Type Casting é um processo em C onde a gente troca a variável que pertence a um tipo de dado para outro.
Neste caso, estou transformando um tipo de dado char -> int.

ASCII Chart

Então por exemplo:

  • Char: A > Int: 65
  • Char: 0 > Int: 48
  • Char: ! > Int: 33
  • Char: [espaço] > Int: 32

  • O motivo do contador ser UM

Estou partindo do principio que sempre será escrito uma palavra, então sempre terá a primeira palavra colocada, onde eu não terei um marcador pra ser utilizado como referência (um espaço). Então para isso, já considerei que o contador começará com um.

  • Ao final, retorna o valor desse contador.
int number_of_words = numberOfWords(text);
Enter fullscreen mode Exit fullscreen mode

Contando sentenças

int numberOfSentences(string text) {
    int counter = 0;

    for(int i = 0; i < strlen(text); i++) {
        if((int) text[i] == 33 || (int) text[i] == 46 || (int) text[i] == 63) {
            counter++;
        }
    }

    return counter;
}
Enter fullscreen mode Exit fullscreen mode
  • Aqui, valendo-se da mesma regra das palavras

  • Desta vez, os maracadores são: o ponto final, o ponto de exclamação, e a interrogação.

  • Ao final, retorna o valor desse contador

int number_of_sentences = numberOfSentences(text);
Enter fullscreen mode Exit fullscreen mode

E também, como nos dois primeiros, armazenando esses valores em variáveis para serem usados posteriormente.

Indices e o Index Coleman-Liau

index = 0.0588 * L - 0.296 * S - 15.8

As fórmulas utilizadas a seguir, elas seguem o dito pelo enunciado. Agora é aplicar valores.

Calculando L

float indexL(int letters, int words) {
    return letters * 100.0 / words;
}
Enter fullscreen mode Exit fullscreen mode

E utilizando as variáveis onde armazenamos os valores até agora, chamamos essa função assim.

float L = indexL(number_of_letters, number_of_words);
Enter fullscreen mode Exit fullscreen mode

E agora, armazenando esse resultado em uma nova variável

Calculando S

float indexS(int sentences, int words) {
    return sentences * 100.0 / words;
}
Enter fullscreen mode Exit fullscreen mode

O processo é exatamente o mesmo.

float S = indexS(number_of_sentences, number_of_words);
Enter fullscreen mode Exit fullscreen mode

Calculando o index Coleman-Liau

De posse dos valores de L e S, criamos uma nova função:

float colemanLiau(float L, float S) {
    return (0.0588 * L) - (0.296 * S) - 15.8;
}
Enter fullscreen mode Exit fullscreen mode

E aqui, vou armazenar o valor desse float em uma nova variável.

float indexGrade = colemanLiau(L, S);
Enter fullscreen mode Exit fullscreen mode

Exibindo a nota em Tela

De posse dos valor do index, o problema nos pede:

  • Caso o valor seja 1 ou menor, exibir: Before Grade 1
  • Caso o valor seja 16 ou maior, exibir: Grade 16+
  • Caso o valor esteja entre, ser arredondado para o seu inteiro mais próximo.
void showGrade(float index) {
    if(index < 1) {
        printf("Before Grade 1\n");
    } else if (index > 16) {
        printf("Grade 16+\n");
    } else {
        printf("Grade %i\n", (int) round(index));
    }
}
Enter fullscreen mode Exit fullscreen mode

E aqui, fiz o uso da função round(). Essa função, também pode ser encontrada na Docs do cs50. Ela pertence a biblioteca math.h, e também é por isso que adicionamos ao nosso header.

Resultados

image check

E a função com headers, prototipos e a main juntas.

#include <cs50.h>
#include <stdio.h>
#include <string.h>
#include <math.h>

int numberOfLetters(string text);
int numberOfWords(string text);
int numberOfSentences(string text);

float indexL(int letters, int words);
float indexS(int sentences, int words);
float colemanLiau(float L, float S);

void showGrade(float index);

int main(void)
{
    string text = get_string("Text: ");
    int number_of_letters = numberOfLetters(text);
    int number_of_words = numberOfWords(text);
    int number_of_sentences = numberOfSentences(text);

    float L = indexL(number_of_letters, number_of_words);
    float S = indexS(number_of_sentences, number_of_words);

    float indexGrade = colemanLiau(L, S);

    showGrade(indexGrade);
}
Enter fullscreen mode Exit fullscreen mode

Obrigado por ler até aqui, espero que tenha te ajudado.

Estou cobrindo o CS50, semana a semana, e fazendo a resolução de alguns dos exercicios da semana para ajudar quem está começando.

Me siga aqui no dev.to para acompanhar, ou também me siga no twitter para acompanhar quando estou postando ou comentando sobre códigos que estou aprendendo e desenvolvendo.

Te vejo na próxima!

Top comments (1)

Collapse
 
tipimenta profile image
Tiago Pimenta

Muito boa a explicação, me escrevi no dev.to para acompanhar sobre o cs50, estou em python já, pórem achei muito válido preencher algumas dúvidas que ficaram e absorver mais sobre o conteúdo.