授業「コンピュータ演習」の2023年,年初めの練習問題。2023年1月13日は金曜日。これを記念したスペシャル問題の解答例。
Python の calendar
を使う
calendar
を import して,月のカレンダーを出力します。
import calendar
# 2023年1月の月カレンダーを出力
calendar.prmonth(2023, 1)
# ヨーロッパの慣習に従い,月曜日始まり
Python の locale
で曜日を日本語に
既定では,英語表記で週のはじまりが月曜日(Mo)になっています。これを日本語表記にし,週のはじまりを日曜日にするには,以下のようにします。(曜日が日本語表示になると,レイアウトが崩れてしまいます。)
import locale
# locale を日本語に設定。これ以後は日本語表示に。
locale.setlocale(locale.LC_TIME, 'ja_JP.UTF-8')
# locale を 日本語に設定した後の「曜日」
print(calendar.day_abbr[:])
# 週の始まりを日曜日に
calendar.setfirstweekday(calendar.SUNDAY)
calendar.prmonth(2023, 1)
# レイアウトが崩れる...
# 曜日表示の間のスペースが1個多い...
参考: %%bash
で cal
コマンド
弘大 JupyterHub は Linux ですから,JupyterHub のホームの「新規」から「端末」を選ぶと,bash のプロンプトに続いてコマンドを打ち込むことができます。
わざわざ「新規」から「端末」を選ばなくても,Python のノートブックであれば,以下のように「セル」の1行目に %%bash
と書いたあとにコマンドを入力して「▶︎ Run」(Shift Enter)すると,結果が表示されます。こちらは,日本語表示でもレイアウトの崩れはありません。
%%bash
# 2023 年 1 月のカレンダーを表示する
cal 1 2023
%%bash
# 2023 年の年間カレンダーを表示する
cal 2023
Python の datetime
を使う
日付や曜日を扱う datetime
を import して,曜日を調べてみます。
import datetime as dt
問題 1
2023年の1月から12月までの13日の曜日を全て表示せよ。
year = 2023
day = 13
for month in range(1, 13):
date = dt.date(year, month, day)
youbi = calendar.day_abbr[date.weekday()]
print('%4d年%2d月%2d日は %s曜日' % (year, month, day, youbi))
問題 2
2023年の1月から12月まで,13日が金曜日である月のみを表示せよ。
year = 2023
day = 13
print('%2d日が 金曜日なのは' % day)
for month in range(1, 13):
date = dt.date(year, month, day)
youbi = calendar.day_abbr[date.weekday()]
if youbi == '金':
print(' %4d年%2d月' % (year, month))
問題 3
2023年から2122年までの100年間に,13日の金曜日は1年あたり平均何回あるか。
year0 = 2023
day = 13
count = 0
print('%2d日が金曜日なのは' % day, end='')
for year in range(year0, year0+100):
# 年ごとに改行
print('')
for month in range(1, 13):
date = dt.date(year, month, day)
youbi = calendar.day_abbr[date.weekday()]
if youbi == '金':
# 同一年は改行せずに横並びで表示
print(' %4d年%2d月' % (year, month), end='')
count += 1
print('')
print('')
print('100年間で %3d回,年平均 %.2f回' % (count, count/100))
問題 4
13日の金曜日は1年に必ず1回以上あることを示せ。
ヒント:2023年のように,1月1日が日曜日の場合は,1月13日が金曜日となる。では,1月1日が他の曜日の場合はどうなるか。残りの曜日の場合を調べればよいことになる。
例えば,1月1日が月曜日なら,各月末までの日数の和を7で割った余りが6なら,次の月初めが日曜日ということになる。
# 閏年でない場合
# 各月の日数
mdays = [[1, 31], [2, 28], [3, 31], [4, 30], [5, 31], [6, 30],
[7, 31], [8, 31], [9, 30], [10,31], [11,30], [12,31]]
print('閏年でない場合')
for weekday in range(7):
print(' 1月1日が「%s」曜日なら... ' % calendar.day_abbr[weekday], end=' ')
if (calendar.day_abbr[weekday]) == '日':
print(' 1月1日が日曜日', end=' ')
tmp = 0
for i in range(11):
tmp += mdays[i][1]
if tmp % 7 == 6 - weekday:
print('%2d月1日が日曜日' % mdays[i+1][0], end=' ')
print('')
print('')
# 閏年の場合
# 各月の日数
mdays = [[1, 31], [2, 29], [3, 31], [4, 30], [5, 31], [6, 30],
[7, 31], [8, 31], [9, 30], [10,31], [11,30], [12,31]]
print('閏年の場合')
for weekday in range(7):
print(' 1月1日が「%s」曜日なら... ' % calendar.day_abbr[weekday], end=' ')
if (calendar.day_abbr[weekday]) == '日':
print(' 1月1日が日曜日', end=' ')
tmp = 0
for i in range(11):
tmp += mdays[i][1]
if tmp % 7 == 6 - weekday:
print('%2d月1日が日曜日' % mdays[i+1][0], end=' ')
print('')
print('')
print('したがって,閏年か否かにかかわらず')
print('1月1日が日〜土のいかなる曜日で始まっても')
print('その年には必ず1回以上,月初めの1日(ついたち)が日曜日となる月があり,')
print('その月の13日が金曜日となる。')
問題 5
13日の金曜日が1年に3回あるのはどんな条件の年か。
解答:
閏年ではなくて,1月1日が「木曜日」の場合,2月13日,3月13日,11月13日の3回。
または閏年であって,1月1日が「日曜日」の場合,1月13日,4月13日,7月13日の3回。
ついでに言えば,13日の金曜日は1年に4回以上はないこともわかる。