Skip to content

Instantly share code, notes, and snippets.

@remore
Last active February 15, 2017 11:29
Show Gist options
  • Save remore/3f354e0ce46edfeaea1db65ce215f290 to your computer and use it in GitHub Desktop.
Save remore/3f354e0ce46edfeaea1db65ce215f290 to your computer and use it in GitHub Desktop.
(1: 最適化問題) 下記パラメータのままでElevator::tick()のみを最適化して平均待ち人数を最小化する / (2: 並列化問題) 以下のプログラムをマルチスレッドで動作させると何倍早くなるか実装して検証する / (3: チューニング問題)並列化以外の方法で本プログラムの実行時間を短縮するためにどのような改修を加えるとよいか考察する
#include <iostream>
#include <iomanip>
#include <random>
#include <unistd.h>
using namespace std;
const int MAX_FLOOR = 14;
const int ELEVATOR_COUNT = 4;
const int RAISING_PROBABILITY = 10;
class Elevator{
private:
int pos=0;
public:
bool dest[MAX_FLOOR]={};
enum RunningStatus {MOVING, STOPPED, ARRIVED};
RunningStatus state=STOPPED;
int get_position();
RunningStatus tick(Elevator *e);
const char* get_state_char();
};
int Elevator::get_position(){
return pos;
}
Elevator::RunningStatus Elevator::tick(Elevator *e){
state = STOPPED;
for (int i=0; i<MAX_FLOOR; i++){
if (dest[i] && i!=pos) {
if (i<pos) {pos-=1;} else {pos+=1;}
if (i==pos) {
state = ARRIVED;
dest[i] = false;
break;
} else {
state = MOVING;
break;
}
}
}
return state;
}
const char* Elevator::get_state_char(){
switch(state){
case Elevator::STOPPED: return "S";
case Elevator::ARRIVED: return "A";
case Elevator::MOVING: return "M";
}
}
int main(int argc, char** argv) {
if (argc<2) {
cout << "入力パラメータを指定してください:" << endl;
cout << "例) ./a.out 1000 -d" << endl;
return -1;
}
int frame_count, sum=0;
Elevator e[ELEVATOR_COUNT];
int waiting_people[MAX_FLOOR]={};
random_device rnd;
for (frame_count=0; frame_count<atol(argv[1]); frame_count++){
// 人が集まる
for (int j=0; j<MAX_FLOOR; j++){
for (int k=0; k<ELEVATOR_COUNT; k++){
if (rnd()%RAISING_PROBABILITY==0){
int peep = 1+rnd()%5;
waiting_people[j] += peep;
e[k].dest[j]=true; // エレベータを呼ぶ
}
}
sum += waiting_people[j];
}
// エレベータ動く
for (int j=0; j<ELEVATOR_COUNT; j++){
switch(e[j].tick(e)){
case Elevator::STOPPED:
case Elevator::ARRIVED:
waiting_people[e[j].get_position()] = 0;
break;
case Elevator::MOVING:
break;
}
}
// コンソール出力
if (argc >=3 && (string)"-d"==argv[2] || (frame_count+1)==atol(argv[1])) {
usleep(50000);
cout << "\033[2J";
cout << " time=" << frame_count << "sec" << endl;
cout << " ----------------------" << endl;
cout << " elevators waiting" << endl;
for (int i=MAX_FLOOR; --i>=0;){
cout << setw(3) << i << "F";
for (auto elevator:e){
cout << "|" << ((elevator.get_position()==i) ? elevator.get_state_char() : (elevator.dest[i] ? "`" : " ") );
}
cout << "|" << " " << waiting_people[i] << endl;
}
}
}
cout << "平均待ち人数=" << (float)sum / (frame_count*MAX_FLOOR) << "人" << endl;
return 0;
}
@mk2
Copy link

mk2 commented Feb 14, 2017

Golang版置いときます。Goroutineでやりたいんですが、時間が。

package main

import "bytes"
import "time"
import "fmt"
import "math/rand"

type State string

const (
	MaxFloor                 = 14
	ElevatorCount            = 4
	RaisingProbability       = 10
	Moving             State = "MOVING"
	Stopped            State = "STOPPED"
	Arrived            State = "ARRIVED"
)

type Elev struct {
	pos   int
	dest  []bool
	state State
	num   int
}

func newElev() *Elev {
	e := new(Elev)
	e.dest = make([]bool, MaxFloor)
	e.state = Stopped
	return e
}

func (e *Elev) toChar() string {
	if e.state == Moving {
		return "M"
	} else if e.state == Stopped {
		return "S"
	} else if e.state == Arrived {
		return "A"
	}
	return "-"
}

func (e *Elev) tick(elevs []*Elev) State {
	e.state = Stopped
	for i := 0; i < MaxFloor; i++ {
		if e.dest[i] && i != e.pos {
			if i < e.pos {
				e.pos--
			} else {
				e.pos++
			}
			if i == e.pos {
				e.state = Arrived
				e.dest[i] = false
			} else {
				e.state = Moving
			}
		}
	}
	return e.state
}

func main() {
	// init elevators
	elevs := make([]*Elev, ElevatorCount)
	for i := 0; i < ElevatorCount; i++ {
		e := newElev()
		e.num = i
		elevs[i] = e
	}

	// init waiting peoples
	wps := make([]int, MaxFloor)

	sum := 0
	var outbuf bytes.Buffer
	for frame := 0; frame < 1000; frame++ {
		// gather waiting peoples
		for f := 0; f < MaxFloor; f++ {
			for _, e := range elevs {
				if rand.Int()%RaisingProbability == 0 {
					wps[f] += 1 + rand.Int()%5
					e.dest[f] = true
					sum += wps[f]
				}
			}
		}

		// check each elevator states
		for _, e := range elevs {
			if res := e.tick(elevs); res == Arrived || res == Stopped {
				wps[e.pos] = 0
			}
		}

		time.Sleep(1 * time.Millisecond)

		fmt.Println("")
		outbuf.Reset()
		outbuf.WriteString(fmt.Sprintf("-Frame:%d-Sum:%d---------------------\n", frame, sum))
		for f := 0; f < MaxFloor; f++ {
			outbuf.WriteString(fmt.Sprintf("%3dF", f))
			for _, e := range elevs {
				outbuf.WriteString("|")
				if e.pos == f {
					outbuf.WriteString(e.toChar())
				} else {
					if e.dest[f] {
						outbuf.WriteString("`")
					} else {
						outbuf.WriteString(" ")
					}
				}
			}
			outbuf.WriteString(fmt.Sprintf("|%3d", wps[f]))
			fmt.Println(outbuf.String())
			outbuf.Reset()
		}
		outbuf.Reset()
	}
	fmt.Printf("Total Waiting Peoples: %d\n", sum)
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment