예제 #1
0
def main(data: Iterable[str]):
    ship_pos = Coord2D(0, 0)
    waypoint = Coord2D(10, 1)
    for cmd, amt in comandorate(data):
        print("Currently at", ship_pos, "waypoint is at", waypoint)

        if cmd == Command.Forward:
            print("Moving to waypoint", amt, "times")
            ship_pos += waypoint * amt
            continue
        elif cmd == Command.Left or cmd == Command.Right:
            print("Rotating waypoint", cmd.name, amt, "degrees")
            waypoint = rotate(waypoint, cmd, amt)
            continue

        if cmd == Command.North:
            move_dir = Direction.North
        elif cmd == Command.South:
            move_dir = Direction.South
        elif cmd == Command.East:
            move_dir = Direction.East
        elif cmd == Command.West:
            move_dir = Direction.West
        else:
            assert False

        print("Moving waypoint", move_dir.name, amt, "units")
        waypoint += move_dir.value * amt

    print("end pos", ship_pos)
    print(abs(ship_pos.x) + abs(ship_pos.y))
예제 #2
0
    def read_data(self, data: Iterable[str]):
        y = 0
        for line in data:
            for x in range(len(line)):
                self[Coord2D(x, y)] = GridCell(line[x])
            y += 1

        gridmax = Coord2D(-1, -1)

        for coord in self.keys():
            gridmax = Coord2D(x=max(gridmax.x, coord.x),
                              y=max(gridmax.y, coord.y))

        self._max = Coord2D(gridmax.x + 1, gridmax.y + 1)
예제 #3
0
    def a_star(self) -> List[Coord2D]:
        # self.print()

        start = Coord2D(0, 0)
        self[start] = self[start]._replace(cheapest_cost=0)

        working_set = WorkingSet[int, Coord2D]()
        working_set.add(start, self._heuristic(start))

        while working_set:
            coord = working_set.pop()
            if coord == self._goal:
                path = self._get_path()
                self.print(path)
                return path
            _, cost, _ = self[coord]

            for neighbour in self._get_neighbours(coord, diagonal=False):
                neighbour_risk, neighbour_cost, _ = self[neighbour]

                new_cost = cost + neighbour_risk
                if new_cost < neighbour_cost:
                    self[neighbour] = Chiton(neighbour_risk, new_cost, coord)
                    working_set.add_or_replace(
                        neighbour,
                        new_cost + self._heuristic(neighbour),
                    )

        raise RuntimeError("Could not find goal?!")
예제 #4
0
def main(data: Iterable[str]) -> None:
    vents = [Vent.parse(line) for line in data]

    gridmax = Coord2D(0, 0)
    for vent in vents:
        gridmax = gridmax.get_max(vent.get_max())

    grid = pd.DataFrame([
        [0 for x in range(gridmax.x + 1)]
        #
        for y in range(gridmax.y + 1)
    ])

    for vent in vents:
        for coord in vent:
            grid[coord.x][coord.y] += 1

    # print(grid.replace(0, ".").to_string(header=False, index=False))

    overlaps = 0
    # gnee
    for col_id in grid.columns:
        for value in grid[col_id]:
            if value > 1:
                overlaps += 1

    print(overlaps)
예제 #5
0
class Grid(Dict[Coord2D, GridCell]):
    _max: Coord2D(-1, -1)

    def read_data(self, data: Iterable[str]):
        y = 0
        for line in data:
            for x in range(len(line)):
                self[Coord2D(x, y)] = GridCell(line[x])
            y += 1

        gridmax = Coord2D(-1, -1)

        for coord in self.keys():
            gridmax = Coord2D(x=max(gridmax.x, coord.x),
                              y=max(gridmax.y, coord.y))

        self._max = Coord2D(gridmax.x + 1, gridmax.y + 1)

    def get_neighbours(self, coord: Coord2D) -> Iterable[GridCell]:
        for dir in DIRECTIONS:
            try:
                yield self[coord + dir]
            except KeyError:
                pass

    def get_visible_seats(self, coord: Coord2D) -> Iterable[GridCell]:
        for dir in DIRECTIONS:
            target = coord + dir
            try:
                while (cell := self[target]) == GridCell.Floor:
                    target += dir
                yield cell
            except KeyError:
                pass
예제 #6
0
 def __str__(self):
     ret = ""
     for y in range(self._max.y):
         for x in range(self._max.x):
             ret += self[Coord2D(x, y)].value
         ret += "\n"
     return ret.strip()
예제 #7
0
    def print(self, path: Optional[Iterable[Coord2D]] = None) -> None:
        if path:
            pathset = set(path)
        else:
            pathset = set((Coord2D(0, 0), self._goal))

        for y in range(self.height):
            for x in range(self.width):
                coord = Coord2D(x, y)
                risk, _, _ = self[coord]
                if coord in pathset:
                    cprint(str(risk), attrs=["bold"], end="")
                else:
                    cprint(str(risk), attrs=["dark"], end="")

            print()
        print()
예제 #8
0
 def __str__(self) -> str:
     ret = ""
     for y in range(self.height):
         for x in range(self.width):
             if self.get(Coord2D(x, y)):
                 ret += "#"
             else:
                 ret += "."
         ret += "\n"
     return ret
예제 #9
0
 def print(self) -> None:
     for y in range(self.height):
         for x in range(self.width):
             energy = self[Coord2D(x, y)]
             if energy == 0:
                 cprint(str(energy), attrs=["bold"], end=" ")
             else:
                 cprint(str(energy), attrs=["dark"], end=" ")
         print()
     print()
예제 #10
0
 def __iter__(self) -> Iterator[Coord2D]:
     start = self.start
     end = self.end
     step = Coord2D(_steppe(start.x, end.x), _steppe(start.y, end.y))
     pos = start
     yield pos
     # probably fine
     while True:
         pos += step
         yield pos
         if pos == end:
             break
예제 #11
0
    def parse(cls, data: Iterator[str]) -> Grid:
        ret = Transparency()

        for line in data:
            if not line:
                break
            coord = Coord2D.parse(line)
            ret.width = max(ret.width, coord.x + 1)
            ret.height = max(ret.height, coord.y + 1)
            ret[coord] = True

        return ret
예제 #12
0
def main(data: Iterator[str]) -> None:
    grid = ChitonCave.parse(data)

    path = grid.a_star()

    total_risk = 0
    start = Coord2D(0, 0)
    for coord in path:
        if coord != start:
            risk, _, _ = grid[coord]
            total_risk += risk

    print(total_risk)
예제 #13
0
def rotate(pos: Coord2D, direction: Command, amount: int):
    assert amount % 90 == 0
    amount //= 90
    assert amount <= 4

    # Always rotate right
    if direction == Command.Left:
        amount = 4 - amount

    for _ in range(amount):
        x, y = pos
        pos = Coord2D(x=y, y=-x)

    return pos
예제 #14
0
def main(data: Iterable[str]):
    coords = sorted(_get_coords(data), key=lambda c: c[0] * c[1])
    gridmin = Coord2D(math.inf, math.inf)
    gridmax = Coord2D(-math.inf, -math.inf)

    for coord in coords:
        gridmin = Coord2D(x=min(gridmin.x, coord.x), y=min(gridmin.y, coord.y))
        gridmax = Coord2D(x=max(gridmax.x, coord.x), y=max(gridmax.y, coord.y))

    print(gridmin.x, gridmin.y, gridmax.x, gridmax.y)

    MAX_DISTANCE = 10000

    size = 0

    for x in range(gridmin.x, gridmax.x + 1):
        for y in range(gridmin.y, gridmax.y + 1):
            to_check = Coord2D(x, y)
            distance = sum(coord.distance(to_check) for coord in coords)
            if distance < MAX_DISTANCE:
                size += 1

    print(size)
예제 #15
0
    def parse(cls, data: Iterator[str]):
        ret = cls()
        ret._fill(((Chiton(
            risk=int(risk),
            cheapest_cost=sys.maxsize,
            cheapest_neighbour=None,
        ) for risk in line) for line in data))
        for y in range(6):
            for x in range(6):
                if x == 0 and y == 0:
                    continue
                for coord in ret._iterate_grid():
                    newcoord = Coord2D(
                        x=coord.x + ret.width * x,
                        y=coord.y + ret.height * y,
                    )
                    existing = ret[coord]
                    ret[newcoord] = existing._replace(
                        risk=((existing.risk + x + y) % 9) or 9)
        ret.width *= 5
        ret.height *= 5

        ret._goal = Coord2D(ret.width - 1, ret.height - 1)
        return ret
예제 #16
0
def main(data: Iterable[str]):
    grid = HeightGrid.parse(data)
    ret = 0

    lowspots: List[Coord2D] = []
    for y in range(grid.height):
        for x in range(grid.width):
            coord = Coord2D(x, y)
            pos = grid[coord]
            if grid.check_lowspot(coord):
                lowspots.append(coord)
                cprint(str(pos), color="red", attrs=["bold"], end="")
            elif pos < 9:
                cprint(str(pos), end="")
            else:
                cprint(str(pos), attrs=["concealed"], end="")
        print()

    basins = [grid.count_floodfill(coord) for coord in lowspots]
    biggest = sorted(basins, reverse=True)[:3]
    ret = biggest[0] * biggest[1] * biggest[2]

    print(ret)
예제 #17
0
 def parse(cls, data: str) -> Vent:
     start, end = data.split(" -> ")
     return Vent(start=Coord2D.parse(start), end=Coord2D.parse(end))
예제 #18
0
from enum import Enum
from typing import Dict, Iterable

from aoc.utils import Coord2D


class GridCell(Enum):
    Floor = "."
    Chair = "L"
    OccupiedChair = "#"


DIRECTIONS = [
    Coord2D(-1, -1),
    Coord2D(0, -1),
    Coord2D(1, -1),
    Coord2D(-1, 0),
    Coord2D(1, 0),
    Coord2D(-1, 1),
    Coord2D(0, 1),
    Coord2D(1, 1),
]


class Grid(Dict[Coord2D, GridCell]):
    _max: Coord2D(-1, -1)

    def read_data(self, data: Iterable[str]):
        y = 0
        for line in data:
            for x in range(len(line)):
예제 #19
0
 def _heuristic(self, coord: Coord2D) -> int:
     return coord.distance(self._goal)
예제 #20
0
def _get_coords(data: Iterable[str]) -> Iterable[Coord2D]:
    for line in data:
        x, y = line.split(",")
        yield Coord2D(int(x), int(y))