回答
AtCoder/arc002_2.php at master · wada811/AtCoder今回はC言語みたいに計算でやらずにPHPの関数で頑張りました。
とりあえず2種類の方法で通したので両方載せる。
<?php fscanf(STDIN, "%s", $date); while(true){ $splits = explode("/", $date); $year = $splits[0]; $month = $splits[1]; $day = $splits[2]; $quotient = $year / $month / $day; if(floor($quotient) == ceil($quotient)){ break; } $date = date("Y/m/d", mktime(0, 0, 0, $month, $day, $year) + 86400); } echo $date."\n"; ?>explode関数で文字列を分割して年月日をそれぞれ取得する。
割り算を計算して、割り切れない場合は商が小数になるので
floor関数とceil関数で小数点以下を切り捨て/切り上げした結果が異なる。
その場合はmktime関数でUNIXTIMEに変換して一日(24*60*60=86400秒)を足す。
新しいUNIXTIMEに対してdate関数でフォーマットを指定して日付を生成して繰り返す。
これを割り切れるまで(商が整数になりfloor関数とceil関数の結果が同じになるまで)やります。
UNIX時間 - Wikipedia
UNIX時間(ユニックスじかん)またはUNIX時刻(ユニックスじこく、UNIX time、POSIX time)とはコンピューターシステム上で日時を表す単位。UTCでの1970年1月1日真夜中(0時0分0秒)からの経過秒数(閏秒を加味しない)で表される。
UNIX系オペレーティングシステムだけでなく、他の多くのオペレーティングシステムにおいてもこの単位が用いられている。システム内部では32ビットまたは64ビットの符号付整数(signed int)で扱われていることが普通であり、特に32ビットで扱われている場合においては符号付整数が取れる最大値 2,147,483,647 を超える時点で時刻を扱えなくなるという問題がある。これを2038年問題という。
ということでUNIXTIMEで計算してるとそのうち面倒な事になるんじゃないの?ってことで違う方法でも解いてみた。
<?php fscanf(STDIN, "%s", $input); $splits = explode("/", $input); $date = new DateTime(); $date->setDate($splits[0], $splits[1], $splits[2]); while(true){ $year = $date->format("Y"); $month = $date->format("m"); $day = $date->format("d"); $quotient = $year / $month / $day; if(floor($quotient) == ceil($quotient)){ break; } $date->add(new DateInterval("P1D")); } echo $date->format("Y/m/d") . PHP_EOL; ?>ロジックは同じ。DateTimeオブジェクトのインスタンスを生成して、setDateメソッドで年月日をセットする。
フォーマットを指定してformatメソッドで値を取得する。
日付の加算はaddメソッドの引数にDateIntervalオブジェクトを渡して行う。
DateIntervalの引数の書式はPHP: DateInterval::__construct - Manualを参照のこと。
どこでも動いたほうがいいよねってことでそのプラットフォームでの改行コードを表すPHP_EOLも使ってみた。
PHP 逆引きレシピ (PROGRAMMER’S RECiPE)も良かったけど日付関連が前者のやり方だったので
後者のやり方を解説しているというパーフェクトPHP(PERFECT SERIES 3)が欲しい。
参考
手を動かして覚えるPHP 5.3新機能 日付(DateTime,DateInterval)編 | Act as Professional
PHP 5.3 の DateTime オブジェクト関連の便利な新機能 - 肉とご飯と甘いもの @ sotarok
追記(2012/09/01):DateTime::createFromFormatの方が簡潔だった
<?php fscanf(STDIN, "%s", $input); $date = DateTime::createFromFormat('Y/m/d', trim($input), new DateTimeZone('Asia/Tokyo')); while(true){ $year = $date->format("Y"); $month = $date->format("m"); $day = $date->format("d"); $quotient = $year / $month / $day; if(floor($quotient) == ceil($quotient)){ break; } $date->add(new DateInterval("P1D")); } echo $date->format("Y/m/d") . PHP_EOL; ?>まだまだ修行が足りない。PHP力が低いなードキュメントは見るようにしてたのだけども…。
パーフェクトPHP (PERFECT SERIES 3)