Edited at

【PHP】競技プログラミング用の関数チートシート【プロコン】


はじめに

最近競技プログラミング/プログラミングコンテストへの参戦を始めましたが、PHPでやっている人が少なくあまり情報がないのと、自分用のメモとしても、PHPで参戦する競技プログラミングのチートシートをまとめて行きたいと思います。


前提

下記のファイルを用意。index.phpが実行ファイル、test.txtが標準入力用のファイルとします。


test.txt

1 2 3

4 5 6
7 8 9


標準入力


fgets()

PHP マニュアル : fgets — ファイルポインタから 1 行取得する


index.php

$line = fgets(STDIN); // STDIN(スタンダードインプット:標準入力)から1行を取得

echo $line; // 結果:1 2 3

fgets()での読み出しは length のオプションを指定しない場合、改行またはEOF(End of File)に達したかのいずれかの時点で終了します。


fopen()

ローカル環境で標準入力用のファイルを用意してテストを行う場合は以下のようにしてみました。


index.php

// ファイルパス指定し、任意のファイルを読み取り専用でファイルオープン

$file = fopen("test.txt", "r");
// ファイルオープンして代入した変数 $file から fgets() で1行 $line に代入
$line = fgets($file);
echo $line; // 結果:1 2 3


fscanf()

fscanf — フォーマットに基づきファイルからの入力を処理する

test.txtのように1行に複数の文字列が含まれる場合、フォーマットを指定して別々の変数に格納することができます。fscanf()をコールする度に、ファイルから1行ずつ読み込みます。


index.php

// 半角スペースを区切りとして、別々の変数に格納

fscanf(STDIN, "%d %d %d", $a, $b, $c);
echo $a; // 1
echo $b; // 2
echo $c; // 3

区切り文字がカンマの場合は"%d,%d,%d"とします。

各種フォーマットの種類と、それらを指定するオプションについては下記を参照。

例えばよく使われるのは、文字列を意味する%s(string)や、10進数の整数を意味する%d(digit)などです。

%s%dのことは型指定子またはフォーマット指定子といいます。C言語などでは馴染みが深いのではないでしょうか。

sprintf — フォーマットされた文字列を返す


while()

whileループ

標準入力の内容が複数行に渡る場合、whileを使うと簡単にすべての行を取り出せます。

whileに限らず条件分岐でよくある挙動は「trueなら実行する、falseなら実行しない」ですが、whileについても「条件式がtrueである間は実行する」というループになります。そのためwhileの条件式に($line = fgets(STDIN))という内容を設定した場合は、ファイルの最終行まで実行して読み込めるものがなくなったらfalse(実行終了)となります。


index.php

while ($line = fgets(STDIN)){

echo $line;
// 1回目の繰り返し:1 2 3
// 2回目の繰り返し:4 5 6
// 3回目の繰り返し:7 8 9
};


文字列の加工


trim()

trim — 文字列の先頭および末尾にあるホワイトスペースを取り除く

用意された標準入力ファイルの行頭・行末に余計な空白等があって望んだ出力が得られない場合はそれらを削除します。オプションを指定しなければtrim()は空白・タブ・改行などを削除してくれます。


index.php

$line = fgets(STDIN);

$i = trim($line);
echo $i; // 1 2 3


explode()

explode — 文字列を文字列により分割する

文字列を区切り文字で分割した結果を配列として返します。


index.php

$line = fgets(STDIN);

// 半角スペースを区切りとして、配列に格納
$arr = explode(" ", $line);
echo $arr[0]; // 1
echo $arr[1]; // 2
echo $arr[2]; // 3


implode()

implode — 配列要素を文字列により連結する

区切り文字で、配列の中身を連結したいときはimplode()を使用します。引数には区切り文字として使用する文字列と、連結したい文字列の格納された配列を用意します。


index.php

$line = fgets(STDIN);

$arr = explode(" ", $line);
// カンマを区切りとして、配列の中身を連結
$str = implode(",", $arr);
echo $str; // 1,2,3


str_split()

str_split — 文字列を配列に変換する

文字列を1文字ずつ分割して配列に格納します。オプションに文字数nを指定すれば、n文字ずつ格納することができます。


index.php

$line = fgets(STDIN);

$arr = str_split($line);
echo $arr[0]; // 1
echo $arr[1]; // 半角スペース
echo $arr[2]; // 2
echo $arr[3]; // 半角スペース
echo $arr[4]; // 3


文字列の検索


str_replace()

str_replace — 検索文字列に一致したすべての文字列を置換する

第三引数の文字列の中で、第一引数の文字列を検索し、第二引数の文字列に置換します。


index.php

$line = fgets(STDIN);

// $lineで定義された"1 2 3"という文字列から"1"を探し"9"に置き換える
$str = str_replace("1", "9", $line);
echo $str; // 9 2 3


strpos()

strpos — 文字列内の部分文字列が最初に現れる場所を見つける

第一引数の文字列の中から、第二引数の文字列を検索し、検索文字列が最初に現れる位置を返します。位置は0から始まる数え方で表され、検索した文字列が存在しない場合はfalseを返します。


index.php

while($line = fgets(STDIN)){

$arr[] = trim($line);
}
echo strpos($arr[0], "1"); // 0

似たような挙動であるstrstr()と比べて高速でメモリ消費も少なく、PHPマニュアルによると文字列の検索だけであれば上記のstrpos()を使うと良いそうです。

strstr — 文字列が最初に現れる位置を見つける


もし特定の haystack に needle があるかどうかを調べるだけの場合、 より高速でメモリ消費も少ない strpos() を代わりに使用してください。



カウント・個数や回数を数える


mb_substr_count()

mb_substr_count — 部分文字列の出現回数を数える

第一引数に指定された文字列の中で、第二引数で指定された文字列の個数を数えます。


index.php

$line = fgets(STDIN);

echo mb_substr_count($line, "3"); // 1


strlen

strlen — 文字列の長さを得る

文字長をバイト数で数えます。1や2などの半角数字は1としてカウントされ、半角スペースや改行やタブなども1としてカウントされます。

test.txtにおける1 2 3であれば1,半角スペース,2,半角スペース,3,改行とカウントされ6が結果となりますが、文字列があいう(全角ひらがなのみ、改行やスペースなし)などであった場合、ひらがなは単純計算で1文字3バイトとして数えられるため、出力結果は3文字x3バイトで9となります。


index.php

$line = fgets(STDIN);

echo strlen($line); // 6


mb_strlen()

mb_strlen — 文字列の長さを得る

引数に長さを調べたい文字列を指定すると、マルチバイトで文字列の長さを返してくれますう。スペースや改行や全角半角文字を含む文字数がわかり、文字のバイト数は問わないため文字列があいう(全角ひらがなのみ、改行やスペースなし)などであった場合は3が返ってきます。


index.php

$line = fgets(STDIN);

echo mb_strlen($line); // 6


count()

count — 変数に含まれるすべての要素、 あるいはオブジェクトに含まれる何かの数を数える

引数で指定した、配列またはオブジェクトの数を数えます。配列の要素の数を数えるときなどに便利です。


index.php

while ($line = fgets(STDIN)){

$arr[] = $line;
};
$cnt = count($arr);
echo $cnt; // 3


計算・合計値や絶対値を出す


array_sum()

array_sum — 配列の中の値の合計を計算する

配列に格納された数値を合計し、整数または float として返します。


index.php

$temp = fgets(STDIN);

$line = trim($temp);
$arr = explode(" ", $line);
echo $arr[0]; // 1
echo $arr[1]; // 2
echo $arr[2]; // 3
echo array_sum($arr); // 1+2+3= 6


abs()

abs — 絶対値

数値の絶対値を返します。簡単に言うと、負の数を正の数に(マイナスの数をプラスの数に)変換します。絶対値なので、正の数は正の数のままになります。


index.php

$temp = fgets(STDIN);

$line = trim($temp);
$arr = explode(" ", $line);
$num = $arr[0] - $arr[2]; // -2
echo abs($num); // 2


小数点・切り捨てと繰り上げ


floor()

floor — 端数の切り捨て

小数点以下の数字を切り捨てて小さい方の整数へ合わせます。


index.php

<?php

echo floor(4.3); // 4
echo floor(9.999); // 9
echo floor(-3.14); // -4


ceil()

ceil — 端数の切り上げ

小数点以下の数字を繰り上げて大きい方の整数へ合わせます。


index.php

<?php

echo ceil(4.3); // 5
echo ceil(9.999); // 10
echo ceil(-3.14); // -3


配列・ソートや除外


asort()

asort — 連想キーと要素との関係を維持しつつ配列をソートする

asort関数では要素の中身(バリュー)を判定して番号順やアルファベット順に配列を組み替えます。


index.php

$test = ["d" => 1, "a" => 4, "b" => 2, "c" => 3];

asort($test);
foreach ($test as $key => $val) {
echo "$key = $val\n";
// 出力結果: d = 1
// 出力結果: b = 2
// 出力結果: c = 3
// 出力結果: a = 4
}

これをすることによって元の配列の順序は変更され、asort()自体の返り値としては成功した場合に TRUE を、失敗した場合に FALSE を返します。


krsort()

krsort — 配列をキーで逆順にソートする

キーと値の関係は維持したまま、キーの順序を逆順にすることによって、配列の中身を組み替えます。

こちらも関数自体の返り値としては成功した場合に TRUE を、失敗した場合に FALSE を返します。


index.php

$test = ["a", "p", "p", "l", "e"];

krsort($test);
foreach ($test as $key => $val) {
echo "$key = $val\n";
// 出力結果: 4 = e
// 出力結果: 3 = l
// 出力結果: 2 = p
// 出力結果: 1 = p
// 出力結果: 0 = a
}

配列のソート

PHPには、配列を並び替える・順序を変更するための関数が複数用意されているので、上記のリストから状況や目的に応じて関数を選択すると良さそうです。


array_unique()

array_unique — 配列から重複した値を削除する

引数として与えられた配列を元に、値に重複のない新規配列を返します。配列内の要素がすべて同じ値であるかどうかを知りたいときなどに便利です。

例えばゾロ目の判定をしたいとき、桁数の多い数をひと桁ずつ、配列のひとつひとつの要素として分解後、array_unique()によって重複を削除することでゾロ目の数値であるかがわかります。

重複を削除すればゾロ目のものは配列が1つしか残りませんし、ゾロ目でなければ2つ以上となります。


index.php

$array = [1, 1, 1, 1];

if (count(array_unique($array)) == 1) {
echo "Yes\n"; // 配列の値がすべて同じなのでYesとなる
} else {
echo "No\n";
}



その他


改行

改行(\n)はダブルコーテーション内で使用することで改行として認識されます。

HTMLの改行<br>とは異なるので、ブラウザでレンダリングされたHTMLによる画面表示としてではなく、PHPの出力として改行されていることを検証ツールなどで確認してください。


index.php

echo "月が\n綺麗ですね。";

// 月が
// 綺麗ですね。

個人的によく使うものを中心にまとめましたが、また増えると思うので随時追加します。


参考URL

ファイルから1行ずつ読み込む - fgets()

PHPでファイルの読み込みをする主な4つの方法

標準入力、標準出力とは何か?

標準入出力

Paizaで使える標準入力の取得

PHPで標準入力から値を取得して表示する方法を解説

フォーマットを作る!PHPのsprintf関数の使い方【初心者向け】

PHPの出力で文字を改行(\n)させるには’’(シングルコーテーション)じゃなくて""(ダブルコーテーション)で記述する

余分な空白・改行を取り除くtrim関数を使おう!〜PHP入門編〜

PHP関数iconv_strlen、mb_strlen、およびstrlenの違いは何ですか?

PHPの文字数検知 Tips

grapheme_strlen

UTF-8における「strlen」と「mb_strlen」の挙動について

【PHP入門】文字列の置換 | str_replace・str_ireplace・strtr

【PHP】複数文字列の置換(str_replace)

%sとか%dってなんだ?【PHP】

explodeとimplodeの使い方

PHPでカンマ区切りデータを配列に入れる方法 (explode)

【php】文字列を1文字ずつに分解して配列にする

PHPで配列を初期化する方法

PHPで配列に要素を追加する方法

PHPのcount関数を使って配列の要素の数をカウントする方法【初心者向け】

php 負数を正数にする(絶対値)

phpでの小数点を切り捨てや切り上げする方法!【floor/ceil/round】

配列の値が全て同じか判定する方法

PHPで文字列を検索をする:strpos, strstr, preg_match

【PHP】特定の文字列を含むかのチェック

PHP:特定の文字列を含むかどうか検索する方法、まとめ。