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

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


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

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


#02:入力値の理解

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

#03:ロジックの概要

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

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

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



#04:ロジックの詳細 

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


#05:実装：入力の処理


```PHP: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の基本的な配列、
```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　…６席のテーブル、店に３グループがやってくる
3 2　…第１グループ：３名のグループで、２番目の席から座り始める
1 6　…第２グループ：１名のグループで、６番目の席から座り始める
2 5　…第３グループ：２名のグループで、５番目の席から座り始める




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

```PHP: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:実装：空席確認をする１ 
このチャプターでは、グループ毎に空席確認をおこなうためのループ処理を書きます。

```PHP: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　…６席のテーブル(座席数)、店に３グループがやってくる
3 2　…第１グループ：３名のグループで、２番目の席から座り始める
1 6　…第２グループ：１名のグループで、６番目の席から座り始める
2 5　…第３グループ：２名のグループで、５番目の席から座り始める

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

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

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

```PHP: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:実装：空席確認をする２ 
各グループの人数分のループを回して、そのグループ全員が座れるのかの
空席確認を二重ループ処理を書きます。



```PHP: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　…標準入力２行目以降のグループ人数と着席開始位置の入った配列
$group_person_num　…各グループの人数
$sit_point　…着席開始位置
$seat　…空席確認用の座席配列
$j　…各グループの人数ループをまわすfor文のイテレータ(空席確認をする席番号)

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

```PHP: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:実装：円卓処理 
このチャプターでは、丸テーブルのうなぎ屋問題の肝である、円卓処理を実装します。

```PHP: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:着席処理 
このチャプターでは、グループ人数分の空席がある場合の着席処理を実装します。
()

```PHP: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:集計処理 
このチャプターでは、最終的に着席できた人数を集計します


```PHP: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社長片山が５分でB級問題をライブコーディングで解く！！
圧倒的ですね！

https://paiza.jp/works/php/basicnew/unagi-new/2212