# Words by the Numbers 7, Exercise 3 import pathlib, re, statistics, urllib.request BOOKS = {"Alice in Wonderland": 11, "The Time Machine": 35, "Pride and Prejudice": 1342, "The Federalist Papers": 1404} def load(number): path = pathlib.Path(f"pg{number}.txt") if not path.exists(): url = f"https://www.gutenberg.org/cache/epub/{number}/pg{number}.txt" req = urllib.request.Request(url, headers={"User-Agent": "Mozilla/5.0"}) path.write_bytes(urllib.request.urlopen(req).read()) raw = path.read_text(encoding="utf-8-sig").replace("\r", "") start = raw.index("\n", raw.index("*** START OF")) + 1 return raw[start:raw.index("*** END OF")] def syllables(word): w = re.sub(r"[^a-z]", "", word.lower()) if not w: return 0 n = len(re.findall(r"[aeiouy]+", w)) if w.endswith("e") and not w.endswith("le") and n > 1: n -= 1 if w.endswith("ed") and not w.endswith(("ted", "ded")) and n > 1: n -= 1 return max(n, 1) def grade(text): for fancy, plain in (("\u2019", "'"), ("\u201c", '"'), ("\u201d", '"')): text = text.replace(fancy, plain) text = re.sub(r"\s+", " ", text) sentences = [s for s in re.split(r"(?<=[.!?])[\"')\]]*\s+", text.strip()) if s] words = re.findall(r"[A-Za-z]+(?:'[A-Za-z]+)?", text) syl = sum(syllables(w) for w in words) return 0.39 * len(words) / len(sentences) + 11.8 * syl / len(words) - 15.59 SIZE = 1000 print(f"{'book':22} {'chunks':>6} {'mean':>6} {'sd':>5} {'min':>6} {'max':>6} share above grade 10") for title, number in BOOKS.items(): words = load(number).split() chunks = [" ".join(words[i:i + SIZE]) for i in range(0, len(words) - SIZE, SIZE)] g = [grade(c) for c in chunks] share = sum(x > 10 for x in g) / len(g) print(f"{title:22} {len(g):6d} {statistics.mean(g):6.1f} {statistics.stdev(g):5.1f} {min(g):6.1f} {max(g):6.1f} {share:5.0%}") # Output when run (Python 3.14; texts from the Project Gutenberg plain-text files): # book chunks mean sd min max share above grade 10 # Alice in Wonderland 26 6.1 1.8 3.6 12.1 4% # The Time Machine 32 7.6 1.6 4.4 10.9 9% # Pride and Prejudice 127 8.6 2.1 4.5 15.7 24% # The Federalist Papers 192 16.1 2.0 10.9 23.3 100%