update from Atlas
This commit is contained in:
107
control/coroaverager3.py
Normal file
107
control/coroaverager3.py
Normal file
@@ -0,0 +1,107 @@
|
||||
"""
|
||||
A coroutine to compute a running average.
|
||||
|
||||
Testing ``averager`` by itself::
|
||||
|
||||
>>> coro_avg = averager()
|
||||
>>> next(coro_avg)
|
||||
>>> coro_avg.send(10)
|
||||
>>> coro_avg.send(30)
|
||||
>>> coro_avg.send(6.5)
|
||||
>>> coro_avg.send(None)
|
||||
Traceback (most recent call last):
|
||||
...
|
||||
StopIteration: Result(count=3, average=15.5)
|
||||
|
||||
|
||||
Driving it with ``yield from``::
|
||||
|
||||
>>> def summarize(results):
|
||||
... while True:
|
||||
... result = yield from averager()
|
||||
... results.append(result)
|
||||
...
|
||||
>>> results = []
|
||||
>>> summary = summarize(results)
|
||||
>>> next(summary)
|
||||
>>> for height in data['girls;m']:
|
||||
... summary.send(height)
|
||||
...
|
||||
>>> summary.send(None)
|
||||
>>> for height in data['boys;m']:
|
||||
... summary.send(height)
|
||||
...
|
||||
>>> summary.send(None)
|
||||
>>> results == [
|
||||
... Result(count=10, average=1.4279999999999997),
|
||||
... Result(count=9, average=1.3888888888888888)
|
||||
... ]
|
||||
True
|
||||
|
||||
"""
|
||||
|
||||
# BEGIN YIELD_FROM_AVERAGER
|
||||
from collections import namedtuple
|
||||
|
||||
Result = namedtuple('Result', 'count average')
|
||||
|
||||
|
||||
# the subgenerator
|
||||
def averager(): # <1>
|
||||
total = 0.0
|
||||
count = 0
|
||||
average = None
|
||||
while True:
|
||||
term = yield # <2>
|
||||
if term is None: # <3>
|
||||
break
|
||||
total += term
|
||||
count += 1
|
||||
average = total/count
|
||||
return Result(count, average) # <4>
|
||||
|
||||
|
||||
# the delegating generator
|
||||
def grouper(results, key): # <5>
|
||||
while True: # <6>
|
||||
results[key] = yield from averager() # <7>
|
||||
|
||||
|
||||
# the client code, a.k.a. the caller
|
||||
def main(data): # <8>
|
||||
results = {}
|
||||
for key, values in data.items():
|
||||
group = grouper(results, key) # <9>
|
||||
next(group) # <10>
|
||||
for value in values:
|
||||
group.send(value) # <11>
|
||||
group.send(None) # <12>
|
||||
|
||||
# print(results) # uncomment to debug
|
||||
report(results)
|
||||
|
||||
|
||||
# output report
|
||||
def report(results):
|
||||
for key, result in sorted(results.items()):
|
||||
group, unit = key.split(';')
|
||||
print('{:2} {:5} averaging {:.2f}{}'.format(
|
||||
result.count, group, result.average, unit))
|
||||
|
||||
|
||||
data = {
|
||||
'girls;kg':
|
||||
[40.9, 38.5, 44.3, 42.2, 45.2, 41.7, 44.5, 38.0, 40.6, 44.5],
|
||||
'girls;m':
|
||||
[1.6, 1.51, 1.4, 1.3, 1.41, 1.39, 1.33, 1.46, 1.45, 1.43],
|
||||
'boys;kg':
|
||||
[39.0, 40.8, 43.2, 40.8, 43.1, 38.6, 41.4, 40.6, 36.3],
|
||||
'boys;m':
|
||||
[1.38, 1.5, 1.32, 1.25, 1.37, 1.48, 1.25, 1.49, 1.46],
|
||||
}
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
main(data)
|
||||
|
||||
# END YIELD_FROM_AVERAGER
|
||||
5
control/kwcombos.py
Normal file
5
control/kwcombos.py
Normal file
@@ -0,0 +1,5 @@
|
||||
from keyword import kwlist
|
||||
from itertools import combinations
|
||||
|
||||
for combo in combinations(kwlist, 2):
|
||||
print(*combo)
|
||||
@@ -2,25 +2,25 @@
|
||||
"""
|
||||
Taxi simulator
|
||||
|
||||
Sample run with two cars, random seed = 4. This is a valid doctest.
|
||||
Sample run with two cars, random seed 10. This is a valid doctest.
|
||||
|
||||
>>> main(num_taxis=2, seed=10)
|
||||
taxi: 0 Event(time=0, proc=0, action='leave garage')
|
||||
taxi: 0 Event(time=4, proc=0, action='pick up passenger')
|
||||
taxi: 1 Event(time=5, proc=1, action='leave garage')
|
||||
taxi: 1 Event(time=9, proc=1, action='pick up passenger')
|
||||
taxi: 0 Event(time=10, proc=0, action='drop off passenger')
|
||||
taxi: 1 Event(time=10, proc=1, action='leave garage')
|
||||
taxi: 1 Event(time=11, proc=1, action='pick up passenger')
|
||||
taxi: 0 Event(time=14, proc=0, action='pick up passenger')
|
||||
taxi: 1 Event(time=12, proc=1, action='drop off passenger')
|
||||
taxi: 0 Event(time=17, proc=0, action='pick up passenger')
|
||||
taxi: 1 Event(time=19, proc=1, action='pick up passenger')
|
||||
taxi: 1 Event(time=21, proc=1, action='drop off passenger')
|
||||
taxi: 1 Event(time=24, proc=1, action='pick up passenger')
|
||||
taxi: 0 Event(time=28, proc=0, action='drop off passenger')
|
||||
taxi: 1 Event(time=28, proc=1, action='drop off passenger')
|
||||
taxi: 0 Event(time=32, proc=0, action='drop off passenger')
|
||||
taxi: 0 Event(time=33, proc=0, action='going home')
|
||||
taxi: 1 Event(time=33, proc=1, action='pick up passenger')
|
||||
taxi: 1 Event(time=35, proc=1, action='drop off passenger')
|
||||
taxi: 1 Event(time=38, proc=1, action='pick up passenger')
|
||||
taxi: 1 Event(time=42, proc=1, action='drop off passenger')
|
||||
taxi: 1 Event(time=44, proc=1, action='pick up passenger')
|
||||
taxi: 1 Event(time=75, proc=1, action='drop off passenger')
|
||||
taxi: 1 Event(time=76, proc=1, action='going home')
|
||||
taxi: 0 Event(time=29, proc=0, action='going home')
|
||||
taxi: 1 Event(time=30, proc=1, action='pick up passenger')
|
||||
taxi: 1 Event(time=61, proc=1, action='drop off passenger')
|
||||
taxi: 1 Event(time=62, proc=1, action='going home')
|
||||
*** end of events ***
|
||||
|
||||
See explanation and longer sample run at the end of this module.
|
||||
@@ -35,8 +35,9 @@ import argparse
|
||||
|
||||
DEFAULT_NUMBER_OF_TAXIS = 3
|
||||
DEFAULT_END_TIME = 80
|
||||
SEARCH_INTERVAL = 4
|
||||
SEARCH_DURATION = 4
|
||||
TRIP_DURATION = 10
|
||||
DEPARTURE_INTERVAL = 5
|
||||
|
||||
Event = collections.namedtuple('Event', 'time proc action')
|
||||
|
||||
@@ -50,7 +51,7 @@ def taxi_process(ident, trips, start_time=0): # <1>
|
||||
"""Yield to simulator issuing event at each state change"""
|
||||
time = yield Event(start_time, ident, 'leave garage') # <2>
|
||||
for i in range(trips): # <3>
|
||||
prowling_ends = time + compute_delay(SEARCH_INTERVAL) # <4>
|
||||
prowling_ends = time + compute_delay(SEARCH_DURATION) # <4>
|
||||
time = yield Event(prowling_ends, ident, 'pick up passenger') # <5>
|
||||
|
||||
trip_ends = time + compute_delay(TRIP_DURATION) # <6>
|
||||
@@ -107,7 +108,7 @@ def main(end_time=DEFAULT_END_TIME, num_taxis=DEFAULT_NUMBER_OF_TAXIS,
|
||||
if seed is not None:
|
||||
random.seed(seed) # get reproducible results
|
||||
|
||||
taxis = {i: taxi_process(i, (i+1)*2, i*10)
|
||||
taxis = {i: taxi_process(i, (i+1)*2, i*DEPARTURE_INTERVAL)
|
||||
for i in range(num_taxis)}
|
||||
sim = Simulator(taxis)
|
||||
sim.run(end_time)
|
||||
@@ -216,40 +217,40 @@ Notes for the ``Simulator.run`` method::
|
||||
sometimes).
|
||||
|
||||
|
||||
Sample run from the command line::
|
||||
Sample run from the command line, seed=24, total elapsed time=160::
|
||||
|
||||
# BEGIN TAXI_SAMPLE_RUN
|
||||
$ clear; python3 taxi_sim.py -t 3 -s 19
|
||||
$ python3 taxi_sim.py -s 24 -e 160
|
||||
taxi: 0 Event(time=0, proc=0, action='leave garage')
|
||||
taxi: 0 Event(time=5, proc=0, action='pick up passenger')
|
||||
taxi: 1 Event(time=10, proc=1, action='leave garage')
|
||||
taxi: 1 Event(time=13, proc=1, action='pick up passenger')
|
||||
taxi: 2 Event(time=20, proc=2, action='leave garage')
|
||||
taxi: 0 Event(time=21, proc=0, action='drop off passenger')
|
||||
taxi: 1 Event(time=21, proc=1, action='drop off passenger')
|
||||
taxi: 1 Event(time=23, proc=1, action='pick up passenger')
|
||||
taxi: 2 Event(time=23, proc=2, action='pick up passenger')
|
||||
taxi: 1 Event(time=25, proc=1, action='drop off passenger')
|
||||
taxi: 1 Event(time=27, proc=1, action='pick up passenger')
|
||||
taxi: 2 Event(time=27, proc=2, action='drop off passenger')
|
||||
taxi: 2 Event(time=29, proc=2, action='pick up passenger')
|
||||
taxi: 1 Event(time=31, proc=1, action='drop off passenger')
|
||||
taxi: 2 Event(time=31, proc=2, action='drop off passenger')
|
||||
taxi: 1 Event(time=33, proc=1, action='pick up passenger')
|
||||
taxi: 2 Event(time=33, proc=2, action='pick up passenger')
|
||||
taxi: 2 Event(time=36, proc=2, action='drop off passenger')
|
||||
taxi: 2 Event(time=37, proc=2, action='pick up passenger')
|
||||
taxi: 2 Event(time=40, proc=2, action='drop off passenger')
|
||||
taxi: 1 Event(time=42, proc=1, action='drop off passenger')
|
||||
taxi: 1 Event(time=43, proc=1, action='going home')
|
||||
taxi: 0 Event(time=44, proc=0, action='pick up passenger')
|
||||
taxi: 2 Event(time=44, proc=2, action='pick up passenger')
|
||||
taxi: 0 Event(time=49, proc=0, action='drop off passenger')
|
||||
taxi: 0 Event(time=50, proc=0, action='going home')
|
||||
taxi: 2 Event(time=58, proc=2, action='drop off passenger')
|
||||
taxi: 2 Event(time=65, proc=2, action='pick up passenger')
|
||||
taxi: 2 Event(time=71, proc=2, action='drop off passenger')
|
||||
taxi: 2 Event(time=72, proc=2, action='going home')
|
||||
taxi: 1 Event(time=5, proc=1, action='leave garage')
|
||||
taxi: 1 Event(time=6, proc=1, action='pick up passenger')
|
||||
taxi: 2 Event(time=10, proc=2, action='leave garage')
|
||||
taxi: 2 Event(time=11, proc=2, action='pick up passenger')
|
||||
taxi: 2 Event(time=23, proc=2, action='drop off passenger')
|
||||
taxi: 0 Event(time=24, proc=0, action='drop off passenger')
|
||||
taxi: 2 Event(time=24, proc=2, action='pick up passenger')
|
||||
taxi: 2 Event(time=26, proc=2, action='drop off passenger')
|
||||
taxi: 0 Event(time=30, proc=0, action='pick up passenger')
|
||||
taxi: 2 Event(time=31, proc=2, action='pick up passenger')
|
||||
taxi: 0 Event(time=43, proc=0, action='drop off passenger')
|
||||
taxi: 0 Event(time=44, proc=0, action='going home')
|
||||
taxi: 2 Event(time=46, proc=2, action='drop off passenger')
|
||||
taxi: 2 Event(time=49, proc=2, action='pick up passenger')
|
||||
taxi: 1 Event(time=70, proc=1, action='drop off passenger')
|
||||
taxi: 2 Event(time=70, proc=2, action='drop off passenger')
|
||||
taxi: 2 Event(time=71, proc=2, action='pick up passenger')
|
||||
taxi: 2 Event(time=79, proc=2, action='drop off passenger')
|
||||
taxi: 1 Event(time=88, proc=1, action='pick up passenger')
|
||||
taxi: 2 Event(time=92, proc=2, action='pick up passenger')
|
||||
taxi: 2 Event(time=98, proc=2, action='drop off passenger')
|
||||
taxi: 2 Event(time=99, proc=2, action='going home')
|
||||
taxi: 1 Event(time=102, proc=1, action='drop off passenger')
|
||||
taxi: 1 Event(time=104, proc=1, action='pick up passenger')
|
||||
taxi: 1 Event(time=135, proc=1, action='drop off passenger')
|
||||
taxi: 1 Event(time=136, proc=1, action='pick up passenger')
|
||||
taxi: 1 Event(time=151, proc=1, action='drop off passenger')
|
||||
taxi: 1 Event(time=152, proc=1, action='going home')
|
||||
*** end of events ***
|
||||
# END TAXI_SAMPLE_RUN
|
||||
|
||||
52
control/yield_from_expansion.py
Normal file
52
control/yield_from_expansion.py
Normal file
@@ -0,0 +1,52 @@
|
||||
# Code below is the expansion of the statement:
|
||||
#
|
||||
# RESULT = yield from EXPR
|
||||
#
|
||||
# Copied verbatim from the Formal Semantics section of
|
||||
# PEP 380 -- Syntax for Delegating to a Subgenerator
|
||||
#
|
||||
# https://www.python.org/dev/peps/pep-0380/#formal-semantics
|
||||
|
||||
|
||||
# BEGIN YIELD_FROM_EXPANSION
|
||||
_i = iter(EXPR) # <1>
|
||||
try:
|
||||
_y = next(_i) # <2>
|
||||
except StopIteration as _e:
|
||||
_r = _e.value # <3>
|
||||
else:
|
||||
while 1: # <4>
|
||||
try:
|
||||
_s = yield _y # <5>
|
||||
except GeneratorExit as _e: # <6>
|
||||
try:
|
||||
_m = _i.close
|
||||
except AttributeError:
|
||||
pass
|
||||
else:
|
||||
_m()
|
||||
raise _e
|
||||
except BaseException as _e: # <7>
|
||||
_x = sys.exc_info()
|
||||
try:
|
||||
_m = _i.throw
|
||||
except AttributeError:
|
||||
raise _e
|
||||
else: # <8>
|
||||
try:
|
||||
_y = _m(*_x)
|
||||
except StopIteration as _e:
|
||||
_r = _e.value
|
||||
break
|
||||
else: # <9>
|
||||
try: # <10>
|
||||
if _s is None: # <11>
|
||||
_y = next(_i)
|
||||
else:
|
||||
_y = _i.send(_s)
|
||||
except StopIteration as _e: # <12>
|
||||
_r = _e.value
|
||||
break
|
||||
|
||||
RESULT = _r # <13>
|
||||
# END YIELD_FROM_EXPANSION
|
||||
Reference in New Issue
Block a user