CS50 Probelm set 2 - 독해 난이도 측정

dondonee·2023년 1월 26일
0

CS50

목록 보기
5/12
post-thumbnail

독해 난이도 측정

어떤 책을 이해하기 위해 어느 정도의 취학 정도가 필요한지 알기 위해서, 전문가가 직접 책을 읽고 판단할 수도 있겠지만, 알고리즘을 통해 계산하는 방법도 가능하지 않을까?

그러한 시도로 Coleman-Liau index가 있다. 보통 글은 단어가 길 수록, 문장이 길 수록 어렵다는 점에서 착안해 한 텍스트의 글자, 단어 및 문장 수를 이용하여 공식으로 만든 것이다.

Readability 과제

사용자에게 텍스트를 입력받아 Coleman-Liau index를 계산하여 아래와 같이 출력하는 프로그램을 만든다.

$ ./readability
Text: Congratulations! Today is your day. You're off to Great Places! You're off and away!
Grade 3

지시 사항

  • string 타입으로 유저의 입력을 받는다.
  • 문자는 소문자 혹은 대문자 알파벳이며 마침표, 숫자 등 다른 어떤 기호도 포함하지 않는다.
  • sister-in-law처럼 하이픈으로 연결된 단어는 3개의 단어가 아니라 1개의 단어로 취급한다.
  • 프로그램은 최종적으로 “Grade X”를 출력해야 한다. X는 Coleman-Liau 공식에 따라 계산한 필요 학년이며, 가장 가까운 정수로 변환한 값이다.
  • 만약 인덱스 값이 16 이거나 그보다 큰 경우 “Grade 16+”를 출력하고, 1보다 작은 경우 “Before Grade 1”을 출력한다.

✍️ 풀이

  • 문자수 세기
    • 입력받은 문자열의 첫번째 요소부터 탐색해서 isupper() 또는 islower()가 참인 경우 카운트를 했었다. 그러다 다른 사람의 코드를 보다 isalpha() 함수가 있는 걸 발견해서 변경했다.
  • 단어수 세기
    • 단어는 공백 문자를 카운트했다. 한 공백이지만 공백 문자가 여러 개인 경우가 있을 수 있으므로 공백 직후에 문자가 오는 경우만 카운트했다.
    • 공백 수는 항상 단어 수보다 1개 적기 때문에 단어 카운트 변수를 1로 초기화했다.
  • 문장수 세기
    • 문장수는 마침표, 느낌표, 물음표, 콜론 부호를 카운트했다.
    • Mr. 혹은 Mrs. 처럼 마침표로 끝나지만 문장의 마침표가 아닐 때도 있다. 이것을 판별하기 위해 문장을 끝내는 기호가 있는 경우 직전의 두 글자, 세 글자를 저장하는 변수를 만들고 “Mr” 또는 “Mrs”와 비교해서 둘 다 일치하지 않는 경우만 카운트를 하도록 했다.
int main(void)
{
    // 유저의 입력 받기
    string text = get_string("Text: ");
    int textLen = strlen(text);

    // 문자, 단어, 문장의 수 집계
    float letterCnt = countLetter(text, textLen);
    float wordCnt = countWord(text, textLen);
    int sentenceCnt = countSentence(text, textLen);

    // Coleman-Liau Index 계산
    int nGrade = calculateIndex(letterCnt, wordCnt, sentenceCnt);

    // 결과 출력
    if (nGrade < 1)
    {
        printf("Before Grade 1\n");
    }
    else if (nGrade > 15)
    {
        printf("Grade 16+\n");
    }
    else
    {
        printf("Grade %i\n", nGrade);
    }
}

float countLetter(string text, int length)
{
    int result = 0;
    for (int i = 0; i < length; i++)
    {
        char c = text[i];

        if (isalpha(c))
        {
            result++;
        };
    }

    return result;
}

float countWord(string text, int length)
{
    int result = 1;

    for (int i = 0; i < length; i++)
    {
        char c = text[i];

        if (c == ' ' && isalpha(text[i + 1]))
        {
            result++;
        }
    }

    return result;
}

float countSentence(string text, int length)
{
    int result = 0;

    for (int i = 0; i < length; i++)
    {
        char c = text[i];

        if (c == '.' || c == '!' || c == '?' || c == ':')
        {
            char str1[2];
            char str2[3];
            strncpy(str1, &text[i - 2], 2);
            strncpy(str2, &text[i - 3], 3);

            if (strncmp(str1, "Mr", 2) != 0 && strncmp(str2, "Mrs", 3) != 0)
            {
                result++;
            }
        }
    }

    return result;
}

int calculateIndex (float letter, float word, float sentence)
{
    float L = letter / word * 100.00;
    float S = sentence / word * 100.00;
    int result = round(0.0588 * L - 0.296 * S - 15.8);

    return result;
}

메모

배운 것

  • 조건문에서 비교 연산자는 생략 가능하기도 하다.
    • if (isalpha(c))와 같은 경우에는 생략하는 것이 더 깔끔해 보이는 것 같다.
  • 추상화를 하면 수정이 편하다.
    • 처음에는 그냥 쭉 코드를 작성했는데 수정할 때 너무 번거로웠다. 처음부터 분리하는게 편할 것 같다.

궁금한 것

  • 가장 고민을 많이 한 부분이 문장 마침표와 Mr.나 Mrs.의 마침표를 구분하는 것이었는데 다른 방법은 어떤게 있을지 궁금하다.

References

과제

0개의 댓글