Skip to content

Commit 42d75a0

Browse files
author
Miles Shang
committed
A README.md
A elevator.py
0 parents  commit 42d75a0

File tree

2 files changed

+201
-0
lines changed

2 files changed

+201
-0
lines changed

README.md

Lines changed: 139 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,139 @@
1+
Python Elevator Challenge
2+
=========================
3+
4+
So You Think You Can Program An Elevator?
5+
-----------------------------------------
6+
7+
Many of us ride elevators every day. We intuitively feel like we have a good grasp on them. We understand the how elevators decide where to go. But say you wanted to express this algorithm in code. How would you go about it?
8+
9+
The Test Harness
10+
----------------
11+
12+
Lets consider a simplified model of an elevator. Like all elevators, it can go up or down. We define constants for these. This elevator also happens to be in a building with six floors.
13+
14+
>>> UP = 1
15+
>>> DOWN = 2
16+
>>> FLOOR_COUNT = 6
17+
18+
We will make an `Elevator` class that simulates an elevator. This will delegate to another class which contains the elevator business logic, i.e. deciding what the elevator should do. Your challenge is to implement the business logic.
19+
20+
A user can interact with the elevator in two ways. She can call the elevator by pressing the up or down button on any floor, and she can select a destination floor by pressing the button for that floor on the panel in the elevator. Both of these actions get passed straight through to the logic delegate.
21+
22+
>>> class Elevator(object):
23+
... def call(self, floor, direction):
24+
... self._logic_delegate.on_called(floor, direction)
25+
...
26+
... def select_floor(self, floor):
27+
... self._logic_delegate.on_floor_selected(floor)
28+
29+
The logic delegate can respond by setting the elevator to move up, move down, or stop. It can also read the current floor and movement direction of the elevator. These actions are accessed through `Callbacks`, a mediator provided by the `Elevator` class to the logic delegate.
30+
31+
>>> class Elevator(Elevator):
32+
... def __init__(self, logic_delegate):
33+
... self._current_floor = 1
34+
... print "1...",
35+
... self._motor_direction = None
36+
... self._logic_delegate = logic_delegate
37+
... self._logic_delegate.callbacks = self.Callbacks(self)
38+
...
39+
... class Callbacks(object):
40+
... def __init__(self, outer):
41+
... self._outer = outer
42+
...
43+
... @property
44+
... def current_floor(self):
45+
... return self._outer._current_floor
46+
...
47+
... @property
48+
... def motor_direction(self):
49+
... return self._outer._motor_direction
50+
...
51+
... @motor_direction.setter
52+
... def motor_direction(self, direction):
53+
... self._outer._motor_direction = direction
54+
55+
The simulation runs in steps. Every time step consists of either a change of floor, or a pause at a floor. Either way, the business logic delegate gets notified. Along the way, we print out the movements of the elevator so that we can keep track of it. We also define a few helper methods.
56+
57+
>>> class Elevator(Elevator):
58+
... def step(self):
59+
... delta = 0
60+
... if self._motor_direction == UP: delta = 1
61+
... elif self._motor_direction == DOWN: delta = -1
62+
...
63+
... if delta:
64+
... self._current_floor = self._current_floor + delta
65+
... print "%s..." % self._current_floor,
66+
... self._logic_delegate.on_floor_changed()
67+
... else:
68+
... self._logic_delegate.on_ready()
69+
...
70+
... assert self._current_floor >= 1
71+
... assert self._current_floor <= FLOOR_COUNT
72+
...
73+
... def run_until_stopped(self):
74+
... self.step()
75+
... while self._motor_direction is not None: self.step()
76+
...
77+
... def run_until_floor(self, floor):
78+
... self.step()
79+
... for i in range(100):
80+
... if self._current_floor == floor: break
81+
... self.step()
82+
... else: assert False
83+
84+
That's it for the framework.
85+
86+
The Business Logic
87+
------------------
88+
89+
As for the business logic, an example implementation is provided in the `elevator.py` file in this project.
90+
91+
>>> from elevator_solution import ElevatorLogic
92+
93+
As provided, it doesn't pass the tests in this document. Your challenge is to fix it so that it does. To run the tests, run this in your shell:
94+
95+
python -m doctest -v README.md
96+
97+
With the correct business logic, here's how the elevator should behave:
98+
99+
### Basic usage
100+
101+
Make an elevator. It starts at the first floor.
102+
103+
>>> elevator = Elevator(ElevatorLogic())
104+
1...
105+
106+
Somebody on the fifth floor wants to go down.
107+
108+
>>> elevator.call(5, DOWN)
109+
>>> elevator.run_until_stopped()
110+
2... 3... 4... 5...
111+
112+
The elevator went up to the fifth floor. Now, the passenger gets on and presses the button to select the first floor.
113+
114+
>>> elevator.select_floor(1)
115+
>>> elevator.run_until_stopped()
116+
4... 3... 2... 1...
117+
118+
More Tests
119+
----------
120+
121+
>>> elevator = Elevator(ElevatorLogic())
122+
1...
123+
>>> elevator.call(3, UP)
124+
>>> elevator.call(5, UP)
125+
>>> elevator.run_until_stopped()
126+
2... 3...
127+
>>> elevator.run_until_stopped()
128+
4... 5...
129+
130+
>>> elevator = Elevator(ElevatorLogic())
131+
1...
132+
>>> elevator.call(5, UP)
133+
>>> elevator.call(3, UP)
134+
>>> elevator.run_until_stopped()
135+
2... 3...
136+
>>> elevator.run_until_stopped()
137+
4... 5...
138+
139+

elevator.py

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
UP = 1
2+
DOWN = 2
3+
FLOOR_COUNT = 6
4+
5+
class ElevatorLogic(object):
6+
"""
7+
An incorrect implementation. Can you make it pass all the tests?
8+
9+
Fix the methods below to implement the correct logic for elevators.
10+
The tests are integrated into `README.md`. To run the tests:
11+
$ python -m doctest -v README.md
12+
13+
To learn when each method is called, read its docstring.
14+
To interact with the world, you can get the current floor from the
15+
`current_floor` property of the `callbacks` object, and you can move the
16+
elevator by setting the `motor_direction` property. See below for how this is done.
17+
"""
18+
19+
def __init__(self):
20+
# Feel free to add any instance variables you want.
21+
self.destination_floor = None
22+
self.callbacks = None
23+
24+
def on_called(self, floor, direction):
25+
"""
26+
This is called when somebody presses the up or down button to call the elevator.
27+
This could happen at any time, whether or not the elevator is moving.
28+
The elevator could be requested at any floor at any time, going in either direction.
29+
30+
floor: the floor that the elevator is being called to
31+
direction: the direction the caller wants to go, up or down
32+
"""
33+
self.destination_floor = floor
34+
35+
def on_floor_selected(self, floor):
36+
"""
37+
This is called when somebody on the elevator chooses a floor.
38+
This could happen at any time, whether or not the elevator is moving.
39+
Any floor could be requested at any time.
40+
41+
floor: the floor that was requested
42+
"""
43+
self.destination_floor = floor
44+
45+
def on_floor_changed(self):
46+
"""
47+
This lets you know that the elevator has moved one floor up or down.
48+
You should decide whether or not you want to stop the elevator.
49+
"""
50+
if self.destination_floor == self.callbacks.current_floor:
51+
self.callbacks.motor_direction = None
52+
53+
def on_ready(self):
54+
"""
55+
This is called when the elevator is ready to go.
56+
Maybe passengers have embarked and disembarked. The doors are closed,
57+
time to actually move, if necessary.
58+
"""
59+
if self.destination_floor > self.callbacks.current_floor:
60+
self.callbacks.motor_direction = UP
61+
elif self.destination_floor < self.callbacks.current_floor:
62+
self.callbacks.motor_direction = DOWN

0 commit comments

Comments
 (0)