Skip to content

Instantly share code, notes, and snippets.

@elendiastarman
Last active April 16, 2018 00:02
Show Gist options
  • Save elendiastarman/2440ee665c2e051b5691f501ab432fd4 to your computer and use it in GitHub Desktop.
Save elendiastarman/2440ee665c2e051b5691f501ab432fd4 to your computer and use it in GitHub Desktop.
Distinct line configurations on a cube
# If each face of a cube is marked with a diagonal line between opposing corners,
# how many distinct configurations are there considering rotations and reflections?
# Vertex labeling
# 2-----3
# |\ |\
# | \ | \
# | 0-----1
# | | | |
# 6--|--7 |
# \ | \ |
# \| \|
# 4-----5
reflection = [(0, 4), (1, 5), (2, 6), (3, 7)]
rotations = [
# identity
[],
# 90 deg around face-centered axis
[(0, 1, 3, 2), (4, 5, 7, 6)],
[(0, 2, 3, 1), (4, 6, 7, 5)],
[(0, 1, 5, 4), (2, 3, 7, 6)],
[(0, 4, 5, 1), (2, 6, 7, 3)],
[(0, 4, 6, 2), (1, 5, 7, 3)],
[(0, 2, 6, 4), (1, 3, 7, 5)],
# 180 deg around face-centered axis
[(0, 3), (1, 2), (4, 7), (5, 6)],
[(0, 5), (1, 4), (2, 7), (3, 6)],
[(0, 6), (2, 4), (1, 7), (3, 5)],
# 180 deg around edge-centered axis
[(0, 1), (2, 5), (3, 4), (6, 7)],
[(0, 7), (1, 6), (2, 3), (4, 5)],
[(0, 2), (1, 6), (3, 4), (5, 7)],
[(0, 7), (1, 3), (4, 6), (2, 5)],
[(0, 4), (1, 6), (2, 5), (3, 7)],
[(0, 7), (1, 5), (2, 6), (3, 4)],
# 120 deg around vertex-centered axis
[(1, 2, 4), (3, 6, 5)],
[(1, 4, 2), (3, 5, 6)],
[(0, 3, 5), (2, 7, 4)],
[(0, 5, 3), (2, 4, 7)],
[(0, 3, 6), (1, 7, 4)],
[(0, 6, 3), (1, 4, 7)],
[(0, 5, 6), (1, 7, 2)],
[(0, 6, 5), (1, 2, 7)],
]
edge_choices = [
[(0, 3), (1, 2)],
[(0, 5), (1, 4)],
[(1, 7), (3, 5)],
[(3, 6), (2, 7)],
[(2, 4), (0, 6)],
[(4, 7), (5, 6)],
]
edge_sets = []
for i in range(64):
b = bin(i)[2:]
edge_set = []
for j in range(6):
if j >= len(b) or b[-j - 1] == '0':
edge_set.append(edge_choices[j][0])
else:
edge_set.append(edge_choices[j][1])
edge_sets.append(edge_set)
def transform(symmetry, edge_set):
transformed_edge_set = []
for edge in edge_set:
transformed_edge = []
for endpoint in edge:
new_endpoint = endpoint
for cycle in symmetry:
if endpoint in cycle:
new_endpoint = cycle[(cycle.index(endpoint) + 1) % len(cycle)]
break
transformed_edge.append(new_endpoint)
transformed_edge_set.append(tuple(sorted(transformed_edge)))
return transformed_edge_set
def compose(*symmetries):
symmetries = list(symmetries)
comp = symmetries.pop()
while symmetries:
sym = symmetries.pop()
labels = []
for cycle in comp + sym:
labels.extend(cycle)
labels = sorted(list(set(labels)), reverse=True)
new_comp = []
while labels:
new_cycle = [labels.pop()]
while len(new_cycle) == 1 or new_cycle[0] != new_cycle[-1]:
new_label = new_cycle[-1]
for cycle in comp + sym:
if new_label in cycle:
new_label = cycle[(cycle.index(new_label) + 1) % len(cycle)]
new_cycle.append(new_label)
if new_label in labels:
labels.remove(new_label)
if len(new_cycle) > 2:
new_comp.append(tuple(new_cycle[:-1]))
comp = new_comp
return comp
def distinct(symmetries, edge_sets):
distinct_sets = []
for edge_set in edge_sets:
transformed = []
for sym in symmetries:
transformed.append(sorted(transform(sym, edge_set)))
transformed.sort()
if transformed[0] not in distinct_sets:
distinct_sets.append(transformed[0])
return distinct_sets
all_symmetries = rotations + [compose(rotation, reflection) for rotation in rotations]
# # uncomment this if you want interactivity
# import IPython # noqa
# IPython.embed()
total = 0
for symmetry in all_symmetries:
total += sum([sorted(transform(symmetry, edge_set)) == sorted(edge_set) for edge_set in edge_sets])
print("Number of distinct configurations: {} / {} = {}".format(total, len(all_symmetries), total / len(all_symmetries)))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment