LoginSignup
12
11

More than 5 years have passed since last update.

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

Last updated at Posted at 2015-01-30

環境
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)の連続。そもそも、入力値を適切にとれていない可能性があります。そこで、簡単にローカル環境で(入力値)テストケースを変化させ、確認しながらコードをかける方法を考えました。

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

12
11
3

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
12
11