エレベータの制御(基本編)
長いからとサンプルコードはしょってしまったのでいろいろと不都合がでてしまいました。 last_round は僕のデバックの都合上のものなので出力に関しては気にしないでください。 ごめんなさい。 お題を間違えてCのまま投稿してしまったので 言語設定せずに投稿します。 gcc -Wall -std=c99 doukaku225.c # ところで、これ投稿したの一昨日くらいなのですが、 公開のカウントって下書きした段階ではじまってる?
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 | #include <stdio.h>
#include <stdbool.h>
#include <assert.h>
#define CARRYING_LIMIT (3)
#define CARRYING_MOVE_COST (5)
#define ELEVATOR_MOVE_COST (2)
typedef struct tagFloor
{
bool called; /* */
int floor_Nth; /* */
int carry_remain; /* */
long last_round; /* */
struct tagFloor *down; /* */
struct tagFloor *up; /* */
} FLOOR;
typedef struct tagElevatorBox
{
int carrying; /* */
int cool_time; /* */
FLOOR * now_floor; /* */
FLOOR * target_floor; /* */
} ELEVATOR;
static long round = 0;
static long round_wait_max = 0;
static long move_total = 0;
/* エレベータ内が搭載可能人数を返す */
int elevator_getCarryAvailed( const ELEVATOR *elevator )
{
return (CARRYING_LIMIT - elevator->carrying);
}
/* 目的の階に到着していれば真 */
bool elevator_isTargetFloor( const ELEVATOR *elevator)
{
if( elevator->now_floor == elevator->target_floor )
{
return true;
}
return false;
}
/* エレベータに乗車させる */
int elevator_carrying_in( ELEVATOR *elevator )
{
int avail = 0;
const int oldremain = elevator->now_floor->carry_remain;
avail = elevator_getCarryAvailed(elevator);
if( avail > 0 )
{
if( elevator->now_floor->carry_remain > avail )
{
elevator->now_floor->carry_remain -= avail;
elevator->carrying += avail;
}
else
{
elevator->carrying += elevator->now_floor->carry_remain;
elevator->now_floor->called = false;
elevator->now_floor->carry_remain = 0;
}
elevator->cool_time = CARRYING_MOVE_COST;
printf("IN(%d) [%d] → [%d] "
,elevator->now_floor->floor_Nth,oldremain, elevator->now_floor->carry_remain);
}
return 0;
}
/* エレベータから降車させる */
int elevator_carrying_out( ELEVATOR *elevator )
{
if( elevator->carrying > 0 )
{
elevator->carrying = 0;
elevator->cool_time = CARRYING_MOVE_COST;
printf("OUT ");
}
return 0;
}
/* エレベータを移動する */
int elevator_update(ELEVATOR *elevator)
{
if( elevator->cool_time > 0 )
{
elevator->cool_time --;
return 1;
}
if( elevator_isTargetFloor(elevator) == true )
{
return 0;
}
else
{
/* エレベータの移動 */
move_total ++;
assert( elevator->now_floor->floor_Nth != elevator->target_floor->floor_Nth );
if( elevator->now_floor->floor_Nth < elevator->target_floor->floor_Nth )
{
elevator->now_floor = elevator->now_floor->up;
}
else
{
elevator->now_floor = elevator->now_floor->down;
}
elevator->cool_time = ELEVATOR_MOVE_COST;
}
return 0;
}
/* 次に停止するべき階を選択する */
int floor_select( FLOOR **next, const FLOOR *floor, const long round )
{
long wait_max;
FLOOR *cursor;
*next = NULL; /* 最上階 */
wait_max = -1;
cursor = (FLOOR *)floor;
while( true )
{
if( cursor->called == true && (round - cursor->last_round) > wait_max )
{
*next = cursor;
wait_max = (round - cursor->last_round);
if( (round - cursor->last_round) > round_wait_max )
{
round_wait_max = (round - cursor->last_round);
}
}
if( cursor == cursor->down )
{
break;
}
cursor = cursor->down;
}
if( *next == NULL )
{
/* 1階ならばすべて運び終わっている */
*next = cursor;
return 1;
}
(*next)->last_round = round;
return 0;
}
/* */
int floor_print(const ELEVATOR* elevator, const FLOOR *floor)
{
printf("--------------------\n");
while( true )
{
printf(" [%d]th Floor: [%2d] / last_round:[%4ld] %c %c\n"
, floor->floor_Nth, floor->carry_remain,floor->last_round
, (floor==elevator->target_floor)?'=':' '
, (floor==elevator->now_floor)?'*':' ');
if( floor == floor->down )
{
break;
}
floor = floor->down;
}
return 0;
}
/* */
int main(int argc, char *argv[])
{
static FLOOR floor[] =
{
{false, 1, 0, 0, &floor[0], &floor[1]}
,{true, 2, 7, 0, &floor[0], &floor[2]}
,{true, 3, 3, 0, &floor[1], &floor[3]}
,{true, 4, 11, 0, &floor[2], &floor[4]}
,{true, 5, 7, 0, &floor[3], &floor[4]}
};
static FLOOR *top_floor = &floor[4];
static ELEVATOR schindler = { 0, 0, &floor[0], &floor[0] };
FLOOR *next = NULL;
/* 初期状態の出力*/
printf("INIT ");
floor_print(&schindler, top_floor);
/* 運搬開始 */
round = 0;
round_wait_max = 0;
move_total = 0;
while( true )
{
round ++;
elevator_update(&schindler);
if( schindler.cool_time > 0 )
{
continue;
}
if( elevator_isTargetFloor(&schindler) == true )
{
/* 目的の階に到着 */
if( schindler.now_floor->floor_Nth == 1 )
{
elevator_carrying_out(&schindler);
/* 次の停止回を最上階から検索する */
floor_select( &next, top_floor, round );
if( next->floor_Nth == 1 )
{
/* もうない */
break;
}
//floor_print(&schindler, top_floor);
printf("\n");
}
else
{
elevator_carrying_in(&schindler);
if( elevator_getCarryAvailed( &schindler ) > 0 )
{
/* まだ搭載できるので移動のついでに追加搭載する */
floor_select( &next, schindler.now_floor, round );
}
else
{
/* もう限界なので1階を目的地にする */
next = &floor[0];
}
//floor_print(&schindler, top_floor);
} /* end of if(1階か) */
/* 次の停止階を設定する */
schindler.target_floor = next;
} /* end of if(到着しているか) */
} /* end of while( 残っているか ) */
printf("\n\nEND ");
floor_print(&schindler, top_floor);
printf("%15s:[%ld]\n", "経過時間", round);
printf("%15s:[%ld]\n", "最大待ち時間", round_wait_max);
printf("%15s:[%ld]\n", "移動距離合計数", move_total);
return 0;
}
/* EOF */
|
Posted feedbacks - Haskell
Haskellでやったんですよー言語タグをつけるの忘れました…
1 2 3 | module Main where
main = putStrLn "see my previous post"
|




raynstard
#8289()
Rating-3/3=-1.00
エレベータを制御して、5階建てのビルの各階にいる人たちを、 「効率よく」1階のエントランスまで運んでください。 作成時の条件は次の通りです。 1. 各階において、人が残っていることはわかるが、 あと何人残っているかまではわからないものとする。 # 人が残っているところは常に呼び出しのボタンが押された状態を # 仮定して問題ありません。 2. 稼働しているエレベータは1機のみとする 3. 降車するたびに、変化がわかるような出力をしてください。 4. すべての人を運搬終わったら、最後に次の情報を出力してください。 - 運搬を始めてからの経過時間(ラウンド数) - 一番長く放置されていた階の待ち時間(ラウンド数) - エレベータの移動距離合計数 エレベータの機能は次の通りです。 - 搭載人数は最大3人までとする。 - 移動には、1つの階につき「2」ラウンドかかる。 - 人の乗降には、1回につき「5」ラウンドかかる。 ※ 「ラウンド」は包括された時間だと思ってください。 単純に「秒」と読み替えてもよいです 各階の人数は次の通りです。 5階 7人 4階 11人 3階 3人 2階 7人 1階 0人 冒頭では、「効率よく」なんて曖昧な表現をしようしましたが、 何について効率よくしたのか、設計についての見解を コメントしていただけるとうれしいです。 たとえば、 下記のサンプル出力では、各階の待ち時間を最小とすることで 効率よいとしました。(利用者の視点) ぱっと思いつくところでは、ほかにも2-3種類あるとおもいます。 さて、あなたならどう書く?(笑 // 自分で作ったやつは250L位になってしまいましたorz INIT -------------------- [5]th Floor: [ 7] / last_round:[ 0] [4]th Floor: [11] / last_round:[ 0] [3]th Floor: [ 3] / last_round:[ 0] [2]th Floor: [ 7] / last_round:[ 0] [1]th Floor: [ 0] / last_round:[ 0] IN(5) [7] → [4] OUT IN(4) [11] → [8] OUT IN(3) [3] → [0] OUT IN(2) [7] → [4] OUT IN(5) [4] → [1] OUT IN(4) [8] → [5] OUT IN(2) [4] → [1] OUT IN(5) [1] → [0] IN(4) [5] → [3] OUT IN(2) [1] → [0] OUT IN(4) [3] → [0] OUT END -------------------- [5]th Floor: [ 0] / last_round:[ 174] [4]th Floor: [ 0] / last_round:[ 229] [3]th Floor: [ 0] / last_round:[ 58] [2]th Floor: [ 0] / last_round:[ 213] [1]th Floor: [ 0] / last_round:[ 0] 経過時間:[257] 最大待ち時間:[100] 移動距離合計数:[52]1 reply [ reply ]