Skip to content

Instantly share code, notes, and snippets.

@yattom
Last active June 24, 2017 05:26
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save yattom/e591836b57073374b5b94657ad87ce6a to your computer and use it in GitHub Desktop.
Save yattom/e591836b57073374b5b94657ad87ce6a to your computer and use it in GitHub Desktop.

PLoP(Pattern Language of Programming)のイベントで知ったアイスブレークがあります。

  1. 全員が輪になる
  2. 最初の1人(司会など)がスタートとして、右の人に"tic"、左の人に"toc"という
  3. あとは、以下のルールで伝えていく
    • なにか(ticかtoc)言われたら、"What?"と聞き返す
    • "What?"と右から言われたら、そのまま左に"What?"と流す。左から言われたら右に
    • 2回目になにか(ticかtoc)言われたら、その言葉を次の人に伝える(右から来たら左へ、左から来たら右へ)
  4. ぐるっと回って最初の人までticとtocが伝わったら、おわり

言葉で説明するとよくわからないですが、実際やってみると簡単です。全員がひそひそ話をひそひそと伝え合って最後にしーんと丸く収まるという、不思議な感覚があります。

この動きをプログラムで再現してみました。

python tictoc.py 15

引数で人数を指定できます。

書いてみて分かったこと:

  • 人数×人数回で終わる(ここでは1回=右回りと左回りで1回ずつ発話すること。最初の人の最初の発話も、ticとtocあわせて1回と数える)
  • 1人の発話の回数は、全員同じで、人数×2
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)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment