起きたらDMにまた課題教えて下さいって来てたのですが、やっとPythonの課題になったので勉強がてら調べながらやってみました。
課題内容は次の通り。
西暦または和暦+干支?を入力すると、その年の干支を出力せよ
では実装していきましょう。
目次
1.コード
2.必要なこと
入出力は次のようになっています。
入力:西暦or和暦+干支?
出力:干支
ここでめんどくさいのは、入力例が西暦の場合"2000年"、和暦の場合"平成12年"になります。干支は12年周期なので、年を数値化できればすぐに計算できますが、入力がstr型の上に、和暦は西暦に直したほうが計算しやすいです。
そのため、まずは西暦、和暦を数値化します。
また、申年は西暦が12の倍数の年のときになります。
3.西暦を数値化
まずは西暦を数値化します。これは簡単です。
入力は+で区切られているのですが、+以降はいらないので+の前半、後半に分けます。
word = str.split('+') # +前半と後半で分割
そして、"2000年"の年はいらないので消します。
year = year[:-1] # 入力値の末尾の年を削除
pythonのスライス操作ですが、-の値にすると後ろから取ることができます。めっちゃ便利。この場合は、前から最後から2番目までの要素を取得するという意味です。マイナス値を使わないのであれば次のようになります。
year = year[:4] # 入力値の末尾の年を削除
今回は末尾の文字を消すのが目的なので、マイナス値の方がわかりやすいと思います。
私はメインがC++なので、末尾の削除は
string str="2000年";
str.pop_back();
のように書くものだと思ってましたが、pythonではスライス操作ですべてやるようです。スライス操作便利ですしね。
というか、そろそろC++にsplit関数が標準化されませんかね。
話が脱線しましたが、これで"2000年"の"2000"だけを抽出できました。あとは数値化して干支を出力するだけですが、和暦の場合があるので条件分岐させます。
先程のスライス操作で"2000年"は"2000"に、"平成12年"は"平成12"になっているので、文字列がすべて数字かどうかで判別できます。分岐できたら干支を出力して終わりです。
また、干支のリストは申年が12の倍数のときなので、余り0のときに申年になるように、申年から始めています。
if year.isdecimal(): # 入力された値が数値(西暦)の時の処理
print(eto[int(year) % 12])
4.和暦の場合
和暦の場合は西暦に直して同じ処理をする必要があります。
直し方は調べましたが一発でやる方法はないっぽかったので、自力で実装する必要があります。
まず、年号と年を分離させます。
jp = year[:2] # 年号部分の切り出し
yy = year[2:] # 年部分の切り出し
そして、年号の始まりの年(西暦)を変数に入れます。
jp_cal = ["明治", "大正", "昭和", "平成", "令和"] # 明治 1868~1911(1912),大正1912~1925(1926),昭和1926~1988(1989),平成1989~2018,令和2019~
ad = 0 # 和暦->西暦変換した時の西暦を表す変数
# 年号によってadに値を入れていく
if jp == jp_cal[0]:
ad += 1868
elif jp == jp_cal[1]:
ad += 1912
elif jp == jp_cal[2]:
ad += 1926
elif jp == jp_cal[3]:
ad += 1989
elif jp == jp_cal[4]:
ad += 2019
そして、例えば平成1年は平成元年と呼ぶので、年が"元"でなければ年を数値化して変数に足します。
# 元年でないならば、その値-1(元年が1年であるため)をadに足す
if yy != '元':
ad += int(yy)-1
最後に西暦と同じように出力して終わりです。
print(eto[ad % 12])
5.おわりに
pythonのスライス操作が便利すぎてはえーってなってました。書き方がC++ライクなのでもう少しpythonライクに書きたいのですが、なかなか書けません。
和暦を西暦に直すのはなかなかにめんどくさいものだと思いました。今回は明治~令和だったのでいいですが、これが明治以前まで含めるとなると、この書き方をしていてはif文が多くなって可読性が悪くなる上に、書くのがめんどくさいです。いい方法ないかなあと思うのですが、調べてもなかったので、どっかのDBにつないで西暦を返してもらうのが一番早い気がします。