Last active
June 2, 2023 09:35
-
-
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.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# 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") |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# 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