Paiza スキルチェック過去問題(PHP編) 日別訪問者数の最大平均区間 ～ランク B 相当～ 解いてみた。

<h2>はじめに</h2>
Paizaにて日別訪問者数の最大平均区間 (paizaランク B 相当)を解いてみました。

本番問題の解答・解説はNGですが、こちらに関しては、公開していいそうなのでまとめておきます。

(回答をPaizaでは再度閲覧できないため、<span style="text-decoration: underline;">備忘録的目的</span>もあります。)

また、事前知識として標準入力の基本を知っておく必要がありますが、今回は割愛します。以下が参考になるかと思います。

<a href="https://paiza.jp/works/mondai/skillcheck_archive/max_range?language_uid=php">https://paiza.jp/works/mondai/skillcheck_archive/max_range?language_uid=php</a>
<h2>日別訪問者数の最大平均区間 (paizaランク B 相当)</h2>
以下が問題のリンクです。詳細はこちらでご確認ください。

<a href="https://paiza.jp/works/mondai/skillcheck_archive/max_range?language_uid=php">https://paiza.jp/works/mondai/skillcheck_archive/max_range?language_uid=php</a>

※問題文抜粋※
<blockquote><span style="font-size: 10pt;">あなたは、とあるウェブサイトを管理していました。</span>
<span style="font-size: 10pt;">ある連続したk日間、このウェブサイトでキャンペーンを行ったのですが、いつからいつまでの期間に行ったかを忘れてしまいました。</span>

<span style="font-size: 10pt;">幸い、ウェブサイトを運営していた全n日分のアクセスログが残っており、1日ごとの訪問者数が分かっています。</span>
<span style="font-size: 10pt;">とりあえず、連続するk日の中で、1日あたりの平均訪問者数が最も多い期間を、キャンペーンを行った期間の候補だと考えることにしました。</span>

<span style="font-size: 10pt;">n日分の訪問者数のリストとキャンペーンの日数kが入力されるので、キャンペーンを行った期間の候補数と、候補の中で最も早い開始日を出力してください。</span></blockquote>
<pre><sup>実際に入力される値：
</sup>5 3
1 2 3 2 1

<sup>ケースパターン3(躓いた部分メモ)：
</sup>100 10
2 7 1 1 5 7 0 7 5 8 4 9 9 0 9 6 5 2 3 2 9 8 5 2 10 10 9 4 3 0 9 9 4 2 7 6 6 3 4 8 0 6 4 2 6 1 8 7 0 0 8 10 6 1 2 10 0 9 9 0 4 4 1 4 10 3 6 8 7 6 2 2 6 7 0 5 1 4 0 7 2 7 4 0 2 4 5 8 9 6 3 5 3 9 7 5 6 7 3 4</pre>
<pre><sup>期待される出力：</sup>	
1 2</pre>

ちなみに他ケースパターンはpaiza.ioで実行テストできます。

ブラウザ上で且つ無料で使えるのでかなり便利です◎

<a href="https://paiza.io/ja">https://paiza.io/ja</a>

<img class="alignnone size-full wp-image-306" src="https://chobimusic.com/wp-content/uploads/2020/03/paiza7.jpg" alt="" width="955" height="841" />
<h2>失敗例</h2>

<pre><sup>解答コード：</sup>
&lt;?php
    // $nに全日数5、$kにキャンペーン日数3 を代入
    fscanf(STDIN, "%d %d", $n, $k);
    $visiter = fgets(STDIN);
    // 数字で配列として1 2 3 2 1を代入
    (int)$visiters = explode(" ",$visiter);
    // k日分の訪問者数の和を必要な回数分求める
    $slice_visiters = [];//[6,7,6]
    for($i=0;$i&lt;$n-$k+1;$i++){
    // 全訪問者数からキャンペーン日数分の値のみ取り出す
    $slice_visiter = array_slice($visiters,$i,$k);
    //キャンペーン日数分の値の合計を出す
    $slice_visiter = array_sum($slice_visiter);
    //$slice_visitersへ配列を代入。配列に配列を代入してる。
    array_push($slice_visiters,$slice_visiter);
    }
    //[6,7,6]を676に結合
    $join = implode('', $slice_visiters);
    $max = max($slice_visiters);//7
　　//substr_count( 検索対象の文字列, 検索する文字列 )
    $count = substr_count( $join, $max );
　　//mb_strpos( 検索対象の文字列, 検索する文字列 )※0からカウントされる
    $position = mb_strpos( $join, $max );
    $ask_position = $position+1;
    echo "$count $ask_position";
?&gt;
</pre>
約2時間の格闘の末、なんとかsuccessまで持っていきました。

絶対コードぐちゃぐちゃ<del>(じぶんもよくわからない)。</del>

もはや執念。。。

<img class="alignnone size-full wp-image-303" src="https://chobimusic.com/wp-content/uploads/2020/03/paiza5.jpg" alt="" width="977" height="672" />

ところがどっこい。。。

<img class="alignnone size-full wp-image-304" src="https://chobimusic.com/wp-content/uploads/2020/03/paiza6.jpg" alt="" width="976" height="911" />

不正解でした。

implode関数で結合しましたがよくよく考えたら、例えばmax値が15のときだと、1,5の配列も15としてみなされてカウントされちゃうのでだめですね。。。2桁の数字があると位置もずれるし。。。値が2桁になるケースを考えていなかった。。。

Oh my god!!

<h2>正解例</h2>
以下が正解例になります。
<img class="alignnone size-full wp-image-317" src="https://chobimusic.com/wp-content/uploads/2020/03/paiza8.jpg" alt="" width="968" height="913" />
<pre><sup>解答コード：</sup>
&lt;?php
    fscanf(STDIN, "%d %d", $n, $k);
    $visiter = fgets(STDIN);
    (int)$visiters = explode(" ",$visiter);
    $slice_visiters = [];//[4,13,15,13]
    for($i=0;$i&lt;$n-$k+1;$i++){
    // 全訪問者数からキャンペーン日数分の値のみ取り出す
    $slice_visiter = array_slice($visiters,$i,$k);
    //キャンペーン日数分の値の合計を出す
    $slice_visiter = array_sum($slice_visiter);
    //$slice_visitersへ配列を代入。配列に配列を代入してる。
    array_push($slice_visiters,$slice_visiter);
    }
    //数字が連結しないようにカンマで区切る
    $join = implode(',', $slice_visiters);
    //配列の中の最大値を取得
    $max = max($slice_visiters);
    //最大値が出現する回数をカウント 
    $count = substr_count( $join, $max );
    // 配列の中で最大値の最初の位置をキー値で取得※0からカウントされるので+1
    $position = (int)array_search($max,$slice_visiters)+1;
    echo "$count $position";
?&gt;
</pre>
失敗例のコードから諦めきれず、約1時間格闘した末なんとか正解まで辿り着きました。

ポイントは最大値が2桁の数字の際に、1桁の数字が連結してカウントされないように,(カンマ)でimplodeする際区切ったことと、array_search関数を使用して、配列の位置をキーで取得したことです。

参考になれば幸いです。

<h2>おわりに</h2>
値の数が多くなるとプログラミングを使うメリットを感じます。

ちゃんとPaizaランクBになれるよう頑張ります。

<h2>関連リンク</h2>
Paiza スキルチェック見本問題(PHP編)まとめ ～ランクC相当～
<a href="https://chobimusic.com/paiza_skillcheck_c/">https://chobimusic.com/paiza_skillcheck_c/</a>

Paiza スキルチェック見本問題(PHP編)まとめ ～ランクD相当～
<a href="https://chobimusic.com/paiza_skillcheck_d/">https://chobimusic.com/paiza_skillcheck_d/</a>

Paiza 標準入力セット(PHP編)まとめ ～ランクD相当～
<a href="https://chobimusic.com/paiza_standard_input/">https://chobimusic.com/paiza_standard_input/</a>