Example #1
0
def get_neighbors(grid, x, y):
    neighbors = []
    if y > 0: neighbors.append(point(x, y - 1))
    if y < len(grid) - 1: neighbors.append(point(x, y + 1))
    if x > 0: neighbors.append(point(x - 1, y))
    if x < len(grid[0]) - 1: neighbors.append(point(x + 1, y))
    return neighbors
Example #2
0
    def clone(self) -> grid:
        cl = grid(self.width, self.height, self.get(point(0, 0)))

        for y in range(self.height):
            for x in range(self.width):
                cl.set(point(x, y), self.get(point(x, y)))

        return cl
Example #3
0
def move_east(cucumbers: grid) -> grid:
    step: grid = cucumbers.clone()
    eastie_bois = cucumbers.find_all(lambda cell: cell == '>')
    for boi in eastie_bois:
        x = (boi.x + 1) % cucumbers.width
        if cucumbers.get(point(x, boi.y)) == '.':
            step.set(point(boi.x, boi.y), '.')
            step.set(point(x, boi.y), '>')
    return step
Example #4
0
def move_south(cucumbers: grid) -> grid:
    step: grid = cucumbers.clone()
    eastie_bois = cucumbers.find_all(lambda cell: cell == 'v')
    for boi in eastie_bois:
        y = (boi.y + 1) % cucumbers.height
        if cucumbers.get(point(boi.x, y)) == '.':
            step.set(point(boi.x, boi.y), '.')
            step.set(point(boi.x, y), 'v')
    return step
Example #5
0
 def find_all(
         self,
         predicate: Callable[[T], bool] = lambda _: True) -> list[point]:
     return [
         point(x, y) for x in range(self.width) for y in range(self.height)
         if predicate(self.matrix[y][x])
     ]
Example #6
0
def find_basin(grid, x, y):
    visited = [point(x, y)]
    basin = [point(x, y)]
    tovisit = get_neighbors(grid, x, y)

    while tovisit:
        p = tovisit.pop()
        if p in visited: continue

        visited.append(p)

        if grid[p.y][p.x] == 9: continue

        basin.append(p)
        neighbors = get_neighbors(grid, p.x, p.y)
        tovisit.extend([n for n in neighbors if n not in visited])

    return basin
Example #7
0
def process(velocity: point, target: rect) -> point:
    max_x = target.x + target.w
    min_y = target.y
    pos = point(0, 0)
    i = 0
    while pos.x >= 0 and pos.x <= max_x and pos.y >= min_y:
        i += 1
        pos = step(velocity, i)
        yield pos
Example #8
0
def part1(target):
    total_max_y = 0
    for x in range(target.x):
        for y in range(target.x):
            velocity = point(x, y)
            steps: list[point] = [step for step in process(velocity, target)]

            if any(step.in_rect(target) for step in steps):
                highest = max(steps, key=lambda p: p.y)
                total_max_y = max(total_max_y, highest.y)

    print(total_max_y)
Example #9
0
    def neighbors(self, p: point, diag: bool = False) -> list[point]:
        other: list[point] = [
            point(p.x, p.y - 1),
            point(p.x, p.y + 1),
            point(p.x - 1, p.y),
            point(p.x + 1, p.y)
        ]

        if diag:
            other.extend([
                point(p.x - 1, p.y - 1),
                point(p.x + 1, p.y - 1),
                point(p.x - 1, p.y + 1),
                point(p.x + 1, p.y + 1)
            ])

        return [p for p in other if self.in_grid(p)]
Example #10
0
def fold_vert(dots, x):
    copy = [p for p in dots if p.x < x]
    for p in [p for p in dots if p.x > x]:
        copy.append(point(x - (p.x - x), p.y))
    return copy
Example #11
0
def fold_hor(dots, y):
    copy = [p for p in dots if p.y < y]
    for p in [p for p in dots if p.y > y]:
        copy.append(point(p.x, y - (p.y - y)))
    return copy
Example #12
0
from aoc.grid import grid
import re

pattern = '^(\d+),(\d+)$'
pattern_fold = '^fold along (\w)=(\d+)'

lines = aoc.read_lines('data/13.txt')

dots = []
folds = []

for line in lines:
    digits = re.match(pattern, line)
    if digits:
        x, y = digits.groups()
        dots.append(point(int(x), int(y)))
        continue

    fold_instr = re.match(pattern_fold, line)
    if fold_instr:
        axis, num = fold_instr.groups()
        folds.append((axis, int(num)))


def print_dots(dots):
    x_max = max([p.x for p in dots])
    y_max = max([p.y for p in dots])
    g = grid(x_max + 1, y_max + 1, '.')
    for dot in dots:
        g.set(dot, '#')
    g.print_condensed()
Example #13
0
def step(velocity: point, n: int):
    return point(sum_ap_x(velocity.x, n, -1), sum_ap_y(velocity.y, n, -1))