慣習と法律とで,満年齢に違いが現れる日(生年月日と基準日のペア)を求めるプログラムを作りなさい.生年月日と基準日の範囲は,ハードコード(プログラムの中で決め打ち)してよい.
続・満年齢の計算 - わさっき
前のプログラムを修正します.まず
if __FILE__ == $0
の行を
if __FILE__ == $0 and false
として,実行しないようにします*1.そして,以下のコードを追加します.
if __FILE__ == $0 ac = Age.new birth_min = Date.new(1999, 1, 1) birth_max = Date.new(2000, 12, 31) today_min = Date.new(2004, 1, 1) today_max = Date.new(2005, 12, 31) birth_min.upto(birth_max) do |b| today_min.upto(today_max) do |t| ac.birth = b ac.today = t ac.method = Age::METHOD_CONVENTION age_c = ac.calc_age ac.method = Age::METHOD_LAW age_l = ac.calc_age if age_c != age_l puts "birth=#{b}, today=#{t}, age_c=#{age_c}, age_l=#{age_l}" end end end end
生年月日は1999年1月1日から2000年12月31日まで,基準日は2004年1月1日から2005年12月31日まで.閏年とそうでない年を入れました.それで2重ループです.Dateインスタンスに対するuptoは,1日1行カレンダー - わさっきでも使用しました.
実行結果のうち,2月28日近辺を抜き出してみます.
birth=1999-02-28, today=2004-02-27, age_c=4, age_l=5 birth=1999-02-28, today=2005-02-27, age_c=5, age_l=6 birth=1999-03-01, today=2004-02-29, age_c=4, age_l=5 birth=1999-03-01, today=2005-02-28, age_c=5, age_l=6 (略) birth=2000-02-28, today=2004-02-27, age_c=3, age_l=4 birth=2000-02-28, today=2005-02-27, age_c=4, age_l=5 birth=2000-02-29, today=2004-02-28, age_c=3, age_l=4 birth=2000-02-29, today=2005-02-28, age_c=4, age_l=5 birth=2000-03-01, today=2004-02-29, age_c=3, age_l=4 birth=2000-03-01, today=2005-02-28, age_c=4, age_l=5
たぶん合っているはず.
それにしても,すべて求めるのに,3分以上かかりました.(365+366)の2乗は,534361回.ノートPCのファンが回って,途中,不安になりました.
コードを見直してみましょう.そもそも注意しないといけないのは,誕生日近辺です.だから,基準日を,生年月日の4年後と5年後のプラスマイナス何日かのみに限定することにします.生年月日のループは,1999年1月1日から2000年12月31日までで変えません.
上の追加コードの「if __FILE__ == $0」はまた「if __FILE__ == $0 and false」としてから,新たなコードです.
if __FILE__ == $0 ac = Age.new birth_min = Date.new(1999, 1, 1) birth_max = Date.new(2000, 12, 31) birth_min.upto(birth_max) do |b| [4, 5].each do |i| (-3 .. 3).each do |j| ac.birth = b ac.today = b + (365 * i + j) ac.method = Age::METHOD_CONVENTION age_c = ac.calc_age ac.method = Age::METHOD_LAW age_l = ac.calc_age if age_c != age_l puts "birth=#{b}, today=#{ac.today}, age_c=#{age_c}, age_l=#{age_l}" end end end end end
そして実行.今度は4秒ほどで終わりました*2.2月28日の周辺を取り出してみます.
birth=1999-02-28, today=2003-02-27, age_c=3, age_l=4 birth=1999-02-28, today=2004-02-27, age_c=4, age_l=5 birth=1999-03-01, today=2003-02-28, age_c=3, age_l=4 birth=1999-03-01, today=2004-02-29, age_c=4, age_l=5 (略) birth=2000-02-28, today=2004-02-27, age_c=3, age_l=4 birth=2000-02-28, today=2005-02-27, age_c=4, age_l=5 birth=2000-02-29, today=2004-02-28, age_c=3, age_l=4 birth=2000-02-29, today=2005-02-28, age_c=4, age_l=5 birth=2000-03-01, today=2004-02-29, age_c=3, age_l=4 birth=2000-03-01, today=2005-02-28, age_c=4, age_l=5
基準日を「生年月日の4年後近辺と5年後近辺」に変更したので,1999年生まれの出力は,前のと異なっています.しかし2000年生まれの出力は同じですし,この修正版でも,「誕生年が閏年か否か」と「基準年が閏年か否か」であわせて4通りについて,2月28日前後のチェックが行えています.生年月日と基準日はプログラマ(私)の都合で決めたもので,結局のところ,「満年齢に違いが現れる日(生年月日と基準日のペア)を求める」という目的のもとではうまくいっているわけです.