Source code for tryalgo.laser_mirrors

#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""\
Orienting mirrors to allow connectivity by a laser beam

jill-jênn vie et christoph dürr - 2014-2019
"""

# snip{ laser-miroir-preparation
# directions
UP = 0
LEFT = 1
DOWN = 2
RIGHT = 3
# orientations None:? 0:/ 1:\

# destination UP          LEFT        DOWN           RIGHT
reflex = [[RIGHT, LEFT], [DOWN, UP], [LEFT, RIGHT], [UP, DOWN]]


# pylint: disable=unused-variable, unused-argument
[docs] def laser_mirrors(rows, cols, mir): """Orienting mirrors to allow reachability by laser beam :param int rows: :param int cols: rows and cols are the dimension of the grid :param mir: list of mirror coordinates, except mir[0]= laser entrance, mir[-1]= laser exit. :complexity: :math:`O(2^n)` """ # build structures n = len(mir) orien = [None] * (n + 2) orien[n] = 0 # arbitrary orientations orien[n + 1] = 0 succ = [[None for direc in range(4)] for i in range(n + 2)] L = [(mir[i][0], mir[i][1], i) for i in range(n)] L.append((0, -1, n)) # enter L.append((0, cols, n + 1)) # exit last_r, last_i = None, None for (r, c, i) in sorted(L): # sweep by row if last_r == r: succ[i][LEFT] = last_i succ[last_i][RIGHT] = i last_r, last_i = r, i last_c = None for (r, c, i) in sorted(L, key=lambda rci: (rci[1], rci[0])): if last_c == c: # sweep by column succ[i][UP] = last_i succ[last_i][DOWN] = i last_c, last_i = c, i if solve(succ, orien, n, RIGHT): # exploration return orien[:n] return None
# snip} # snip{ laser-miroir-exploration
[docs] def solve(succ, orien, i, direc): """Can a laser leaving mirror i in direction direc reach exit ? :param i: mirror index :param direc: direction leaving mirror i :param orient: orient[i]=orientation of mirror i :param succ: succ[i][direc]=succ mirror reached when leaving i in direction direc """ assert orien[i] is not None j = succ[i][direc] if j is None: # basic case return False if j == len(orien) - 1: return True if orien[j] is None: # try both orientations for x in [0, 1]: orien[j] = x if solve(succ, orien, j, reflex[direc][x]): return True orien[j] = None return False return solve(succ, orien, j, reflex[direc][orien[j]])
# snip}