Enable Javascript in your browser and then refresh this page, for a much enhanced experience.
OOP solution in Uncategorized category for Wall Keeper by pohmelie
import collections
import itertools
import contextlib
class LightsOutField:
def __init__(self, on_panels):
self._f = collections.ChainMap(collections.defaultdict(lambda: False))
for n in on_panels:
y, x = divmod(n - 1, 5)
self._f[x, y] = True
@contextlib.contextmanager
def sub_field(self):
self._f = self._f.new_child()
yield
self._f = self._f.parents
def _do_step(self, x, y):
for dx, dy in ((0, 0), (1, 0), (0, 1), (-1, 0), (0, -1)):
self._f[x + dx, y + dy] = not self._f[x + dx, y + dy]
def catch_lights(self):
steps = []
for y in range(4):
for x in range(5):
if self._f[x, y]:
self._do_step(x, y + 1)
steps.append(x + (y + 1) * 5 + 1)
return steps
def brute_force_first_row(self):
for state in itertools.product([True, False], repeat=5):
with self.sub_field():
steps = []
for x, v in enumerate(state):
if v:
self._do_step(x, 0)
steps.append(x + 1)
steps += self.catch_lights()
if self.solved:
return steps
raise RuntimeError("Unsolvable field")
@property
def solved(self):
points = itertools.product(range(5), repeat=2)
return not any(map(self._f.__getitem__, points))
def __repr__(self):
lines = []
for y in range(5):
line = []
for x in range(5):
if self._f[x, y]:
line.append("*")
else:
line.append(".")
lines.append("".join(line))
return "\n".join(lines)
def wall_keeper(on_panels):
f = LightsOutField(on_panels)
steps = f.catch_lights()
if not f.solved:
steps += f.brute_force_first_row()
return steps
Sept. 16, 2017