わたしは、就活のため・自身の能力をあげるために競技プログラミングに取り組んでいます。
その中で、わたしが苦戦した問題があったので、紹介します。
対象の読者
・atcoderでB,C問題に苦戦している。
・PHPを使っている。
問題文
文字列 string を受け取り、文字数の半分を文字列の真ん中から返す、middleSubstring という関数を定義してください。
入力された文字列の長さが偶数の場合、文字列の真ん中から文字数の半分に相当する部分文字列を返します。例えば、入力が "ABCDEFGH" の場合、真ん中の部分文字列は "CDEF" です。入力された文字列の長さが奇数の場合、真ん中の文字を除いた、文字数の半分に相当する部分文字列を返します。例えば、入力が "ABCDEFG" の場合、真ん中の部分文字列は "CDE" です。
入力文字列の文字数が 2 以下の場合、最初の文字を返します。例えば、入力が "A" や "AB" の場合、"A" を返します。
例えば"ABCDE"という奇数個の文字が入力された場合は、以下のように返します。
BC
回答のコード
<?php
function middleSubstring(string $stringInput): string{
// 文字列の長さ
$len = strlen($stringInput);
// 切り取られるサイズ
$middle = floor($len/2);
// 切り取りを始める前方の位置
$front = ceil($middle/2);
// 文字列の長さが2以下のときは、最初の文字を返す。
if ($len <= 2) return $stringInput[0];
// 前方から前方+middle分だけ切り取り
return substr($stringInput,$front, $middle);
}
echo(middleSubstring("A")). PHP_EOL;// A
echo(middleSubstring("AB")). PHP_EOL;// A
echo(middleSubstring("ABC")). PHP_EOL;// B
echo(middleSubstring("ABCD")). PHP_EOL;// BC
echo(middleSubstring("ABCDE")). PHP_EOL;// BC
echo(middleSubstring("ABCDEF")). PHP_EOL;// CDE
解説
<?php
function middleSubstring(string $stringInput): string{
// 文字列の長さ
$len = strlen($stringInput);
// 切り取られるサイズ
$middle = floor($len/2);
// 切り取りを始める前方の位置
$front = ceil($middle/2);
// 文字列の長さが2以下のときは、最初の文字を返す。
if ($len <= 2) return $stringInput[0];
// 前方から前方+middle分だけ切り取り
return substr($stringInput,$front, $middle);
}
echo(middleSubstring("A")). PHP_EOL;// A
echo(middleSubstring("AB")). PHP_EOL;// A
echo(middleSubstring("ABC")). PHP_EOL;// B
echo(middleSubstring("ABCD")). PHP_EOL;// BC
echo(middleSubstring("ABCDE")). PHP_EOL;// BC
echo(middleSubstring("ABCDEF")). PHP_EOL;// CDE
解説
文字数の半分を len/2 と書き換えて、流れを見ていきましょう。
"A BC D" --> BC
"A BC DE" --> BC
"AB CDEF GH" --> CDEF
"AB CDEF GHI" --> CDEF
文字列のサイズが 4 または 5 の時、サイズの半分は 2、文字列のサイズが 8、9 の時、サイズの半分が 4 となっていることから、floor 関数を使って floor(len/2) と表現できることがわかります。これを middle としましょう。
"AB CDE F" --> CDE
"AB CDE FG" --> CDE
また、切り取られる文字サイズが奇数のパターンの前方に着目すると、前方は ceil(middle/2) になっていることがわかるでしょう。今求めたいのは真ん中の文字列なので、前方の最後から、前方+真ん中まで切り取ればいいことがわかります。substring 関数を用いて substring(前方, 前方 + 真ん中)と表現できます。