Beispiel #1
0
def part2():
    cur_pos = Coord(0, 0)
    cur_waypoint = Coord(10, 1)

    def _rotate_waypoint(diff):
        num_times = units // 90
        if dir == 'L':
            num_times = (4 - num_times) % 4

        for _ in range(num_times):
            diff = Coord(diff.y, -diff.x)

        return diff

    for dir, units in map(Inst.from_str, data):
        if dir in 'LR':
            cur_waypoint = cur_pos + _rotate_waypoint(cur_waypoint - cur_pos)
        elif dir == 'F':
            waypoint_diff = cur_waypoint - cur_pos
            cur_pos += waypoint_diff * units
            cur_waypoint = cur_pos + waypoint_diff
        else:
            cur_waypoint += Dir[dir].value * units

    return cur_pos.manhattan
Beispiel #2
0
    def board_dimensions(self) -> Dimensions:
        xs = {c.x for c in self.board}
        ys = {c.y for c in self.board}

        min_x, max_x = juxt(min, max)(xs)
        min_y, max_y = juxt(min, max)(ys)
        return Dimensions(Coord(min_x, min_y), Coord(max_x, max_y))
Beispiel #3
0
class Dir(Enum):
    n = Coord(0, 1)
    e = Coord(1, 0)
    s = Coord(0, -1)
    w = Coord(-1, 0)

    def from_offset(self, offset: int):
        return rot_map[(rot_map[self] + offset) % 4]
Beispiel #4
0
 def to_coord(cmd, val):
     match cmd:
         case 'forward':
             return Coord(val, 0)
         case 'down':
             return Coord(0, val)
         case 'up':
             return Coord(0, -val)
Beispiel #5
0
class Dir(Enum):
    N = Coord(0, 1)
    E = Coord(1, 0)
    S = Coord(0, -1)
    W = Coord(-1, 0)

    def rotate(self, dir, units):
        mult = 1 if dir == 'R' else -1
        return _list_dirs[(_list_dirs.index(self) + mult * units // 90) %
                          len(_list_dirs)]
Beispiel #6
0
    def _update_board(self, x, y, tile_id):
        if (x, y) == (-1, 0):
            self.score = tile_id
            return

        t = Tile(tile_id)
        if t is Tile.ball:
            self.ball_pos = Coord(x, y)
            return

        if t is Tile.paddle:
            self.paddle_pos = Coord(x, y)
        super()._update_board(x, y, tile_id)
Beispiel #7
0
def _gen_coords():
    """
    create coords in the order they would appear in the data structure in the docstring in aoc03_a
    coords:
    0, 0

    1, 0
    1, 1
    0, 1
    -1, 1
    -1, 0
    -1, -1,
    0, -1
    1, -1

    """
    for i, size in zip(count(1), count(3, 2)):
        cur = Coord(
            i,
            1 - i)  # the start of the next outer square (bottom right corner)
        cur_offset = Coord(0, 1)
        offset_dict = {
            Coord(i, i): Coord(-1, 0),
            Coord(-i, i): Coord(0, -1),
            Coord(-i, -i): Coord(1, 0),
        }
        yield cur
        n_elements = size**2 - (size - 2)**2
        for _ in range(n_elements - 1):
            cur += cur_offset
            yield cur
            cur_offset = offset_dict.get(cur, cur_offset)
Beispiel #8
0
def aoc03_b(value):
    """generate square with neighbors to figure out first > value occurrence

    represent square as dict of {coord: value}
    """
    offsets = {Coord(x, y) for x, y in product(range(-1, 2), range(-1, 2))}
    grid = {Coord(0, 0): 1}

    def _get_neighbor_vals(_c):
        return sum(grid.get(_c + o, 0) for o in offsets)

    for c in _gen_coords():
        v = grid[c] = _get_neighbor_vals(c)
        if v > value:
            return v
Beispiel #9
0
class Direction(Enum):
    up = Coord(0, -1)
    right = Coord(1, 0)
    down = Coord(0, 1)
    left = Coord(-1, 0)

    def rotated(self, val):
        """
        0: rotate 90 deg counter-clockwise
        1: rotate 90 deg clockwise
        """
        dirs = list(Direction)
        val = 2 * val - 1
        new_idx = (dirs.index(self) + val) % len(dirs)
        return dirs[new_idx]
Beispiel #10
0
def parse_file(fn):
    rows = U.read_file(fn, 2017, do_strip=False)
    return {
        Coord(c_num, r_num): v
        for r_num, r in enumerate(rows) for c_num, v in enumerate(r)
        if v not in set(' \n')
    }
Beispiel #11
0
 def __init__(self, program: Program):
     self._cur_pos = Coord(0, 0)
     self._map = Map()
     self._map[self._cur_pos] = Tile.empty
     self._prog = self._init_program(program)
     self._last_dir = None
     self._dirs = []
Beispiel #12
0
 def __init__(self, init_color=0):
     """colors are 0 (black) or 1 (white)"""
     self.whites: Set[Coord] = set()
     self._cur_pos = Coord(0, 0)
     if init_color:
         self.whites.add(self._cur_pos)
     self._cur_dir = Direction.up
     self._painted: Set[Coord] = set()
Beispiel #13
0
def aoc01_a(insts: List[Inst]):
    cur = Coord(0, 0)
    dir = Direction.up
    for i in insts:
        dir = turns[i.direction](dir)
        cur += dir.value * i.steps

    return cur.manhattan
Beispiel #14
0
    def _rotate_waypoint(diff):
        num_times = units // 90
        if dir == 'L':
            num_times = (4 - num_times) % 4

        for _ in range(num_times):
            diff = Coord(diff.y, -diff.x)

        return diff
Beispiel #15
0
    def traversed_coords(self, include_diag=False) -> set[Coord]:
        if not include_diag and self.is_diag:
            return set()

        (x1, y1), (x2, y2) = self
        if x1 == x2:  # vertical
            return {Coord(x1, v) for v in range(min(y1, y2), max(y1, y2) + 1)}

        if y1 == y2:  # horizontal
            return {Coord(v, y1) for v in range(min(x1, x2), max(x1, x2) + 1)}

        # diagonal
        x_off = 1 if x2 > x1 else -1
        y_off = 1 if y2 > y1 else -1
        return {
            self.c1 + m * Coord(x_off, y_off)
            for m in range(abs(x2 - x1) + 1)
        }
Beispiel #16
0
def aoc03_a(location):
    """only works where the location doesn't 'wrap around' from the bottom of the square

    e.g., based on this input:

    17  16  15  14  13
    18   5   4   3  12
    19   6   1   2  11
    20   7   8   9  10
    21  22  23---> ...

    [21, 25], [7, 9], and [1] would work, but 17, e.g, would not
    """
    side = get_square_side(location)
    end = side**2
    ec = side // 2
    end_coord = Coord(ec, ec)
    end_coord -= Coord(end - location, 0)
    return end_coord.manhattan
Beispiel #17
0
    def _add_to_grid(cell: Cell, coord: Coord = Coord(0, 0), rot: Dir = Dir.n):
        if cell in processed:
            return

        processed.add(cell)
        grid[coord] = rot, cell
        for cur_to_other, (other_to_cur, other_tile) in cell.conns.items():
            abs_dir_to_other = _get_dir_to_other(cell.tile, other_tile, rot)
            other_rot = _get_other_rotation(rot, cur_to_other, other_to_cur)
            _add_to_grid(Cell(other_tile), coord + abs_dir_to_other.value,
                         other_rot)
Beispiel #18
0
def aoc01_b(insts: List[Inst]):
    cur = Coord(0, 0)
    dir = Direction.up
    seen = {cur}
    for i in insts:
        dir = turns[i.direction](dir)
        for _ in range(i.steps):
            cur += dir.value
            if cur in seen:
                return cur.manhattan
            seen.add(cur)
Beispiel #19
0
class HexOffset(Enum):
    e = Coord(1, 0)
    se = Coord(0, 1)
    sw = Coord(-1, 1)
    w = Coord(-1, 0)
    nw = Coord(0, -1)
    ne = Coord(1, -1)
Beispiel #20
0
class Offset(Enum):
    n = Coord(0, 1)
    ne = Coord(1, 0)
    se = Coord(1, -1)
    s = Coord(0, -1)
    sw = Coord(-1, 0)
    nw = Coord(-1, 1)
Beispiel #21
0
def parse_map(filename=13):
    track = {Coord(c_num, r_num): v
             for r_num, row in enumerate(read_file(filename, 2018, do_strip=False))
             for c_num, v in enumerate(row)
             if v != ' '}

    carts = {}
    for coord, v in track.items():
        if v in set('<>^v'):
            track[coord] = '|' if v in set('v^') else '-'
            carts[coord] = Cart(v)

    return carts, track
Beispiel #22
0
def part1():
    cur_dir = Dir.E
    cur_pos = Coord(0, 0)

    for dir, units in map(Inst.from_str, data):
        if dir in 'LR':
            cur_dir = cur_dir.rotate(dir, units)
        elif dir == 'F':
            cur_pos += cur_dir.value * units
        else:
            cur_pos += Dir[dir].value * units

    return cur_pos.manhattan
Beispiel #23
0
    def _add_to_grid(cur_cell: Cell,
                     cur_coord: Coord = Coord(0, 0),
                     cur_rot: Dir = Dir.n):
        if cur_cell in processed:
            return

        processed.add(cur_cell)
        if cur_coord in grid:
            a = 4
        grid[cur_coord] = cur_rot, cur_cell
        for dir, (other_dir, other_cell) in cur_cell.conns.items():
            mod_rot = rot_map[(rot_map[dir] + rot_map[cur_rot]) % 4]
            print(cur_cell.tile.id, dir, cur_rot)
            other_coord = cur_coord + mod_rot.value
            _add_to_grid(other_cell, other_coord,
                         _get_other_rotation(cur_rot, dir, other_dir))
Beispiel #24
0
    def draw(self):
        min_x = min(c.x for c in self.whites)
        min_y = min(c.y for c in self.whites)

        offset = Coord(-min_x, -min_y)
        coords = {c + offset for c in self.whites}

        max_x = max(c.x for c in coords)
        max_y = max(c.y for c in coords)

        canvas = [[' '] * (max_y + 1) for _ in range(max_x + 1)]

        for c in coords:
            canvas[c.x][c.y] = 'X'

        for l in reversed(canvas):
            print(''.join(l))
Beispiel #25
0
    def draw(self, t: Tile, around=8):
        res = [[None] * around * 2 for _ in range(around * 2)]
        cp = self._cur_pos

        coords = (Coord(x, y) for x in range(cp.x - around, cp.x + around)
                  for y in range(cp.y - around, cp.y + around))
        res_rcs = ((r, c) for c in range(2 * around)
                   for r in range(2 * around))
        for coord, (r, c) in zip(coords, res_rcs):
            res[r][c] = disp_map[self._map.get(coord)]

        res[around][around] = 'D'
        s = f'{Direction(self._last_dir)} -> {self._cur_pos} {t}'
        print(len(s) * '-')
        print(s)
        print(2 * around * '_')
        for l in reversed(res):
            print(''.join(l) + '|')
        print(2 * around * '-')
        print()
Beispiel #26
0
class Dir(Enum):
    up = Coord(0, -1)
    right = Coord(1, 0)
    down = Coord(0, 1)
    left = Coord(-1, 0)
Beispiel #27
0
 def from_str(cls, s: str):
     c1, c2 = s.split(' -> ')
     return cls(Coord(*eval(c1)), Coord(*eval(c2)))
Beispiel #28
0
def _create_connections(coords: Set[Coord]) -> Dict[Coord, Set[Coord]]:
    res = {}
    offsets = Coord(0, 0), Coord(1, 0), Coord(-1, 0), Coord(0, 1), Coord(0, -1)
    for c in coords:
        res[c] = {new_coord for o in offsets if (new_coord := c + o) in coords}
    return res
Beispiel #29
0
def _get_occupied_mem_coords() -> Set[Coord]:
    return {Coord(r, c)
            for r in range(128)
            for c, v in enumerate(get_hash(r))
            if v == '1'}
Beispiel #30
0
 def _update_board(self, x, y, tile_id):
     self.board[Coord(x, y)] = Tile(tile_id)