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:実装:入力の処理
<?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
$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:実装:座席配列を作る
<?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
このチャプターでは、グループ毎に空席確認をおこなうためのループ処理を書きます。
<?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
標準入力からの値取得方法はこちらをご確認ください
期待する出力値
!!!!!!
<?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
各グループの人数分のループを回して、そのグループ全員が座れるのかの
空席確認を二重ループ処理を書きます。
<?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文のイテレータ(空席確認をする席番号)
各グループ人数を判定して!で表す。
<?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
//①入力処理:値取得、テーブル座席の配列準備
$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
//①入力処理:値取得、テーブル座席の配列準備
$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
//①入力処理:値取得、テーブル座席の配列準備
$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級問題をライブコーディングで解く!!
圧倒的ですね!