import matplotlib.pyplot as plt
import matplotlib.animation as animation
import numpy as np
# Parameters
n = 100
positions = list(range(1, n + 1))
angle = np.linspace(0, 2 * np.pi, n, endpoint=False)
# Set up figure
fig, ax = plt.subplots(figsize=(8, 8))
ax.axis('off')
sc = ax.scatter([], [], s=400)
# Annotate numbers
texts = []
for i in range(n):
x, y = np.cos(angle[i]), np.sin(angle[i])
txt = ax.text(x, y, str(i+1), ha='center', va='center', fontsize=8, color='white',
bbox=dict(boxstyle='circle,pad=0.3', fc='blue', ec='black', lw=1))
texts.append(txt)
# State variables
current_index = 0
def update(frame):
global current_index, positions, texts
if len(positions) <= 1:
return
# Calculate index of person to be removed
remove_index = (current_index + 1) % len(positions)
# Remove from display
texts[positions[remove_index] - 1].set_visible(False)
# Remove from list
del positions[remove_index]
# Next killer
current_index = remove_index % len(positions)
# Redraw remaining people
new_angle = np.linspace(0, 2 * np.pi, len(positions), endpoint=False)
for i, pos in enumerate(positions):
x, y = np.cos(new_angle[i]), np.sin(new_angle[i])
texts[pos - 1].set_position((x, y))
ani = animation.FuncAnimation(fig, update, frames=100, interval=700, repeat=False)
plt.show()
aW1wb3J0IG1hdHBsb3RsaWIucHlwbG90IGFzIHBsdAppbXBvcnQgbWF0cGxvdGxpYi5hbmltYXRpb24gYXMgYW5pbWF0aW9uCmltcG9ydCBudW1weSBhcyBucAoKIyBQYXJhbWV0ZXJzCm4gPSAxMDAKcG9zaXRpb25zID0gbGlzdChyYW5nZSgxLCBuICsgMSkpCmFuZ2xlID0gbnAubGluc3BhY2UoMCwgMiAqIG5wLnBpLCBuLCBlbmRwb2ludD1GYWxzZSkKCiMgU2V0IHVwIGZpZ3VyZQpmaWcsIGF4ID0gcGx0LnN1YnBsb3RzKGZpZ3NpemU9KDgsIDgpKQpheC5heGlzKCdvZmYnKQpzYyA9IGF4LnNjYXR0ZXIoW10sIFtdLCBzPTQwMCkKCiMgQW5ub3RhdGUgbnVtYmVycwp0ZXh0cyA9IFtdCmZvciBpIGluIHJhbmdlKG4pOgogICAgeCwgeSA9IG5wLmNvcyhhbmdsZVtpXSksIG5wLnNpbihhbmdsZVtpXSkKICAgIHR4dCA9IGF4LnRleHQoeCwgeSwgc3RyKGkrMSksIGhhPSdjZW50ZXInLCB2YT0nY2VudGVyJywgZm9udHNpemU9OCwgY29sb3I9J3doaXRlJywKICAgICAgICAgICAgICAgICAgYmJveD1kaWN0KGJveHN0eWxlPSdjaXJjbGUscGFkPTAuMycsIGZjPSdibHVlJywgZWM9J2JsYWNrJywgbHc9MSkpCiAgICB0ZXh0cy5hcHBlbmQodHh0KQoKIyBTdGF0ZSB2YXJpYWJsZXMKY3VycmVudF9pbmRleCA9IDAKCmRlZiB1cGRhdGUoZnJhbWUpOgogICAgZ2xvYmFsIGN1cnJlbnRfaW5kZXgsIHBvc2l0aW9ucywgdGV4dHMKCiAgICBpZiBsZW4ocG9zaXRpb25zKSA8PSAxOgogICAgICAgIHJldHVybgoKICAgICMgQ2FsY3VsYXRlIGluZGV4IG9mIHBlcnNvbiB0byBiZSByZW1vdmVkCiAgICByZW1vdmVfaW5kZXggPSAoY3VycmVudF9pbmRleCArIDEpICUgbGVuKHBvc2l0aW9ucykKCiAgICAjIFJlbW92ZSBmcm9tIGRpc3BsYXkKICAgIHRleHRzW3Bvc2l0aW9uc1tyZW1vdmVfaW5kZXhdIC0gMV0uc2V0X3Zpc2libGUoRmFsc2UpCgogICAgIyBSZW1vdmUgZnJvbSBsaXN0CiAgICBkZWwgcG9zaXRpb25zW3JlbW92ZV9pbmRleF0KCiAgICAjIE5leHQga2lsbGVyCiAgICBjdXJyZW50X2luZGV4ID0gcmVtb3ZlX2luZGV4ICUgbGVuKHBvc2l0aW9ucykKCiAgICAjIFJlZHJhdyByZW1haW5pbmcgcGVvcGxlCiAgICBuZXdfYW5nbGUgPSBucC5saW5zcGFjZSgwLCAyICogbnAucGksIGxlbihwb3NpdGlvbnMpLCBlbmRwb2ludD1GYWxzZSkKICAgIGZvciBpLCBwb3MgaW4gZW51bWVyYXRlKHBvc2l0aW9ucyk6CiAgICAgICAgeCwgeSA9IG5wLmNvcyhuZXdfYW5nbGVbaV0pLCBucC5zaW4obmV3X2FuZ2xlW2ldKQogICAgICAgIHRleHRzW3BvcyAtIDFdLnNldF9wb3NpdGlvbigoeCwgeSkpCgphbmkgPSBhbmltYXRpb24uRnVuY0FuaW1hdGlvbihmaWcsIHVwZGF0ZSwgZnJhbWVzPTEwMCwgaW50ZXJ2YWw9NzAwLCByZXBlYXQ9RmFsc2UpCnBsdC5zaG93KCk=