Readability

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

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

入門

VS Codeを開きます。

ターミナルウィンドウ内をクリックすることから始めて、それからcdを実行します。
その後プロンプトは次のようになっていることがわかります。

$

ターミナルウィンドウの内側をクリックし、次のように入力します。

wget https://cdn.cs50.net/2021/fall/psets/2/readability.zip

その後にEnterを押すと、readability.zipというZIPがあなたのCodespaceにダウンロードされます。wgetと次のURLの間にあるスペースや、その他の文字を見落とさないように注意してください。

次に

unzip readability.zip

を実行して、readabilityというフォルダを作成します。
ZIPファイルは不要になったため、

rm readability.zip

を実行し、プロンプトで “y “に続いてEnterで応答すると、ダウンロードしたZIPファイルが削除されます。

次に

cd readability

の後にEnterを押して、そのディレクトリに移動する(つまり、開く)。これでプロンプトは以下のようになります。

readability/ $

すべて成功した場合は、次のように実行します。

ls

readability.cというファイルが表示されます。code readability.cを実行すると、このProblem setのコードを入力するファイルが開かれるはずです。そうでない場合は、手順をたどって、どこで間違ったのかを判断してください。

背景

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単語です。14単語あたり65文字は、100単語あたり約464.29文字の平均値です(65 / 14 * 100 = 464.29だからです)。また、14語あたり4文は、100語あたり約28.57文の平均値である(4 / 14 * 100 = 28.57だから)。Coleman-Liauの式に当てはめると、答えは3(0.0588 * 464.29 – 0.296 * 28.57 – 15.8 = 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つの例よりも単語と文が長いので、この式では12年生の読解レベルとなります。

$ ./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 twelfth-grade reading level.
Grade 12

試してみましょう

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

./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 の main の下に count_letters という関数を追加し、引数としてテキストの文字列を受け取り、そのテキストに含まれる文字の数を int で返します。この関数のプロトタイプもファイルの先頭に追加して、mainがこの関数をどのように呼び出すかを知るようにしてください。プロトタイプは次のようなものであることが多いでしょう。

int count_letters(string text)

そして、この関数を main で呼び出して、テキストそのものを出力する代わりに、テキストに含まれる文字の数を出力するようになります。

これで、プログラムは以下のように動作するはずです。

$ ./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 letters

ヒント

ctype.hで宣言されている関数は、manual.cs50.ioによると、役に立つと思われるものです。もしこれを使うなら、必ずそのヘッダーファイルを自分のコードの先頭にインクルードしてください!

単語

Coleman-Liau 指数は、文字数だけでなく、文中の単語数も気にします。この問題では、スペースで区切られた文字の並びはすべて単語とみなすことにします(したがって、「sister-in-law (義理の姉)」のようなハイフンでつながれた単語は、3つではなく1つの単語とみなすべきです)。

readability.c の main の下に count_words という関数を追加し、引数としてテキストの文字列を受け取り、そのテキストに含まれる単語の数を int で返します。この関数のプロトタイプも必ずファイルの先頭に追加して、main が関数を呼び出す方法をわかるようにしてください。(そのプロトタイプはあなたにお任せします!)。

そして、mainの中でその関数を呼び出して、プログラムがテキスト内の単語数も出力するようにします。

文はスペースで始まったり終わったりしないし、スペースが複数並んだりすることもないと仮定してください。

これで、プログラムは以下のように動作するはずです。

$ ./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 の main の下に count_sentences という名前の関数を追加してください。この関数のプロトタイプもファイルの先頭に追加して、main が関数を呼び出す方法を知るようにしてください。(そのプロトタイプは、またしてもあなたにお任せします!)。

そして、main でその関数を呼び出して、文章中の文の数を表示するようにします。

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

$ ./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"など)。結果のインデックス番号は、必ず最も近い整数に丸めてください。

readability.cを変更して、文字数、単語数、および文章数を出力するのではなく、Coleman-Liauインデックスで指定された等級レベルを出力するようにします (例: "Grade 2"または"Grade 8"など)。。出力される指数の数値は、必ず小数点以下を四捨五入してください。

ヒント

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

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

ウォークスルー

コードのテスト方法

次のテキストでプログラムを実行し、指定された学年が表示されることを確認してください。必ずテキストのみをコピーし、余分なスペースを入れないようにしてください。

  • 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/2022/x/readability

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

style50 readability.c

提出方法

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

submit50 cs50/problems/2022/x/readability