Edited at

【php】標準入力を使った競技プログラミングの問題をローカル環境で解く方法

More than 3 years have passed since last update.

環境

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


入力は全て整数で与えられる

1N100000=10^5

0Xi1000000=10^6,1iN


入力例1

3

0 51 100


入力例2

4

0 1 1 0

入力例に対する出力もあるので、それを参考に解いていきます。


ローカル環境で確認しながら解く


1.テキストファイルを作成

file.textを作成し、そこに上記の入力例をコピー。


2.fopenでファイル読み込み

テキストファイルと同じ階層にあるphpファイルに以下を記入。


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;


ローカルでechoprint_rvar_dumpを駆使しつつ、なんどもテキストファイルに様々な値を書いてみて、ようやくアクセプトされました。

一つ、疑問が残っています。

以下だとOKだったのですが、


OK

$num = trim(fgets(STDIN));

$points = trim(fgets(STDIN));

これだと間違いとなってしまいました。


NG

fscanf(STDIN, '%d', $num);  

fscanf(STDIN, '%s', $points);

2行目の書き方に問題がありそうですが、原因がわかりません。

わかる方、教えていただけると嬉しいです。

また、yukicoderでは、他の方の解答例も見られるのですが、No.135に関して、まだphpで書かれたコードがありません。ぜひ、違う書き方、考え方でコードがかけたら教えて下さい。


なぜこれが必要になったか。

 つい最近競技プログラミングというものを知り、競技アルゴリズム勉強会なるものに参加してみました。まるで数学の問題を解いているようで、久しぶりに数学的な頭をつかい、心地良い疲労感を得ることができました。

 そのときに、標準入力で与えられる数値を使わなくてはならなかったのですが、これがさっぱりわかりませんでした。ペアプログラミングであり、主催者にも質問できる環境だったため、「こう書けばいいよ」ということだけ教わり問題を解きました。

 家に帰って別の問題に挑戦しましたが、WA(Wrong Answer)の連続。そもそも、入力値を適切にとれていない可能性があります。そこで、簡単にローカル環境で(入力値)テストケースを変化させ、確認しながらコードをかける方法を考えました。

最後までお読み下さりありがとうございました。