Skip to content

Instantly share code, notes, and snippets.

@christianp
Last active June 2, 2023 09:35
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 christianp/0e8e12510889e634ee125791d250919e to your computer and use it in GitHub Desktop.
Save christianp/0e8e12510889e634ee125791d250919e to your computer and use it in GitHub Desktop.
Explore the full space of states accessible in the Circular Lights Out puzzle. It can be solved if every light can be turned on at the same time.
# The other set of rules, implemented at https://codepen.io/xenohunter/full/GRpaKjR
# You can flip any three adjacent lights.
def find_all_states_12_lamps(num_lights):
reachable = set()
# Sets of lights that can be changed simultaneously
change_sets = [((i+num_lights-1)%num_lights, i, (i+1)%num_lights) for i in range(num_lights)]
queue = [tuple([True]+[False]*(num_lights-1))]
while len(queue):
s = queue.pop()
if s not in reachable:
reachable.add(s)
for c in change_sets:
ns = tuple([not s[i] if i in c else s[i] for i in range(num_lights)])
queue.append(ns)
can_be_solved = tuple([True]*num_lights) in reachable
return can_be_solved
for i in range(1,16):
if find_all_states_12_lamps(i):
print(f"{i} lights can be solved")
# The Circular Lights Out puzzle at https://somethingorotherwhatever.com/circular-lights-out/
# You can flip any evenly-spaced set of lights if they are all in the same state.
def find_all_states(num_lights):
shortest_route = {}
# Sets of lights that can be changed simultaneously
change_sets = set()
for i in range(num_lights):
for d in range(1,num_lights):
if num_lights%d > 0:
continue
s = tuple(sorted(set((i+k*d) % num_lights for k in range(num_lights//d))))
change_sets.add(s)
change_sets
queue = [(tuple([True]+[False]*(num_lights-1)),[])]
step = 0
while len(queue):
step += 1
s,r = queue.pop()
if s in shortest_route:
record_r = len(shortest_route[s])
if len(r) < record_r:
shortest_route[s] = r
else:
shortest_route[s] = r
for c in change_sets:
if len(set(s[i] for i in c))==1:
ns = tuple([not s[i] if i in c else s[i] for i in range(num_lights)])
queue.append((ns,r+[c]))
print(f"{num_lights} lights")
can_be_solved = tuple([True]*num_lights) in shortest_route
print("Can be solved!" if can_be_solved else "Not solvable")
#for s in sorted(shortest_route.keys()):
# print(' '+''.join('*' if x else '_' for x in s))
return shortest_route
for i in range(1,20):
find_all_states(i)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment