Readability

以下のテキストを理解するために必要なおおよそのグレード (等級レベル) を計算するプログラムを実装します。

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

読解レベル

Scholasticによると、E.B.Whiteの 「Charlotte’s Web」 は2年生から4年生の読解力レベルで、Lois Lowryの 「The Giver」 は8年生から12年生 (中学2年~高校3年) の読解力レベルだそうです。しかし、本が 「4年生読解レベル」とはどういうことでしょうか。

多くの場合、人間の専門家が本を読んで、その本が最適だと思う学年を決めるでしょう。ですが、テキストの読解レベルを計算しようとするアルゴリズムも想像できるでしょう。

では、高い読解力レベルにはどのような特徴があるのでしょうか。長い単語は高い読解力レベルと相関しています。同様に、長い文章は高い読解力レベルとも相関しています。テキストの読解レベルを計算するための数式処理を提供するために、多くの 「可読性テスト」 が長年にわたって開発されてきました。

そのような可読性試験の1つがColeman-Liau指数です。テキストのColeman-Liau指数は、テキストを理解するために必要な (米国) グレードを出力するように設計されています。式は次のとおりです。

index = 0.0588 * L - 0.296 * S - 15.8

ここで、L は100語あたりの平均字数、Sは100語あたりの平均文数です。

readabilityというプログラムを作成します。このプログラムは、テキストを受け取り、その読解レベルを決定します。たとえば、ユーザがDr.Seussの次の文章を入力したとします。

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

ユーザが入力したテキストは、65文字、4文、14語です。65文字/14語は、平均で約464.29字/100語です。14語当たり4文というのは100語当たり平均約28.57文ということです。Coleman-Liau公式にあてはめ、最も近い整数に丸めた結果、3という答えが得られます。つまり、この文章は3年生の読解レベルです。

別の文章でも試してみましょう。

$ ./readability
Text: Harry Potter was a highly unusual boy in many ways. For one thing, he hated the summer holidays more than any other time of year. For another, he really wanted to do his homework, but was forced to do it in secret, in the dead of the night. And he also happened to be a wizard.
Grade 5

この文章は214文字、4文、56単語からなります。100語に382.14文字、100語に7.14文という計算になります。Coleman-Liau式にあてはめると、5年生の読解力レベルとなります。

1文あたりの平均文字数と単語数が増加すると、Coleman-Liauインデックスによってテキストの読み取りレベルが高くなります。たとえば、前の2つの例よりも長い単語や文を含むこの段落を採用すると、式はテキストに読解力レベル11を与えます。

$ ./readability
Text: As the average number of letters and words per sentence increases, the Coleman-Liau index gives the text a higher reading level. If you were to take this paragraph, for instance, which has longer words and sentences than either of the prior two examples, the formula would give the text an eleventh grade reading level.
Grade 11

試してみましょう

スタッフの回答を確かめるには、このサンドボックスで以下を実行します。

./readability

仕様

テキストのColeman-Liauインデックスを計算するプログラムreadabilityを設計して実装します。

  • readabilityというディレクトリにあるreadability.cというファイルにプログラムを実装します。
  • プログラムでは、 (get_stringを使用して) ユーザにテキスト文字列の入力を求めるプロンプトを表示する必要があります。
  • プログラムは、テキスト内の文字、単語、および文の数をカウントする必要があります。文字は、aからzまでの任意の小文字またはAからZまでの任意の大文字であり、スペースで区切られた任意の文字列は単語としてカウントされ、ピリオド、感嘆符、または疑問符が出現すると文の終わりを示します。
  • プログラムは、出力 "Grade X" として出力する必要があります。ここで、XはColeman-Liau式によって計算され、最も近い整数に丸められたグレードです。
  • 作成されたインデックス番号が16以上 (大学4年生以上) の場合は"Grade 16+"と出力され、正確なインデックス番号は出力されません。インデックス番号が1より小さい場合、プログラムは "Before Grade 1" を出力します。

ユーザ入力の取得

まず、ユーザからテキスト入力を受け取り、それを出力するCコードを作成します。具体的には、readability.cにコードを記述して、ユーザがプログラムを実行したときに、テキストの入力を求める "Text: " プロンプトが表示されるようにします。

結果のプログラムの動作は次のようになります。

$ ./readability
Text: In my younger and more vulnerable years my father gave me some advice that I've been turning over in my mind ever since.
In my younger and more vulnerable years my father gave me some advice that I've been turning over in my mind ever since.

文字

ユーザからの入力を収集したので、まずテキストに表示される文字数を数えて、入力の分析を開始します。readability.cを変更して、原文のテキスト自体を出力するのではなく、テキストの文字数を出力するようにします。

結果のプログラムの動作は次のようになります。

$ ./readability
Text: Alice was beginning to get very tired of sitting by her sister on the bank, and of having nothing to do: once or twice she had peeped into the book her sister was reading, but it had no pictures or conversations in it, "and what is the use of a book," thought Alice "without pictures or conversation?"
235 letter(s)

文字は大文字でも小文字でもかまいませんが、句読点、数字、その他の記号は文字数に含めないでください。

ここで役立つ標準ライブラリ関数については、https://man.cs50.io/を参照してください。また、count_lettersのような別の関数を作成すると、コードを整理しておくのに便利です。

単語

Coleman-Liau指数は、文字数だけでなく、文の中の単語数も考慮します。この問題を解決するために、スペースで区切られた任意の文字列を単語と見なします (したがって、「sister-in-law (義理の姉)」のようなハイフネーションされた単語は、3ではなく1つの単語と見なされます)。

readability.cを変更して、テキストの文字数だけでなく、テキスト内の単語数も出力するようにします。

Brianのウォークスルービデオはこの仕様が修正される前に記録されたもので、文がスペースで始まったり終わったりすることはなく、また文が連続して複数のスペースを持つことはないと考えて構いません。

結果のプログラムの動作は次のようになります。

$ ./readability
Text: It was a bright cold day in April, and the clocks were striking thirteen. Winston Smith, his chin nuzzled into his breast in an effort to escape the vile wind, slipped quickly through the glass doors of Victory Mansions, though not quickly enough to prevent a swirl of gritty dust from entering along with him.
250 letter(s)
55 word(s)

文章

Coleman-Liau式が考慮する最後の情報は、文字と単語の数に加えて、文の数です。文の数を決めるのは驚くほど難しいです。最初に、文はピリオドで終わる任意の文字列であると考えるかもしれませんが、もちろん、感嘆符や疑問符で終わることもできます。もちろん、すべてのピリオドが文の終わりを意味するわけではありません。例えば、次の文を考えてみてください。

Mr. and Mrs. Dursley, of number four Privet Drive, were proud to say that they were perfectly normal, thank you very much.

これはただ一つの文ですが、3つのピリオドがあります!この問題では、この微妙な違いは無視してください。つまり、.や ! や ? で終わるすべての文字の並びを文とみなすべきです (ですから、上記の「文」は、3 つの文とみなしても構いません)。実際には、このようなケースを扱うためには文の境界検出をもう少し賢くする必要がありますが、今はその心配はしません。

readability.cを修正して、テキスト中の文章の数も出力するようにします。

できあがったプログラムの動作は以下のようになるはずです。

$ ./readability
Text: When he was nearly thirteen, my brother Jem got his arm badly broken at the elbow. When it healed, and Jem's fears of never being able to play football were assuaged, he was seldom self-conscious about his injury. His left arm was somewhat shorter than his right; when he stood or walked, the back of his hand was at right angles to his body, his thumb parallel to his thigh.
295 letter(s)
70 word(s)
3 sentence(s)

まとめ

すべての情報をまとめます。Coleman-Liau指数は次の式を使用して計算されることを思い出してください。

index = 0.0588 * L - 0.296 * S - 15.8

ここで、Lは100語あたりの平均文字数、Sは100語あたりの平均文章数です。

readability.cを変更して、文字数、単語数、および文章数を出力するのではなく、Coleman-Liauインデックスで指定された等級レベルを出力するようにします (例: "Grade 2"または"Grade 8"など)。結果のインデックス番号は、必ず最も近い整数に丸めてください。

計算された指数が16以上の場合は"Grade 16+"と出力され、正確なインデックス番号は出力されません。インデックス番号が1より小さい場合、プログラムは"Before Grade 1"を出力します。

ヒント

  • math.hroundという関数を宣言していますが、これはここでは便利かもしれません。
  • Cでint型の値を割ると、結果もintになり、余り (小数点以下の桁数) は破棄されることを思い出してください。つまり、結果は 「切り捨て」 されます。LSの計算時に除算を実行する前に、1つ以上の値をfloatにキャストすることができます。

ウォークスルー

コードのテスト方法

次のテキストでプログラムを実行してみてください。

  • One fish. Two fish. Red fish. Blue fish. (Before Grade 1)
  • Would you like them here or there? I would not like them here or there. I would not like them anywhere. (Grade 2)
  • Congratulations! Today is your day. You're off to Great Places! You're off and away! (Grade 3)
  • Harry Potter was a highly unusual boy in many ways. For one thing, he hated the summer holidays more than any other time of year. For another, he really wanted to do his homework, but was forced to do it in secret, in the dead of the night. And he also happened to be a wizard. (Grade 5)
  • In my younger and more vulnerable years my father gave me some advice that I've been turning over in my mind ever since. (Grade 7)
  • Alice was beginning to get very tired of sitting by her sister on the bank, and of having nothing to do: once or twice she had peeped into the book her sister was reading, but it had no pictures or conversations in it, "and what is the use of a book," thought Alice "without pictures or conversation?" (Grade 8)
  • When he was nearly thirteen, my brother Jem got his arm badly broken at the elbow. When it healed, and Jem's fears of never being able to play football were assuaged, he was seldom self-conscious about his injury. His left arm was somewhat shorter than his right; when he stood or walked, the back of his hand was at right angles to his body, his thumb parallel to his thigh. (Grade 8)
  • There are more things in Heaven and Earth, Horatio, than are dreamt of in your philosophy. (Grade 9)
  • It was a bright cold day in April, and the clocks were striking thirteen. Winston Smith, his chin nuzzled into his breast in an effort to escape the vile wind, slipped quickly through the glass doors of Victory Mansions, though not quickly enough to prevent a swirl of gritty dust from entering along with him. (Grade 10)
  • A large class of computational problems involve the determination of properties of graphs, digraphs, integers, arrays of integers, finite families of finite sets, boolean formulas and elements of other countable domains. (Grade 16+)

check50を使用して以下を実行し、コードの正確さを評価してください。ただし、コンパイルとテストは必ず自分で行ってください。

check50 cs50/problems/2021/x/readability

以下を実行し、style50を使用してコードのスタイルを評価します。

style50 readability.c

提出方法

次のコマンドを実行し、GitHubのユーザ名とパスワードを入力してログインします。セキュリティのため、パスワードには実際の文字ではなくアスタリスク (*) が表示されます。

submit50 cs50/problems/2021/x/readability