勉強は学んだことをアウトプットすることがとても大切です。
練習問題を解き、Pythonを「知っている」だけではなく「使える」ようになっているか、確かめてみましょう。
レベル1
FizzBuzz
1から100の数字を出力しなさい。ただし、3の倍数は数字の代わりに”Fizz”、5の倍数は数字の代わりに”Buzz”、3と5の倍数は数字の代わりに”FizzBuzz”を出力しなさい。ただし、「3と5の倍数」の条件は「3の倍数」または「5の倍数」よりも優先される。例えば、15は3の倍数であるが、5の倍数でもあるため”Fizz”とは出力せず、”FizzBuzz”と出力することになる。
for i in range(1, 101):
if i % 3 == 0 and i % 5 == 0:
print("FizzBuzz")
elif i % 3 == 0:
print("Fizz")
elif i % 5 == 0:
print("Buzz")
else:
print(i)
for文で1~100のループを作り、それぞれの数字について「3の倍数かつ5の倍数」かどうか、「3の倍数」かどうか、「5の倍数」かどうかを判定しています。
「3の倍数である」ということは、「3で割った余りが0である」ということですので、%演算子を使って判定しましょう。
掛け算九九
for文を使い、次に示す九九の表を出力しなさい。
1 2 3 4 5 6 7 8 9
2 4 6 8 10 12 14 16 18
3 6 9 12 15 18 21 24 27
4 8 12 16 20 24 28 32 36
5 10 15 20 25 30 35 40 45
6 12 18 24 30 36 42 48 54
7 14 21 28 35 42 49 56 63
8 16 24 32 40 48 56 64 72
9 18 27 36 45 54 63 72 81
for x in range(1, 10):
for y in range(1, 10):
print(str(x * y).rjust(3), end="")
print()
for文で二重ループを作り、積を計算しましょう。
print(str(x * y).rjust(3), end="")
の部分は、str関数で整数を文字列に変換し、rjust関数で文字数を3に指定したうえで右寄せにします。
print関数の引数endは出力後の文字を示し、デフォルトでは改行文字となっていますが、今回は改行させたくないため空文字を指定しています。
中央値
3つの整数を入力から受け取り、その中央値を出力しなさい。以下の例では、”1 3 2″を入力として受け取り、その次の行で中央値の”2″を出力している。
$ python3 median.py
1 3 2
2
a, b, c = map(int, input().split())
if b <= a <= c or c <= a <= b:
print(a)
elif a <= b <= c or c <= b <= a:
print(b)
else:
print(c)
Pythonでは、「aがb以上かつcがa以上」という条件は
b <= a <= c
のように続けて書くことができます。これを利用し、「aが中央値の場合」「bが中央値の場合」「それ以外の場合(=cが中央値の場合)」に場合分けして結果を出力しましょう。
レベル2
ファイル名整理
以下の形式のファイル名が改行区切りで20個与えられる。なお、「ゼロ埋め2桁番号」は01~10までの計10個が重複無く存在する。
<ゼロ埋め2桁番号>_<アルファベットからなる文字列>.<"csv"または"txt">
以下の形式で出力せよ。
--- txt files ---
01_<アルファベットからなる文字列>.txt
02_<アルファベットからなる文字列>.txt
03_<アルファベットからなる文字列>.txt
...
09_<アルファベットからなる文字列>.txt
10_<アルファベットからなる文字列>.txt
--- end of txt files ---
--- csv files ---
01_<アルファベットからなる文字列>.csv
02_<アルファベットからなる文字列>.csv
03_<アルファベットからなる文字列>.csv
...
09_<アルファベットからなる文字列>.csv
10_<アルファベットからなる文字列>.csv
--- end of csv files ---
入力例
03_alpha.csv
09_beta.txt
08_gamma.csv
05_delta.txt
01_epsilon.csv
04_zeta.txt
06_eta.csv
08_theta.txt
09_iota.csv
02_kappa.txt
05_lambda.csv
07_mu.txt
02_nu.csv
10_xi.txt
07_omicron.csv
06_pi.txt
10_rho.csv
03_sigma.txt
04_tau.csv
01_upsilon.txt
出力例
--- txt files ---
01_upsilon.txt
02_kappa.txt
03_sigma.txt
04_zeta.txt
05_delta.txt
06_pi.txt
07_mu.txt
08_theta.txt
09_beta.txt
10_xi.txt
--- end of txt files ---
--- csv files ---
01_epsilon.csv
02_nu.csv
03_alpha.csv
04_tau.csv
05_lambda.csv
06_eta.csv
07_omicron.csv
08_gamma.csv
09_iota.csv
10_rho.csv
--- end of csv files ---
files = [input() for _ in range(20)]
txt_files = []
csv_files = []
for filename in files:
if filename.endswith(".txt"):
txt_files.append(filename)
elif filename.endswith(".csv"):
csv_files.append(filename)
txt_files.sort()
csv_files.sort()
print("--- txt files ---")
for filename in txt_files:
print(filename)
print("--- end of txt files ---")
print()
print("--- csv files ---")
for filename in csv_files:
print(filename)
print("--- end of csv files ---")
入力からファイル名を取得し、txt用のリストとcsv用のリストにそれぞれ該当するファイル名を追加しています。
文字列sが特定の文字列tで終わるかどうかは、
s.endswith(t)
で判定することができます。sがtで終わる場合はTrue、終わらない場合はFalseを返します。
その後はリストのsortメソッドでファイル名を昇順にソートし、出力しています。
山手線2駅間の距離
山手線の駅2つを入力で受け取り、内回りの場合の2駅間の距離[m]を求めよ。
入力はスペース区切りとする。
各駅の名称、各駅間の距離は以下のディクショナリを参照すること。キーが駅名、値が内回りにおける直前の駅からの距離[m]である。例えば、御徒町駅から上野駅までの距離は600mである。
stations = {
"神田駅": 1300,
"秋葉原駅": 700,
"御徒町駅": 1000,
"上野駅": 600,
"鶯谷駅": 1100,
"日暮里駅": 1100,
"西日暮里駅": 500,
"田端駅": 800,
"駒込駅": 1600,
"巣鴨駅": 700,
"大塚駅": 1100,
"池袋駅": 1800,
"目白駅": 1200,
"高田馬場駅": 900,
"新大久保駅": 1400,
"新宿駅": 1300,
"代々木駅": 700,
"原宿駅": 1500,
"渋谷駅": 1200,
"恵比寿駅": 1600,
"目黒駅": 1500,
"五反田駅": 1200,
"大崎駅": 900,
"品川駅": 2000,
"高輪ゲートウェイ駅": 900,
"田町駅": 1300,
"浜松町駅": 1500,
"新橋駅": 1200,
"有楽町駅": 1100,
"東京駅": 800
}
入力例
目黒駅 浜松町駅
出力例
7800
# 各駅の名称と、内回りにおける直前の駅からの距離[m]
stations = {
"神田駅": 1300,
"秋葉原駅": 700,
"御徒町駅": 1000,
"上野駅": 600,
"鶯谷駅": 1100,
"日暮里駅": 1100,
"西日暮里駅": 500,
"田端駅": 800,
"駒込駅": 1600,
"巣鴨駅": 700,
"大塚駅": 1100,
"池袋駅": 1800,
"目白駅": 1200,
"高田馬場駅": 900,
"新大久保駅": 1400,
"新宿駅": 1300,
"代々木駅": 700,
"原宿駅": 1500,
"渋谷駅": 1200,
"恵比寿駅": 1600,
"目黒駅": 1500,
"五反田駅": 1200,
"大崎駅": 900,
"品川駅": 2000,
"高輪ゲートウェイ駅": 900,
"田町駅": 1300,
"浜松町駅": 1500,
"新橋駅": 1200,
"有楽町駅": 1100,
"東京駅": 800
}
# 累積和を計算
cumulative_sum = {}
temp_sum = 0
for station_name, distance in stations.items():
temp_sum += distance
cumulative_sum[station_name] = temp_sum
# 入力
station_from, station_to = input().split()
# 出力
ans = cumulative_sum[station_to] - cumulative_sum[station_from]
if ans < 0:
ans += cumulative_sum["東京駅"]
print(ans)
この問題は累積和を使うことでシンプルに解くことができます。
変数cumulative_sumに内回りにおける直前の駅からの距離の累積和、つまり東京駅からの距離を代入することで、その差を計算して駅間の距離を求めることができます。
もし求めた距離ansがマイナスとなった場合は、ansに「-(2駅間の外回りにおける距離)」が入っているため、「山手線一周の距離(=東京駅から東京駅まで一周した距離であるcumulative_sum[“東京駅”])」にansを加えることで、求めたい距離を計算できます。
レベル3
経路の数
ある建物には部屋が10個ある。それぞれ部屋1、部屋2、部屋3、…、部屋10と呼ぶことにする。
それぞれの部屋からは、以下の通り特定の1つ以上の部屋に通路で直接つながっている。例えば、部屋1は部屋2と部屋5の2つの部屋と通路で直接つながっており、行き来ができる。
部屋 | つながっている部屋 |
部屋1 | 部屋2、部屋5 |
部屋2 | 部屋1、部屋6、部屋8 |
部屋3 | 部屋4、部屋7 |
部屋4 | 部屋3、部屋7、部屋10 |
部屋5 | 部屋1、部屋8 |
部屋6 | 部屋2、部屋8、部屋9 |
部屋7 | 部屋3、部屋4 |
部屋8 | 部屋2、部屋5、部屋6 |
部屋9 | 部屋6、部屋10 |
部屋10 | 部屋4、部屋9 |
上記に加え、部屋2と部屋3、部屋6と部屋7、部屋8と部屋9は日本時間で9:00~17:00の間のみ通行ができ、0:00から9:00になる直前、17:00の直後から24:00の間は封鎖されている。(つまり、9:00ちょうどと17:00ちょうど、及びその間は通行が可能である。)
現在の時間を取得し、その時間における部屋1から部屋10までの全経路を出力しなさい。例えば、部屋1→部屋2→部屋6→部屋9→部屋10の経路は以下のように出力する。
1 2 6 9 10
また、最後の行に全経路数を出力しなさい。
ただし、一度通った部屋をもう一度通ることはできないものとする。(例えば、部屋1→部屋2→部屋6→部屋8→部屋2→部屋3→部屋4→部屋10という経路は部屋2を2回通っているため不可であり、1経路としてカウントされない。)
import datetime
# 日本標準時で時刻を取得
JST = datetime.timezone(datetime.timedelta(hours=+9), "JST")
t_now_jst = str(datetime.datetime.now(JST).timetz())
# keyは部屋番後
# valueはkeyの部屋からつながっている部屋のリスト
g = {
1: [2, 5],
2: [1, 6, 8],
3: [4, 7],
4: [3, 7, 10],
5: [1, 8],
6: [2, 8, 9],
7: [3, 4],
8: [2, 5, 6],
9: [6, 10],
10: [4, 9]
}
# 現在時刻が9:00~17:00の間であれば
# 部屋2と部屋3、部屋6と部屋7、部屋8と部屋9をつなぐ
if "09:00:00.000000+09:00" <= t_now_jst <= "17:00:00.000000+09:00":
g[2].append(3)
g[3].append(2)
g[6].append(7)
g[7].append(6)
g[8].append(9)
g[9].append(8)
# 部屋iまでの経路数を求める関数
# visitedは訪問済みの部屋番号のリスト
def calc(i, visited=[]):
if i == 1:
print(*([1] + visited))
return 1
ans = 0
for prev in g[i]:
if not prev in visited:
ans += calc(prev, [i] + visited)
return ans
print(calc(10))
最初に現在時刻(日本時間)を取得し、その次に部屋同士のつながりをディクショナリgで表現します。
部屋iまでの経路数を求める再帰関数calcを定義し、最後に部屋10までの経路数を求めます。