Exemple #1
0
def find_portals(maze):
    """Find each inner and outer portal."""
    # inner_portals[inner_location] = label
    inner_portals = {}
    # outer_portals[outer_location] = label
    outer_portals = {}

    # Look at every point in the maze
    for pos, tile in maze.items():
        # If it's traversable look at everything adjacent to it
        if tile == ".":
            for offset in ((1, 0), (0, 1), (-1, 0), (0, -1)):
                adj = tuple_add(pos, offset)
                adj_tile = maze[adj]
                # If it's the start of a label find the whole label
                if adj_tile.isupper():
                    next_pos = tuple_add(adj, offset)
                    next_tile = maze[next_pos]
                    assert next_tile.isupper(), "ill-formed label found"
                    after_pos = tuple_add(next_pos, offset)
                    label = label_for(adj_tile, next_tile, offset)
                    if after_pos in maze:
                        inner_portals[pos] = label
                    else:
                        outer_portals[pos] = label
    return inner_portals, outer_portals
Exemple #2
0
 def get_tiles_in_aoe(self, user, map, target_loc):
     if target_loc[0] > user.location[0]:
         aoe = [
             target_loc,
             tuple_add(target_loc, (1, 0)),
             tuple_add(target_loc, (2, 0))
         ]
     elif target_loc[0] < user.location[0]:
         aoe = [
             target_loc,
             tuple_add(target_loc, (-1, 0)),
             tuple_add(target_loc, (-2, 0))
         ]
     elif target_loc[1] > user.location[1]:
         aoe = [
             target_loc,
             tuple_add(target_loc, (0, 1)),
             tuple_add(target_loc, (0, 2))
         ]
     elif target_loc[1] < user.location[1]:
         aoe = [
             target_loc,
             tuple_add(target_loc, (0, -1)),
             tuple_add(target_loc, (0, -2))
         ]
     else:
         aoe = []
     return [map.get_tile(loc) for loc in aoe if map.on_map(loc)]
Exemple #3
0
def optimize_polynomial(pol):
    r"""
    Optimization polynomial by representing it as an SDP in the
    appropriate basis
    TODO: Support constraints

    \min_y c^\top y
           subject to M(y) \succeq 0
           y_1 = 1

    @param poly       - polynomial to optimize
    @param basis      - basis for the polynomial (can be 'power',
                        'symmetric', 'symmetric_irreducible')
    @returns (p*, y*) - the optimal value of the polynomial and
                        y* = E_\mu[b(x)].
    """

    # basis in sorted order from 1 to largest
    # Get the largest monomial term
    max_degree = get_max_degree(pol)
    half_degree = map(lambda deg: int(np.ceil(deg / 2.)), max_degree)

    # Generate basis
    basis = list(it.product(*[range(deg + 1) for deg in max_degree]))
    half_basis = list(it.product(*[range(deg + 1) for deg in half_degree]))
    N, M = len(basis), len(half_basis)

    # The coefficient term
    c = np.matrix([float(pol.nth(*elem)) for elem in basis]).T
    # The inequality term, enforcing sos-ness
    G = np.zeros((M**2, N))
    for i, j in it.product(xrange(M), xrange(M)):
        e1, e2 = half_basis[i], half_basis[j]
        monom = tuple_add(e1, e2)
        k = basis.index(monom)
        if k != -1:
            G[M * i + j, k] = 1
    h = np.zeros((M, M))

    # Finally, y_1 = 1
    A = np.zeros((1, N))
    A[0, 0] = 1
    b = np.zeros(1)
    b[0] = 1

    sol = solvers.sdp(
        c=matrix(c),
        Gs=[matrix(-G)],
        hs=[matrix(h)],
        A=matrix(A),
        b=matrix(b),
    )
    assert sol['status'] == 'optimal'

    return dict([(get_monom(pol, coeff), val)
                 for coeff, val in zip(basis, list(sol['x']))])
Exemple #4
0
 def get_tiles_in_aoe(self, user, map, target_loc):
     if target_loc[0] > user.location[0]:
         aoe = [target_loc, tuple_add(target_loc, (1,0)), tuple_add(target_loc, (2,0))]
     elif target_loc[0] < user.location[0]:
         aoe = [target_loc, tuple_add(target_loc, (-1,0)), tuple_add(target_loc, (-2,0))]
     elif target_loc[1] > user.location[1]:
         aoe = [target_loc, tuple_add(target_loc, (0,1)), tuple_add(target_loc, (0,2))]
     elif target_loc[1] < user.location[1]:
         aoe = [target_loc, tuple_add(target_loc, (0,-1)), tuple_add(target_loc, (0,-2))]
     else:
         aoe = []
     return [map.get_tile(loc) for loc in aoe if map.on_map(loc)]
Exemple #5
0
def describe_moment_polynomial(syms, moments_x, moment_y, alpha, b):
    """
    Computes the moment polynomial for E[x^alpha, y^b]
    """
    D = len(syms)
    expr = -moment_y
    coeffs = sp.ntheory.multinomial_coefficients(D, b)
    for beta in partitions(D, b):
        expr += coeffs[beta] * monomial(syms, beta) * moments_x[tuple_add(alpha, beta)]
    return expr
Exemple #6
0
def optimize_polynomial(pol):
    r"""
    Optimization polynomial by representing it as an SDP in the
    appropriate basis
    TODO: Support constraints

    \min_y c^\top y
           subject to M(y) \succeq 0
           y_1 = 1

    @param poly       - polynomial to optimize
    @param basis      - basis for the polynomial (can be 'power',
                        'symmetric', 'symmetric_irreducible')
    @returns (p*, y*) - the optimal value of the polynomial and
                        y* = E_\mu[b(x)].
    """

    # basis in sorted order from 1 to largest
    # Get the largest monomial term
    max_degree = get_max_degree(pol)
    half_degree = map( lambda deg: int(np.ceil(deg/2.)), max_degree)

    # Generate basis
    basis = list(it.product( *[range(deg + 1) for deg in max_degree] ) )
    half_basis = list(it.product( *[range(deg + 1) for deg in half_degree] ) )
    N, M = len(basis), len(half_basis)

    # The coefficient term
    c = np.matrix([float(pol.nth(*elem)) for elem in basis]).T
    # The inequality term, enforcing sos-ness
    G = np.zeros( ( M**2, N ) )
    for i, j in it.product(xrange(M), xrange(M)):
        e1, e2 = half_basis[i], half_basis[j]
        monom = tuple_add(e1,e2)
        k = basis.index(monom)
        if k != -1:
            G[ M * i + j, k ] = 1
    h = np.zeros((M, M))

    # Finally, y_1 = 1
    A = np.zeros((1, N))
    A[0,0] = 1
    b = np.zeros(1)
    b[0] = 1

    sol = solvers.sdp(
            c = matrix(c),
            Gs = [matrix(-G)],
            hs = [matrix(h)],
            A  = matrix(A),
            b  = matrix(b),
            )
    assert sol['status'] == 'optimal'

    return dict([ (get_monom(pol,coeff), val) for coeff, val in zip(basis, list(sol['x'])) ] )
Exemple #7
0
def describe_moment_polynomial(syms, moments_x, moment_y, alpha, b):
    """
    Computes the moment polynomial for E[x^alpha, y^b]
    """
    D = len(syms)
    expr = -moment_y
    coeffs = sp.ntheory.multinomial_coefficients(D, b)
    for beta in partitions(D, b):
        expr += coeffs[beta] * monomial(syms, beta) * moments_x[tuple_add(
            alpha, beta)]
    return expr
Exemple #8
0
def compute_exact_y_moments(ws, pis, moments_x, alpha, b):
    """
    Compute the exact moments E[x^a y^b] using coefficients ws, pis and moments_x.
    """
    D, _ = ws.shape
    coeffs = sp.ntheory.multinomial_coefficients(D, b)

    ret = 0.
    for beta in partitions(D, b):
        ret += coeffs[beta] * evaluate_mixture(ws, pis, beta) * moments_x[tuple_add(alpha, beta)]
    return ret
Exemple #9
0
def compute_exact_y_moments(ws, pis, moments_x, alpha, b):
    """
    Compute the exact moments E[x^a y^b] using coefficients ws, pis and moments_x.
    """
    D, _ = ws.shape
    coeffs = sp.ntheory.multinomial_coefficients(D, b)

    ret = 0.
    for beta in partitions(D, b):
        ret += coeffs[beta] * evaluate_mixture(
            ws, pis, beta) * moments_x[tuple_add(alpha, beta)]
    return ret
Exemple #10
0
def part2(maze, state):
    """Solve for the answer to part 2."""
    # Section the maze and add the robots
    replacement = ["@#@", "###", "@#@"]
    start = state["start"]
    for x_offset, y_offset in itertools.product((-1, 0, 1), repeat=2):
        maze_idx = tuple_add(start, (x_offset, y_offset))
        maze[maze_idx] = replacement[y_offset + 1][x_offset + 1]

    # The strategy here is basically the same as part 1, only slight change in the DFS

    # Get some data out of the maze
    robots = frozenset(pos for pos, tile in maze.items() if tile == "@")
    keys = state["keys"]
    doors = state["doors"]
    key_for = state["key_for"]

    # Mark the shortest paths similar to part 1, but including all 4 start positions now
    paths = {}
    for robot in robots:
        mark_paths(maze, robot, keys, doors, paths)
    for key in keys:
        mark_paths(maze, key, keys, doors, paths)

    @functools.lru_cache(maxsize=None)
    def shortest_tour(robots, unlocked=frozenset()):
        """Find the shortest number of steps to get all keys."""
        # Use DFS
        remaining = keys - unlocked
        if not remaining:
            return 0
        # Brute force all the places each robot could go next, thank you lru_cache
        return min(
            path.dist + shortest_tour(
                robots - {mover} | {path.end},
                unlocked | path.keys | {path.end},
            ) for mover in robots for path in
            [paths[mover, key] for key in remaining if (mover, key) in paths]
            if all(key_for[door] in unlocked for door in path.doors))

    return shortest_tour(robots)
Exemple #11
0
def process(input):
    instrs = input.strip().splitlines()
    loc = (0, 0)
    way = (10, 1)
    dir = 'E'
    for instr in instrs:
        cmd, val = instr[0], int(instr[1:])
        if cmd == 'F':
            move = tuple([val * x for x in way])
            loc = util.tuple_add(loc, move)
        elif cmd in ['L', 'R']:
            repeat = int(val / 90)
            for _ in range(repeat):
                way = way[1], way[0]
                if cmd == 'L':
                    way = (way[0] * -1, way[1])
                else:
                    way = (way[0], way[1] * -1)
        else:
            way = util.coord_move(way, cmd, val)
        print(cmd, val, '->', loc, way)
    return util.taxi_distance(loc)
Exemple #12
0
def count_trees(input, dir):
    input = input.strip()
    grid = util.text_to_grid(input)
    y_size = len(grid)
    x_size = len(grid[0])

    num_trees = 0
    loc = (0, 0)
    while True:
        loc = util.tuple_add(loc, dir)
        # Stop after reaching the bottom
        if loc[1] >= y_size:
            break
        # Loop around at the horizontal edge
        if loc[0] >= x_size:
            loc = (loc[0] - x_size, loc[1])
        is_tree = grid[loc[1]][loc[0]] == '#'
        print('loc', loc, ':', is_tree)
        if is_tree:
            num_trees += 1

    return num_trees
Exemple #13
0
 def calc_move(self, direction):
     """Calculate the resulting position of moving in a direction."""
     return tuple_add(self.pos, DIRECTION_TO_OFFSET[direction])