Leap Year
グレゴリオ暦の年 year が与えられます。2月29日があるうるう年なら true を、そうでなければ false を返してください。
年が 4 で割り切れる場合はうるう年ですが、100 で割り切れる年はうるう年ではありません。ただし、400 でも割り切れる場合はうるう年です。
関数
- yearinteger
- 確認する年
- 戻り値boolean
- その年に2月29日がある場合は true、それ以外の場合は false
制約
1 ≤ year ≤ 106
例
- 入力
- year = 2024
- 出力
- true
- 説明
2024は4で割り切れ、世紀年ではないため、うるう年です。
- 入力
- year = 1900
- 出力
- false
- 説明
1900は4で割り切れますが、100でも割り切れ、400では割り切れないため、世紀の例外が適用され、うるう年ではありません。
- 入力
- year = 2000
- 出力
- true
- 説明
2000は100で割り切れるため、通常なら閏年ではありませんが、400でも割り切れるため、閏年になります。
提出時に隠しテスト+16件
ヒント
1つずつ開いてください。開くたびに少しずつ答えに近づきます。
4で割った後の余りが0であることが最初のルールです。これに当てはまらない年はどれですか?世紀年はこの規則を破り、さらに
400の倍数は世紀年の規則を破ります。400の倍数はすべて100と4の倍数でもあるため、チェックする順序によって答えが決まります。まず
400で割り切れるか確認し、次に100、その次に4で割り切れるか確認して、最初に当てはまったルールで判定します。または、条件を組み合わせて、4で割り切れて100では割り切れない、または400で割り切れるとします。
解説
各ルールで必要な余りは1つだけなので、行うのは3回の割り切れるかどうかの確認です。注意すべきなのは順序です。これらのルールは、世紀であり、かつ400の倍数でもある2000のような年では互いに矛盾します。最も具体的なルールを先に確認するか、例外が適切に処理されるように括弧を付けて、1つの式でルールを書きましょう。
最も具体的なルールから最も具体性の低いルールへと確認してください
考え方
この3つのルールは、例外が連鎖しています。4で割り切れると閏年になり、100で割り切れるとその判定が取り消され、400で割り切れると取り消しがさらに取り消されます。後のルールに当てはまる年は、必ずそれより前のルールにも当てはまります。400の倍数はすべて100の倍数であり、100の倍数はすべて4の倍数だからです。
したがって、当てはまる中で最も具体的なルールによって答えが決まります。まず400を調べ、次に100、その次に4を調べ、いずれかに当てはまったらすぐに結果を返します。2000の場合、最初の判定ですでに「はい」となります。1900の場合、最初の判定は失敗し、2番目の判定は「いいえ」となります。2024の場合、最初の2つの判定は失敗し、3番目の判定は「はい」となります。
3つのどれにも当てはまらない場合、その年はそもそも4で割り切れないため、平年です。
アルゴリズム
year % 400 == 0の場合、trueを返します。year % 100 == 0の場合、falseを返します。year % 4 == 0の場合、trueを返します。- それ以外の場合は
falseを返します。
def isLeapYear(year):
if year % 400 == 0:
return True
if year % 100 == 0:
return False
if year % 4 == 0:
return True
return False1つのブール式
考え方
この規則は、うるう年となる2つの条件として読みます。年が4で割り切れ、かつ世紀年でないか、または400で割り切れるかのどちらかです。この文をそのままコードにすると、(year % 4 == 0 and year % 100 != 0) or year % 400 == 0となります。
3つの例で確認しましょう。2024は前半の条件を満たします。1900は世紀年なので前半の条件を満たさず、1900 % 400が300なので後半の条件も満たしません。2000は1900と同じ理由で前半の条件を満たさず、後半の条件を満たします。
別のまとめ方もできます。4で割り切れ、かつ世紀年ではないか、または400の倍数である、という形です。どちらの形でも、すべての年について結果は同じです。この式で行う判定は、多くてもif文の連鎖と同じ3回です。
アルゴリズム
year % 4 == 0 and year % 100 != 0を計算します。4で割り切れ、かつ世紀年ではありません。year % 400 == 0を計算します。- どちらか一方が成り立つ場合は
trueを返します。
def isLeapYear(year):
# Every 4th year, except centuries, except every 400th year.
return (year % 4 == 0 and year % 100 != 0) or year % 400 == 0
落とし穴と境界ケース
ここでの間違いはすべて、この規則を例外の連鎖ではなく、1つの判定として扱うことから生じています。
year % 4 == 0だけを確認する。1901から2099までのすべての年では正しい答えになるため、バグが見つかりにくくなりますが、1900と2100では間違った答えになります。- ifの連鎖で
400より先に100を判定する。世紀の判定は、400の判定が実行される前に、2000に対してfalseを返します。 - 4で割り切れるという条件を省く。
year % 100 != 0 or year % 400 == 0は、2023をうるう年と判定します。これは、2023が世紀ではないためです。 - 余りを求めるつもりで
year / 4を使う。割り算でわかるのは4が何回入るかであり、余りでわかるのは割り切れるかどうかです。
よくある質問4
うるう年の規則は何ですか?
グレゴリオ暦では、4で割り切れる年はうるう年ですが、100で割り切れる場合は除きます。ただし、400で割り切れる年はうるう年です。そのため、2024と2000はうるう年ですが、1900と2100はうるう年ではありません。
なぜ1900年はうるう年ではないのに、2000年はうるう年なのでしょうか?
どちらも、100で割り切れる世紀の年で、通常はうるう年ではありません。2000は400でも割り切れるため、その規則が世紀の年に関する規則より優先されます。1900を400で割ると余りが300となるため、平年のままです。
世紀のルールはなぜ存在するのでしょうか?
太陽年は約365.2422日です。4年ごとに1日を追加すると平均は365.25となり、400年ごとに約3日多くなります。400年のうち3回、世紀年のうるう日を省くことで、その3日分を取り除きます。平均は365.2425日となり、何千年もの間、季節と暦を十分に一致させておくことができます。
うるう年かどうかを判定する時間計算量はどれくらいですか?
時間計算量と空間計算量は O(1) です。年の大きさにかかわらず、判定に必要なのは、最大で3回の剰余演算と数回の比較です。
似た問題
同じ考え方を使う問題です。2〜3問解くとパターンが身につきます。
Python
def isLeapYear(year):
# ここにコードを書いてくださいケース1
ケース2
ケース3
入力
year = 2024
期待値
true