2
3

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

パイザBランク問題解説を考察してみる

2
Posted at

01:問題の理解

「長テーブルのうなぎ屋」の問題内容についてについて説明
プログラムを書き始める前に、正しく問題(やりたい事)を理解する事が、
素早く正確に実装するためのコツです。

問題を簡略化して考えてみる。
円卓に26のイスを6つに考えてみる。

すでにイスが3つうまっていて、一人が真ん中に座ると、
時計回りですわる2人は座れず4人しか座れない。

02:入力値の理解

入力値例:
6 3 …6席のテーブル、店に3グループがやってくる
3 2 …第1グループ:3名のグループで、2番目の席から座り始める
1 6 …第2グループ:1名のグループで、6番目の席から座り始める
2 5 …第3グループ:2名のグループで、5番目の席から座り始める

03:ロジックの概要

今回の問題レベルではいきなりコードを書き始めるのは危険、ロジックを書こう。

1.日本語で処理を組み立て、手順を記述する
・入力処理、本処理、出力処理

2.まずは大きな粒感に分割して考える
①入力処理:値取得、テーブルの配列準備
②グループ毎に空席確認
③空席があいていたら座る処理→②に戻る
④出力処理:座った人の人数を出力

04:ロジックの詳細

②グループ毎に空席確認
・グループ文のループ
・各グループごとに座れるのかというif文(空席確認)
 円卓処理
③空席があいていたら座る処理
・グループ人数分のループ、着席処理
 円卓処理

05:実装:入力の処理

array.php
<?php
//①入力処理:値取得、テーブル座席の配列準備
$nm_array = explode(" ",fgets(STDIN));
$seat_num = $nm_array[0];
$group_num = $nm_array[1];
echo "シート数:".$seat_num."\n";
echo "グループ数:".$group_num."\n";
?>

PHPの基本的な配列、

array.php
<?php
$str = fgets(STDIN);
echo $str;
?>

■fgets () 関数
ファイルポインタから 1 行取得する
http://php.net/manual/ja/function.fgets.php

■explode() 関数
文字列を文字列により分割し配列を返す関数
http://php.net/manual/ja/function.explode.php

■print_r() 関数
指定した変数に関する情報を解りやすく出力する関数
http://php.net/manual/ja/function.print-r.php
入力値例:
6 3 …6席のテーブル、店に3グループがやってくる
3 2 …第1グループ:3名のグループで、2番目の席から座り始める
1 6 …第2グループ:1名のグループで、6番目の席から座り始める
2 5 …第3グループ:2名のグループで、5番目の席から座り始める

06:実装:座席配列を作る

array.php
<?php
//①入力処理:値取得、テーブル座席の配列準備
$nm_array = explode(" ",fgets(STDIN));
$seat_num = $nm_array[0];
$group_num = $nm_array[1];
echo "シート数:".$seat_num."\n";
echo "グループ数:".$group_num."\n";

$seat = array();
$seat = array_pad($seat, $seat_num, 0);
print_r($seat);
?>

テーブルの座席の配列、
シートぶんの配列を作って0で埋める処理をarray_padで行う。

■array_pad() 関数
指定長、指定した値で配列を埋める関数です
http://php.net/manual/ja/function.array-pad.php

■print_r() 関数
指定した変数に関する情報を解りやすく出力する関数
http://php.net/manual/ja/function.print-r.php

動画のように、座席配列の作成と、print_r()によるデバッグ出力をやってみましょう。
座席配列は、下記のように配列のkeyで座席番号を表現し、valueで空席状況を表現すると良いでしょう。
$座席配列[席番号] = 空席状況(0なら空席、1なら着席済み)

07:実装:空席確認をする1

このチャプターでは、グループ毎に空席確認をおこなうためのループ処理を書きます。

7.php
<?php
//①入力処理:値取得、テーブル座席の配列準備
$nm_array = explode(" ",fgets(STDIN));
$seat_num = $nm_array[0];
$group_num = $nm_array[1];
echo "シート数:".$seat_num."\n";
echo "グループ数:".$group_num."\n";

$seat = array();
$seat = array_pad($seat, $seat_num, 0);//0が空席
print_r($seat);

//②グループ毎に空席確認
	//グループ分のループ
for ($i = 0; $i < $group_num; $i++) {
     $group_array = explode(" ",fgets(STDIN));
     $group_person_num = $group_array[0];
     $sit_point = $group_array[1];
     echo "グループの人数".$group_person_num."\n";
     echo "着席開始位置".$sit_point."\n";
}

各グループの人数、着席開始位置を出力してみよう!
グループ数分のループをfor文で書いて、グループ毎のグループ人数、
グループ着席開始位置を取得して出力をしてみよう。
グループ人数:**
着席開始位置:**
という形で各グループの出力をしてみましょう。

演習課題「空席確認」
for文の練習問題です。

入力値の形式は長テーブルのうなぎ屋と同じとします。
座席数分のエクスクラメーションマーク [ ! ] を表示してみましょう。

■出力例
座席数 5の場合 [ !!!!! ] と出力。

■入力例
6 3 …6席のテーブル(座席数)、店に3グループがやってくる
3 2 …第1グループ:3名のグループで、2番目の席から座り始める
1 6 …第2グループ:1名のグループで、6番目の席から座り始める
2 5 …第3グループ:2名のグループで、5番目の席から座り始める

クリックするとヒントが見れます
入力される値
6 3
3 2
1 6
2 5

標準入力からの値取得方法はこちらをご確認ください

期待する出力値
!!!!!!

enshuu2.php
<?php
//①入力処理:値取得、テーブル座席の配列準備
$nm_array = explode(" ",fgets(STDIN));
$seat_num = $nm_array[0];
$group_num = $nm_array[1];

for($i = 0; $i < $seat_num; $i++) {
    echo "!";
}
?>

08:実装:空席確認をする2

各グループの人数分のループを回して、そのグループ全員が座れるのかの
空席確認を二重ループ処理を書きます。

8.php
<?php
//①入力処理:値取得、テーブル座席の配列準備
$nm_array = explode(" ",fgets(STDIN));
$seat_num = $nm_array[0];
$group_num = $nm_array[1];
echo "シート数:".$seat_num."\n";
echo "グループ数:".$group_num."\n";

$seat = array();
$seat = array_pad($seat, $seat_num, 0);//0が空席
print_r($seat);

//②グループ毎に空席確認
//グループ分のループ
$count = 0;
for($i=0 ; $i < $group_num ; $i++){
    $group_array = explode(" ",fgets(STDIN));
    $group_person_num = $group_array[0];
    $sit_point = $group_array[1];
    $sit_point -= 1;
    echo "グループの人数:".$group_person_num."\n";
    echo "着席開始位置:".$sit_point."\n";

    //グループの人数分のループ、空席確認
    $emply_flg = true;
    for($j = $sit_point; $j < $sit_point+$group_person_num; $j++){
        if($seat[$j] >0){
            $emply_flg = false;
            break;
        }
        //円卓処理
    }
    var_dump($empty_flg);
    //③席が空いていたら座る処理
    //グループの人数部のループ、着席処理
    //円卓処理
}
//④出力処理:座った人の人数を出力
?>

$seat_num …テーブルの座席数
$group_num …店にやってくるグループ数
$i …グループ分のループをまわすfor文のイテレータ
$group_array …標準入力2行目以降のグループ人数と着席開始位置の入った配列
$group_person_num …各グループの人数
$sit_point …着席開始位置
$seat …空席確認用の座席配列
$j …各グループの人数ループをまわすfor文のイテレータ(空席確認をする席番号)

各グループ人数を判定して!で表す。

mondai8.php
<?php
$num_array = explode(" ", fgets(STDIN));
$group_num = $num_array[1];

for($i=0; $i<$group_num; $i++){
    $group_array = explode(" ",fgets(STDIN));
    $group_person_num = $group_array[0];
    
    // echo $group_person_num."\n";
    for($j=0; $j<$group_person_num; $j++){
        echo "!";
    }
    echo "\n";
}
?>

09:実装:円卓処理

このチャプターでは、丸テーブルのうなぎ屋問題の肝である、円卓処理を実装します。

9.php
<?php
//①入力処理:値取得、テーブル座席の配列準備
$nm_array = explode(" ",fgets(STDIN));
$seat_num = $nm_array[0];
$group_num = $nm_array[1];
echo "シート数:".$seat_num."\n";
echo "グループ数:".$group_num."\n";

$seat = array();
$seat = array_pad($seat, $seat_num, 0);//0が空席
print_r($seat);

//②グループ毎に空席確認
//グループ分のループ
$count = 0;
for($i=0 ; $i < $group_num ; $i++){
    $group_array = explode(" ",fgets(STDIN));
    $group_person_num = $group_array[0];
    $sit_point = $group_array[1];
    $sit_point -= 1;
    echo "グループの人数:".$group_person_num."\n";
    echo "着席開始位置:".$sit_point."\n";

    // グループ人数分のループ、空席確認
    $empty_flg = true;//trueはすわれる
    for($j = $sit_point; $j < $sit_point+$group_person_num; $j++){
        //円卓処理
        if($j >= $seat_num){
            $search_point = $j - $seat_num;
        }else{
            $search_point = $j;
        }
        //echo $search_point;
        // 空席確認
        if($seat[$search_point] >0){
            $empty_flg= false;
            break;
        }
    }
    var_dump($empty_flg);
    //③席が空いていたら座る処理
    //グループの人数部のループ、着席処理
    //円卓処理

}
//④出力処理:座った人の人数を出力

10:着席処理

このチャプターでは、グループ人数分の空席がある場合の着席処理を実装します。
()

10.php
<?php
//①入力処理:値取得、テーブル座席の配列準備
$nm_array = explode(" ",fgets(STDIN));
$seat_num = $nm_array[0];
$group_num = $nm_array[1];
echo "シート数:".$seat_num."\n";
echo "グループ数:".$group_num."\n";

$seat = array();
$seat = array_pad($seat, $seat_num, 0);//0が空席
print_r($seat);

//②グループ毎に空席確認
//グループ分のループ
for($i=0 ; $i < $group_num ; $i++){
    $group_array = explode(" ",fgets(STDIN));
    $group_person_num = $group_array[0];
    $sit_point = $group_array[1];
    $sit_point -= 1;
    echo "グループの人数:".$group_person_num."\n";
    echo "着席開始位置:".$sit_point."\n";

    // グループ人数分のループ、空席確認
    $empty_flg = true;//trueはすわれる
    for($j = $sit_point; $j < $sit_point+$group_person_num; $j++){
        //円卓処理
        if($j >= $seat_num){
            $search_point = $j - $seat_num;
        }else{
            $search_point = $j;
        }
        //echo $search_point;
        // 空席確認
        if($seat[$search_point] >0){
            $empty_flg= false;
            break;
        }
    }
    var_dump($empty_flg);
    //③席が空いていたら座る処理
    if($empty_flg == true){
        //グループの人数分のループ、着席処理
        //円卓処理
        for($j = $sit_point; $j < $sit_point+$group_person_num; $j++){
            //円卓処理
            if($j >= $seat_num){
                $search_point = $j - $seat_num;
            }else{
                $search_point = $j;
            }
            //echo $search_point;
            // 着席処理
            $seat[$search_point]=1;
        }

    }
    print_r($seat);
}

11:集計処理

このチャプターでは、最終的に着席できた人数を集計します

11.php
<?php
//①入力処理:値取得、テーブル座席の配列準備
$nm_array = explode(" ",fgets(STDIN));
$seat_num = $nm_array[0];
$group_num = $nm_array[1];

$seat = array();
$seat = array_pad($seat, $seat_num, 0);//0が空席

//②グループ毎に空席確認
//グループ分のループ
for($i=0 ; $i < $group_num ; $i++){
    $group_array = explode(" ",trim(fgets(STDIN)));
    $group_person_num = $group_array[0];
    $sit_point = $group_array[1];
    $sit_point -= 1;

    // グループ人数分のループ、空席確認
    $empty_flg = true;//trueはすわれる
    for($j = $sit_point; $j < $sit_point+$group_person_num; $j++){
        //円卓処理
        if($j >= $seat_num){
            $search_point = $j - $seat_num;
        }else{
            $search_point = $j;
        }
        //echo $search_point;
        // 空席確認
        if($seat[$search_point] >0){
            $empty_flg= false;
            break;
        }
    }
    //③席が空いていたら座る処理
    if($empty_flg == true){
        //グループの人数分のループ、着席処理
        //円卓処理
        for($j = $sit_point; $j < $sit_point+$group_person_num; $j++){
            //円卓処理
            if($j >= $seat_num){
                $search_point = $j - $seat_num;
            }else{
                $search_point = $j;
            }
            //echo $search_point;
            // 着席処理
            $seat[$search_point]=1;
        }
    }
}
//④出力処理:座った人の人数を出力
$count = 0;
for($i = 0; $i < $seat_num; $i++) {
    if($seat[$i] > 0){
        $count++;
    }
}
echo $count;

12:ライブでよりスマートにコーディング!

このチャプターでは、よりスマートな書き方をライブコーディングで解説してみます。

paiza社長片山が5分でB級問題をライブコーディングで解く!!
圧倒的ですね!

2
3
0

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
2
3

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?