|
LEFT = 0 |
|
RIGHT = 1 |
|
def theother(side): |
|
if side == LEFT: |
|
return RIGHT |
|
else: |
|
return LEFT |
|
|
|
WAITING = 0 |
|
ASKING = 1 |
|
|
|
class Node: |
|
def __init__(self, name): |
|
self.name = name |
|
self.connections = { LEFT: None, RIGHT: None } |
|
self.mode = { LEFT: WAITING, RIGHT: WAITING } |
|
self.say_count = 0 |
|
|
|
def get_left(self): |
|
return self.connections[LEFT] |
|
|
|
def set_left(self, value): |
|
assert self.connections[LEFT] == None |
|
self.connections[LEFT] = value |
|
|
|
left = property(get_left, set_left) |
|
|
|
def get_right(self): |
|
return self.connections[RIGHT] |
|
|
|
def set_right(self, value): |
|
assert self.connections[RIGHT] == None |
|
self.connections[RIGHT] = value |
|
|
|
right = property(get_right, set_right) |
|
|
|
def hear(self, side_from, message): |
|
if message == "What?": |
|
def relay(): |
|
self.mode[theother(side_from)] = ASKING |
|
return self.say(theother(side_from), message) |
|
return relay |
|
if self.mode[side_from] == WAITING: |
|
def askback(): |
|
self.mode[side_from] = ASKING |
|
return self.say(side_from, "What?") |
|
return askback |
|
elif self.mode[side_from] == ASKING: |
|
def relay(): |
|
self.mode[side_from] = WAITING |
|
return self.say(theother(side_from), message) |
|
return relay |
|
raise RuntimeError() |
|
|
|
def say(self, side_to, message): |
|
print("{0}->{1} '{2}'".format(self.name, self.connections[side_to].name, message)) |
|
self.say_count += 1 |
|
return self.connections[side_to].hear(theother(side_to), message) |
|
|
|
|
|
class StartNode(Node): |
|
def start(self): |
|
acts = [] |
|
acts.append(self.say(LEFT, "tic")) |
|
acts.append(self.say(RIGHT, "toc")) |
|
return acts |
|
|
|
def hear(self, side_from, message): |
|
if message == "What?": |
|
if side_from == LEFT: |
|
def say_tic(): |
|
return self.say(LEFT, "tic") |
|
return say_tic |
|
if side_from == RIGHT: |
|
def say_toc(): |
|
return self.say(RIGHT, "toc") |
|
return say_toc |
|
if message == "tic" and side_from == RIGHT: |
|
return None |
|
if message == "toc" and side_from == LEFT: |
|
return None |
|
raise RuntimeError() |
|
|
|
|
|
def connect(n1, n2): |
|
n1.left = n2 |
|
n2.right = n1 |
|
|
|
def test(count): |
|
print("{0} nodes".format(count)) |
|
nodes = [StartNode("N1")] |
|
for i in range(count - 1): |
|
nodes.append(Node("N{0}".format(i + 2))) |
|
|
|
for i in range(len(nodes) - 1): |
|
connect(nodes[i], nodes[i + 1]) |
|
connect(nodes[-1], nodes[0]) |
|
|
|
rnd = 1 |
|
print("Round: {0}".format(rnd)) |
|
acts = nodes[0].start() |
|
|
|
while acts: |
|
rnd += 1 |
|
print("Round: {0}".format(rnd)) |
|
next_acts = [] |
|
for act in acts: |
|
n = act() |
|
if n: |
|
next_acts.append(n) |
|
acts = next_acts |
|
print("Completed on Round {0}".format(rnd)) |
|
|
|
total = sum([n.say_count for n in nodes]) |
|
top = max(nodes, key=lambda n: n.say_count) |
|
bottom = min(nodes, key=lambda n: n.say_count) |
|
print("total {0} say, {1} say per node".format(total, total / len(nodes))) |
|
|
|
if __name__=='__main__': |
|
import sys |
|
try: |
|
count = int(sys.argv[1]) |
|
except: |
|
count = 10 |
|
test(count) |