課題02-1 単語数の分布#
alice_chapter01.txt は、ルイス・キャロルの「不思議の国のアリス」の第01章のテキストファイルです。
このファイルの単語の頻度を求めてください。
ファイル名は word_freq.py としてください。
なお、ファイル(alice_chapter01.txt)はプログラム中に直接ファイル名を書くのではなく、コマンドライン引数(sys.argv[1])で受け取るようにして下さい
単語の区切りは、スペース、改行としてください。
split 関数では、2つ以上の文字を区切り文字として文字列を分割できませんので、1行ずつ読み込み、スペースで分割してください。
import sys # コマンドライン引数を受け取るためのライブラリ
dic = {} # 単語の出現回数を格納する辞書
with open(sys.argv[1], "r") as f:
# ファイルを1行ずつ読み込む
line = line.strip() # 改行文字を取り除く(strip)。
words = # スペースで分割する。
# 各単語を順番に調べる。
# 単語が辞書にあれば、
# カウントを1増やす。
# なければ、
# 1を代入する。
print(dic)実行結果#
{'Alice': 17, 'was': 42, ...(途中省略)... 'finished': 1, 'off.': 1}ヒント#
発展課題(任意)
発展課題(任意)#
この課題は任意です。提出は必須ではなく、取り組まなくても不利にはなりません。余裕があれば挑戦してください。
英単語の区切りは、スペースだけではなく、コンマやコロン(:)、ピリオド、クォート、括弧などがあります。
それら複数条件での文字列の分割には、正規表現(Regular Expression)を用います(ライブラリ名は re)。
- 複数条件での文字の分割は正規表現(Regular Expression)を使います。
re.split(r"[,:.'\"“()\s\r\n]", line)- 文字列の前に
rを付けると、raw文字として扱われます。
- 文字列の前に
- 正規表現は複雑であり、それだけで1冊の本になるくらいです。
- どのようなものかは補講 正規表現に示しましたので、興味があればそこから始めてください。
ファイル名は word_freq2.py としてください。
import sys # コマンドライン引数を受け取るためのライブラリ
import re # 正規表現を使うためのライブラリ
dic = {} # 単語の出現回数を格納する辞書
with open(sys.argv[1], "r") as f:
# ファイルを1行ずつ読み込む
words = re.split(r"[,:.'\"“()\s\r\n]", line) # 正規表現で区切る
# 各単語を順番に調べる。
# 単語が辞書にあれば、カウントを1増やす。なければ、1を代入する。
print(dic)なお、クォートは種類がいくつかあり、'、"はもちろん、“、‘ などもあります。
'と"は Python で文字列を表現するために用いますので、文字列中で利用する場合は \ でエスケープする必要があります。
“、‘ は "と'と似ていますが、異なる文字です。 Python の文字列を表す文字ではないため、エスケープは不要です。
発展課題の実行結果#
{'Alice': 20, 'was': 43, ...(省略)..., 'toast': 1, 'finished': 1}課題02-2 階乗を計算する関数を作成する#
コマンドライン引数で与えられた数値の階乗を計算する関数 factorial を作成してください。
factorial 関数は、引数 n に対して、n! を計算して返すようにしてください。
n!は、n から 1 までの整数の積を表します。
ファイル名はfactorial.pyとしてください。
import sys
def factorial(n):
# ここに関数を実装してください
pass
for arg in sys.argv[1:]:
n = int(arg)
print(f"{n}! = {factorial(n)}")実行例#
$ python3 factorial.py 2 3 4 5 10
2! = 2
3! = 6
4! = 24
5! = 120
10! = 3628800課題02-3 文字列に含まれる文字の出現頻度を数える関数を作成する#
コマンドライン引数で与えられた文字列それぞれに対して、その文字列に含まれる文字の出現頻度を数えるプログラム char_freq.pyを作成してください。
与えられた文字はすべて小文字に変換して出現頻度を数えるものとします。
ただし、文字の頻度を数える関数 count_charsを作成してください。
strを小文字にします。str.lower()のように、文字列型変数に対して、lower関数を呼び出すと、小文字に変換されます。- 小文字に変換した
strの各文字を順に取り出してcとします。freq[c]が存在しなければfreq[c] = 0とします。freq[c]に 1 を加えます。
import sys
def count_chars(str):
# ここに関数を実装してください
freq = dict()
for c in str.lower():
pass # この行を置き換えて、適切な処理に変更してください。
return freq
for arg in sys.argv[1:]:
print(f"{arg}: {count_chars(arg)}")実行結果#
# ターミナル上でも'や"で囲むとスペース入りの文字列を入力できる。
$ python3 char_freq.py abracadabra 'This is a pen'
abracadabra: {'a': 5, 'b': 2, 'r': 2, 'c': 1, 'd': 1}
This is a pen: {'t': 1, 'h': 1, 'i': 2, 's': 2, ' ': 3, 'a': 1, 'p': 1, 'e': 1, 'n': 1}課題02-4 猛暑日、真夏日、夏日、真冬日、冬日の日数#
weather2000-2023.csv は2000年から2023年の各日の京都の気温です。
気象庁のページからダウンロードしたものを整形しています。
このファイルには、2行目以降に、日付、最高気温、最低気温、平均気温がコンマ区切りで格納されています。
このファイルを読み込み、年毎に猛暑日、真夏日、真冬日、冬日の日数を求めてください。
判定方法は次の通りです(🔗 気象庁のホームページにも記載されています)。
ファイル名は weather_stats.py としてください。
- 猛暑日(extremely hot day)
- 最高気温が35℃以上の日
- 真夏日(hot summer day)
- 最高気温が30℃以上の日
- 夏日(summer day)
- 最高気温が25℃以上の日
- 真冬日(ice day)
- 最高気温が0℃未満の日
- 冬日(frost day)
- 最低気温 が0℃未満の日
これらは互いに排他ではなく、1日が複数に該当することがあります。 例えば最高気温が35℃以上の日は、猛暑日であると同時に真夏日でもあり夏日でもあるので、3つすべてに数えます。 したがって、どの年でも「猛暑日の日数 ≤ 真夏日の日数 ≤ 夏日の日数」となります。 また、境界の値に注意してください。最高気温がちょうど30.0℃の日は真夏日に含めますが、最低気温がちょうど0.0℃の日は冬日には含めません(データにはどちらの日も実際に含まれています)。
なお、2026年4月に気象庁は最高気温が40℃以上の日を 酷暑日 と呼ぶことを決めました(🔗 気象庁の報道発表)。 このデータの期間では京都で40℃に達した日はない(最高は2018年7月19日の39.8℃)ため、本課題では酷暑日は扱いません。
また、データファイルはプログラム中に直接ファイル名を書くのではなく、コマンドライン引数(sys.argv[1])で与えるようにしてください。
import sys
dic = {}
years = set()
with open(sys.argv[1], "r") as f:
f.readline() # 1行目を読み飛ばす。
for line in f.readlines():
(date, max_s, min_s, rests) = line.split(",") # 行をコンマで分割し、それぞれを代入する。
(year, max, min) = (date[:4], float(max_s), float(min_s))
(extremely_hot, hot, summer, ice, frost) = (0, 0, 0, 0, 0)
years.add(year) # 年を集合に追加しておく。
# 猛暑日、真夏日、夏日、真冬日、冬日を判定する。
# 該当するものの extremely_hot, hot, summer, ice, frost をそれぞれ 1 にする(複数該当することがある)。
if year in dic:
# dic[year] からタプルとして、猛暑日、真夏日、夏日、真冬日、冬日、日数を取り出す。
# dic[year] にタプルとして、猛暑日、真夏日、夏日、真冬日、冬日、日数を格納する。
# その際、判定のところで得られた extremely_hot, hot, summer, ice, frost をそれぞれに加算する。
# 日数は1増やす。
else:
dic[year] = (extremely_hot, hot, summer, ice, frost, 1)
for year in sorted(years): # 年を昇順にソートして繰り返す。
(extremely_hot, hot, summer, ice, frost, days) = dic[year]
print(f"{year} 猛暑日 {extremely_hot:>3}, 真夏日 {hot:>3}, 夏日 {summer:>3}, 真冬日 {ice:>2}, 冬日 {frost:>2} ({days:>3}日)")実行結果#
2000 猛暑日 27, 真夏日 88, 夏日 142, 真冬日 0, 冬日 24 (366日)
2001 猛暑日 24, 真夏日 76, 夏日 148, 真冬日 0, 冬日 21 (365日)
2002 猛暑日 23, 真夏日 84, 夏日 148, 真冬日 0, 冬日 11 (365日)
2003 猛暑日 11, 真夏日 61, 夏日 136, 真冬日 0, 冬日 21 (365日)
2004 猛暑日 19, 真夏日 94, 夏日 151, 真冬日 0, 冬日 18 (366日)
2005 猛暑日 17, 真夏日 81, 夏日 146, 真冬日 0, 冬日 30 (365日)
2006 猛暑日 18, 真夏日 71, 夏日 137, 真冬日 0, 冬日 27 (365日)
2007 猛暑日 20, 真夏日 76, 夏日 133, 真冬日 0, 冬日 8 (365日)
2008 猛暑日 21, 真夏日 78, 夏日 147, 真冬日 0, 冬日 17 (366日)
2009 猛暑日 6, 真夏日 69, 夏日 141, 真冬日 0, 冬日 17 (365日)
2010 猛暑日 35, 真夏日 85, 夏日 143, 真冬日 0, 冬日 19 (365日)
2011 猛暑日 17, 真夏日 79, 夏日 131, 真冬日 0, 冬日 31 (365日)
2012 猛暑日 21, 真夏日 79, 夏日 148, 真冬日 0, 冬日 34 (366日)
2013 猛暑日 30, 真夏日 92, 夏日 154, 真冬日 0, 冬日 27 (365日)
2014 猛暑日 13, 真夏日 72, 夏日 151, 真冬日 0, 冬日 23 (365日)
2015 猛暑日 21, 真夏日 68, 夏日 153, 真冬日 0, 冬日 12 (365日)
2016 猛暑日 27, 真夏日 87, 夏日 160, 真冬日 0, 冬日 11 (366日)
2017 猛暑日 18, 真夏日 83, 夏日 144, 真冬日 0, 冬日 15 (365日)
2018 猛暑日 32, 真夏日 75, 夏日 146, 真冬日 0, 冬日 26 (365日)
2019 猛暑日 24, 真夏日 86, 夏日 147, 真冬日 0, 冬日 3 (365日)
2020 猛暑日 26, 真夏日 75, 夏日 152, 真冬日 0, 冬日 2 (366日)
2021 猛暑日 18, 真夏日 77, 夏日 149, 真冬日 0, 冬日 15 (365日)
2022 猛暑日 25, 真夏日 96, 夏日 153, 真冬日 0, 冬日 22 (365日)
2023 猛暑日 43, 真夏日 95, 夏日 156, 真冬日 0, 冬日 14 (365日)