環境
Eclipse Standard/SDK Version: Kepler Service Release 2
XAMPP 5.6.3-0
OSX Yosemite10.10
MacBook Pro(Retina, 13-inch, Mid2014)
対象
- phpで競技プログラミングをやってみたいが、
- コマンドプロンプト、ターミナルには苦手意識があり、
- STDIN, 標準入力と言われてもよくわからない人
与えられる標準入力
例として、yukicoderというサイトの問題文にはこのように書かれています。
問題全体はこちらにあります。
yukicoder No.135 とりあえず1次元の問題
※全文掲載して良いかわからなかったので、リンクにしています。
N
X1 X2 … XN
・1≤N≤100000=10^5
・0≤Xi≤1000000=10^6,1≤i≤N
3
0 51 100
4
0 1 1 0
入力例に対する出力もあるので、それを参考に解いていきます。
ローカル環境で確認しながら解く
1.テキストファイルを作成
file.textを作成し、そこに上記の入力例をコピー。
2.fopenでファイル読み込み
テキストファイルと同じ階層にあるphpファイルに以下を記入。
$filename = "file.text";
$fh = fopen($filename, "r");
$stdinArr = array();
if ($fh) {
while (!feof($fh)) {
$stdinLine = fgets($fh); //一行ごとに内容を取得
$stdinArr[] = $stdinLine; //配列に格納
}
fclose($fh);
}
3.配列に格納された値を利用
これで、$stdinArr
に与えられた入力の行数分だけ内容が入ったので、これを使って問題を解いていきます。
必要に応じてfile.textの中身を変更し、どんな入力値でも求める答えが出せているか確認します。
参考サイト
競技プログラミングの練習サイト:yukicoder
fscanf関数を使った例を掲載:
[競技プログラミング][PHP][AtCoder]おとぎの国の高橋君
paizaの取得例:値取得・出力サンプルコード
fopen関数を使った例を掲載:ファイルの中身を1行ずつテキスト処理するには
その他
上記の問題の解答例と疑問点
<php?
$num = trim(fgets(STDIN));
$points = trim(fgets(STDIN));
$arr1 = explode(" ", $points); //半角スペース区切りの要素を格納
sort($arr1); //昇順に並び替え
$arr2 = array_unique($arr1, SORT_NUMERIC); //値の重複を削除
$arr2 = array_merge($arr2); //重複してとびとびになったインデックスを振り直す
$arr3 = array();
if(count($arr2) == 1){
$ans = 0;
}else{
for($i = 1; $i < count($arr2); $i++){
$arr3[] = $arr2[$i] - $arr2[($i-1)];
}
$ans = min($arr3);
}
echo $ans;
ローカルでecho
とprint_r
、var_dump
を駆使しつつ、なんどもテキストファイルに様々な値を書いてみて、ようやくアクセプトされました。
一つ、疑問が残っています。
以下だとOKだったのですが、
$num = trim(fgets(STDIN));
$points = trim(fgets(STDIN));
これだと間違いとなってしまいました。
fscanf(STDIN, '%d', $num);
fscanf(STDIN, '%s', $points);
2行目の書き方に問題がありそうですが、原因がわかりません。
わかる方、教えていただけると嬉しいです。
また、yukicoderでは、他の方の解答例も見られるのですが、No.135に関して、まだphpで書かれたコードがありません。ぜひ、違う書き方、考え方でコードがかけたら教えて下さい。
なぜこれが必要になったか。
つい最近競技プログラミングというものを知り、競技アルゴリズム勉強会なるものに参加してみました。まるで数学の問題を解いているようで、久しぶりに数学的な頭をつかい、心地良い疲労感を得ることができました。
そのときに、標準入力で与えられる数値を使わなくてはならなかったのですが、これがさっぱりわかりませんでした。ペアプログラミングであり、主催者にも質問できる環境だったため、「こう書けばいいよ」ということだけ教わり問題を解きました。
家に帰って別の問題に挑戦しましたが、WA(Wrong Answer)の連続。そもそも、入力値を適切にとれていない可能性があります。そこで、簡単にローカル環境で(入力値)テストケースを変化させ、確認しながらコードをかける方法を考えました。
最後までお読み下さりありがとうございました。