【日付セット】曜日(large2) (paizaランク A 相当) 解答例 – PHP編【paiza】
【日付セット】 > 曜日(large2) (paizaランク A 相当)
※リンク先へ移動する為には「paiza」へのログインが必要です。
「曜日」の最終問題です。前回までは「date()」関数を利用してきましたが、今回の問題では「paiza歴」という実在しない架空の歴が使用されます。その為「date()」関数が使用できず、難易度が一気に上がります。幸いなことに閏年の規則性は一緒なので巨大な数値の対応方法は前回のものを流用できます。
目次
解答例
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 |
<?php $input = explode(" ",trim(fgets(STDIN))); $year = $input[0]; $month = $input[1]; $day = $input[2]; $y4000 = 1440970;//4000年の日数 $counter = 0; $yearcount = 0; while($year > 4000){ $year = $year-4000; $yearcount++; } $counter = $y4000 * $yearcount; $y = 0; $m = 1; $d = 1; while($y != $year || $m != $month || $d !=$day){ $y4 = $y % 4; $y400 = $y % 400; $y100 = $y %100; if($y4 == 0){ $typeyear = 1; } else { $typeyear = 0; } if($y100 == 0){ $typeyear = 0; } if($y400 == 0){ $typeyear = 1; } $d++; $counter++; if($m == 12 && $typeyear == 0){ if($d == 31){ $d = 1; $m++; } } elseif($m == 12 && $typeyear == 1){ if($d == 32){ $d = 1; $m++; } } else { if($d == 31){ $d = 1; $m++; } } if($m == 13){ $m =1; $y++; } } $num = $counter % 7; $array = ["木曜日","金曜日","土曜日","日曜日","月曜日","火曜日","水曜日"]; echo $array[$num]; ?> |
解答方針
「while」によるループ処理によって、与えられた日付が「paiza歴0年1月1日木曜日」から何日後かをカウントします。このカウントを7で割り余りを求めます。この余りの値と曜日配列を対応させて曜日を求めます。
注意点はグレゴリオ暦とは違い、閏年、平年での日数の違いが12月に発生し、その他の月の日数は31日で固定されている点です。この事を加味し、対象年月日に達するまでの日数をカウントするプログラムを作っていきます。
問題データの取得と年月日への分割
|
1 2 3 4 |
$input = explode(" ",trim(fgets(STDIN))); //標準入力によって問題の年月日を取得し、スペース区切りで配列に分割保存 $year = $input[0]; //年の値 $month = $input[1]; //月の値 $day = $input[2]; //日の値 |
大きすぎる年数に対応する為の補正部分
|
1 2 3 4 5 6 7 8 9 10 11 |
$y4000 = 1440970; //4000年の日数 $counter = 0; //日付をカウントする為の変数 $yearcount = 0; //4000年の回数をカウントする関数 while($year > 4000){ $year = $year-4000; //4000年より大きい年数だった場合、4000を引いて変数へ再格納 $yearcount++; //4000年カウンタを一つ上げる } $counter = $y4000 * $yearcount; //補正した分の日数をあらかじめカウンタに入れる |
この値を利用して、大きすぎる年数を補正した時、補正した年数分の日数をあらかじめカウントします。この処理をすることで、結果として後に行うループ処理の負荷が減ることになります。
「paiza歴0年1月1日」から対象年月日までループさせる
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 |
$y = 0; //年数カウンタ $m = 1; //月数カウンタ $d = 1; //日数カウンタ while($y != $year || $m != $month || $d !=$day){ //各カウンタが問題の年月日に達するまで $y4 = $y % 4; //年が4で割り切れるかどうか検証(閏年検証) $y400 = $y % 400; //年が400で割り切れるかどうか検証(閏年検証) $y100 = $y %100; //年が100で割り切れるかどうか検証(平年検証) if($y4 == 0){ $typeyear = 1; //閏年フラグ } else { $typeyear = 0; //平年フラグ } if($y100 == 0){ $typeyear = 0; //平年フラグ } if($y400 == 0){ $typeyear = 1; //閏年フラグ } $d++; //dカウンタを一つ上げる $counter++; //日数カウンタを一つ上げる if($m == 12 && $typeyear == 0){ //平年であり、月数が12ならば if($d == 31){ //日が31ならば $d = 1; //日を1に降り直す $m++; //月を一つ上げる } } elseif($m == 12 && $typeyear == 1){ //閏年であり、月数が12ならば if($d == 32){ //日が32にならば $d = 1; //日を1に降り直す $m++; //月を一つあげる } } else { //12月以外なら if($d == 31){ //日が31にならば $d = 1; //日を1に降り直す $m++; //月を一つ上げる } } if($m == 13){ //月が13ならば $m =1; //月を1に降り直す $y++; //年を一つ上げる } } |
paiza歴では平年、閏年の違いで12月の日数が31日から32日になります。
そのことに注意して日を表す「$d」がその月の日数を越えた場合、「$d」を1に振り直し、月を表す「$m」を一つ上げる、この時「$m」が13になったら「$m」を1に振り直し、年を表す「$y」を一つ上げる。
この処理を対象年月日に達するまで繰り返し、日数をカウントします。
日数のカウントから曜日を出力する
|
1 2 3 |
$num = $counter % 7; $array = ["木曜日","金曜日","土曜日","日曜日","月曜日","火曜日","水曜日"]; echo $array[$num]; |

