1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

月日を「通し日数」に変換して日付差を比較する

1
Posted at

とある問題で「AさんとBさんの予想日、どっちが実際の開花日に近い?」を判定する場面がありました。

私が詰まった点は
“月日 (M/D) のままでは日数差が計算できない” ということでした。
この記事では、月日 → 通し日数(1年の何日目) に変換する最小ロジックと、差分比較の注意点をまとめます。


背景:なぜ「月日」のまま比較できないのか?

例えば、

  • 実際:4/1
  • 予想:3/29

この差は 3日 です。

でも、もし「401 - 329」みたいに 月日を数値として雑に引き算すると、

  • 401 - 329 = 72

となり、当然ズレます。
月が変わると「日付の連続性」が壊れるため、日数差になりません。


解決策:月日を「通し日数」に変換する

月日を 1年の何日目か に変換します。

例:

  • 3/29 → 1月31日 + 2月28日 + 29日 = 88日目
  • 4/1 → 1月31日 + 2月28日 + 3月31日 + 1日 = 91日目

こうして 整数 にできれば、あとは引き算で差が取れます。


実装:serial(通し日数)関数

# [月,日] -> 通し日数(うるう年は無視)
def serial(m, d)
  mdays = [0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31]
  mdays[1...m].sum + d
end

ポイント

  • mdays は各月の日数の表
    • mdays[1] = 31(1月)
    • mdays[2] = 28(2月)…
  • mdays[1...m] は「1月〜(m-1)月」を取り出す
    • ...終端を含まない(m月は含めない)
  • .sum で前月までの日数合計を出し、最後に + d で当月の日を足す

Rubyは メソッドの最後の式が戻り値になるので、return を書かなくても動きます(書いてもOK)。


差の計算は「引いてから abs」が正解

実際の開花日 / A予想 / B予想を通し日数にして比較します。

actual = serial(month, date)
a_day  = serial(a_m, a_d)
b_day  = serial(b_m, b_d)

diff_a = (actual - a_day).abs
diff_b = (actual - b_day).abs

ミス:abs の位置が違う

❌ 間違い

diff_a = actual - a_day.abs

これは「a_day の絶対値」を取っているだけで、
差の絶対値ではありません。
入力値によって期待通りの答えが出ないことで気づけました。

結果、actual < a_day のケースで diff_a が負になり、比較が壊れます。

✅ 正しいのはこれ

diff_a = (actual - a_day).abs

判定(A/B/DRAW)

result =
  if diff_a < diff_b
    "A"
  elsif diff_b < diff_a
    "B"
  else
    "DRAW"
  end

最後に、問題の出力形式どおりに出します。

puts "#{month} #{date}"
puts result

例:DRAW になるケースを確認

  • 実際の開花日:4/1
  • A予想:4/4(差3日)
  • B予想:3/29(差3日)

このときは、

  • diff_a = 3
  • diff_b = 3

なので DRAW になります。


Conclusion

  • 月日をそのまま比較すると、月をまたぐときに日数差が壊れる
  • 解決は「月日 → 通し日数(1年の何日目)」へ変換すること
  • 差分は (actual - predicted).abs の形で、「引いてから abs」が鉄則
  • diff が同じなら DRAW

「日付の近さ」を比べる問題では、この “通し日数化” が最適解でした💯🌸

1
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?