示例#1
0
def compute2(data):
    logging.getLogger().setLevel(logging.INFO)
    painter = Intcode.from_input(data)

    hull_map = defaultdict(lambda: 1)
    position = Point(0, 0)
    direction = Directions.UP

    paint(painter, hull_map, position, direction)

    x_s = [p.x for p in hull_map.keys()]
    y_s = [p.y for p in hull_map.keys()]
    hull_rect = Rectangle(
        left=min(x_s),
        right=max(x_s),
        top=min(y_s),
        bottom=max(y_s),
    )

    out = []
    for y in range(hull_rect.top, hull_rect.bottom + 1):
        line = ''
        for x in range(hull_rect.left, hull_rect.right + 1):
            line += '#' if hull_map[Point(x, y)] == 1 else ' '
        out.append(line)

    return '\n' + '\n'.join(out)
示例#2
0
    def test_parse(self):
        input = dedent("""\
            .#
            .|""")

        assert_that(
            parse(input), {
                Point(0, 0): States.OPEN,
                Point(1, 0): States.LUMBERYARD,
                Point(0, 1): States.OPEN,
                Point(1, 1): States.TREES,
            })
示例#3
0
 def test_extended_neighbors(self):
     assert_that(Point(2, 2).extended_neighbors, is_([
         Point(1, 1),
         Point(2, 1),
         Point(3, 1),
         Point(1, 2),
         Point(3, 2),
         Point(1, 3),
         Point(2, 3),
         Point(3, 3)
     ]))
示例#4
0
    def test_next_state_trees_stays_trees(self):
        area = parse(
            dedent("""\
            ...
            .|#
            #.."""))

        assert_that(next_state(area, Point(1, 1)), is_(States.TREES))
示例#5
0
    def test_next_state_open_stays_open(self):
        area = parse(
            dedent("""\
            ...
            |..
            ..|"""))

        assert_that(next_state(area, Point(1, 1)), is_(States.OPEN))
示例#6
0
    def test_next_state_open_becomes_trees_surrounded_by_trees(self):
        area = parse(
            dedent("""\
            .|.
            |..
            ..|"""))

        assert_that(next_state(area, Point(1, 1)), is_(States.TREES))
示例#7
0
    def test_next_state_lumberyard_becomes_open_when_not_surrounded2(self):
        area = parse(
            dedent("""\
            |..
            |#.
            |.."""))

        assert_that(next_state(area, Point(1, 1)), is_(States.OPEN))
示例#8
0
    def test_next_state_trees_becomes_lumberyard_surrounded_by_lumberyards(
            self):
        area = parse(
            dedent("""\
            #..
            #|.
            #.."""))

        assert_that(next_state(area, Point(1, 1)), is_(States.LUMBERYARD))
示例#9
0
def show_graphic(soil):
    top = min(pos[Y] for pos in soil.keys())
    bottom = max(pos[Y] for pos in soil.keys())
    left = min(pos[X] for pos in soil.keys())
    right = max(pos[X] for pos in soil.keys())
    print("size", right - left, bottom - top)
    img = Image.new('RGB', (right - left + 1, bottom - top + 1),
                    "black")  # Create a new black image
    pixels = img.load()
    top_left = Point(left, top)
    colors = {
        CLAY: (139, 69, 19),
        RUNNING_WATER: (127, 127, 255),
        STAGNANT_WATER: (0, 0, 255),
    }
    for point, content in soil.items():
        pixels[(Point(*point) - top_left).tuple()] = colors[content]
    img.show()
示例#10
0
    def test_next_state_lumberyard_stays_lumberyard_if_close_to_lumberyard_and_trees(
            self):
        area = parse(
            dedent("""\
            |..
            .#.
            ..#"""))

        assert_that(next_state(area, Point(1, 1)), is_(States.LUMBERYARD))
示例#11
0
def parse(data):
    asteroids = {}
    w, h = 0, 0
    for y, line in enumerate(data.strip().splitlines()):
        for x, char in enumerate(line):
            if char == ASTEROID:
                asteroids[Point(x, y)] = 0
            w = x
        h = y
    return asteroids, w + 1, h + 1
示例#12
0
def compute2(data, lazer=Point(20, 18), stop_at=200):  # from compute 1
    asteroids, w, h = parse(data)

    killed = []

    biggest_side = max(lazer.x, w - 1 - lazer.x, lazer.y, h - 1 - lazer.y)

    size = lcm(*list(range(1, biggest_side + 1)))
    # lazer_map = Rectangle(
    #     left=lazer.x - lcm(*list(range(1, lazer.x + 1))),
    #     right=lazer.x + lcm(*list(range(1, w - lazer.x))),
    #     top=lazer.y - lcm(*list(range(1, lazer.y + 1))),
    #     bottom=lazer.y + lcm(*list(range(1, h - lazer.y))),
    # )
    lazer_map = Rectangle(
        left=lazer.x - size,
        right=lazer.x + size,
        top=lazer.y - size,
        bottom=lazer.y + size,
    )

    real_map = Rectangle(
        left=0,
        right=w - 1,
        top=0,
        bottom=h - 1,
    )

    while True:
        for target in lazer_map.perimeter(Point(lazer.x, lazer_map.top)):
            for step in lazer.raytrace(target):
                if step not in real_map:
                    break
                if step in asteroids:
                    asteroids.pop(step)
                    killed.append(step)
                    logging.debug(f'Destroyed {step}, killed={len(killed)}')
                    if len(killed) == stop_at:
                        return step.x * 100 + step.y
                    break

        logging.debug('Full circle done')
示例#13
0
def compute(data):
    logging.getLogger().setLevel(logging.INFO)
    painter = Intcode.from_input(data)

    hull_map = defaultdict(lambda: 0)
    position = Point(0, 0)
    direction = Directions.UP

    paint(painter, hull_map, position, direction)

    return len(hull_map.items())
示例#14
0
def test_parse():
    data = """\
.#..#
.....
#####
....#
...##"""
    assert_that(
        parse(data),
        is_(({
            Point(1, 0): 0,
            Point(4, 0): 0,
            Point(0, 2): 0,
            Point(1, 2): 0,
            Point(2, 2): 0,
            Point(3, 2): 0,
            Point(4, 2): 0,
            Point(4, 3): 0,
            Point(3, 4): 0,
            Point(4, 4): 0,
        }, 5, 5)))
示例#15
0
    def test_parse(self):
        grid, fighters = parse(
            dedent("""\
        #######
        #.G...#
        #...EG#
        #.#.#G#
        #..G#E#
        #.....#
        #######"""))

        assert_that(
            fighters,
            is_([
                Fighter("G", Point(2, 1)),
                Fighter("E", Point(4, 2)),
                Fighter("G", Point(5, 2)),
                Fighter("G", Point(5, 3)),
                Fighter("G", Point(3, 4)),
                Fighter("E", Point(5, 4)),
            ]))

        assert_that(grid[2, 1], is_(fighters[0]))
        assert_that(grid[3, 1], is_(None))
        assert_that(grid, not_(has_key((2, 3))))
示例#16
0
def parse(data):
    fighters = []
    grid = {}
    for y, line in enumerate(data.split("\n")):
        for x, char in enumerate(line):
            if char == ".":
                grid[x, y] = None
            elif char in ["E", "G"]:
                fighter = Fighter(char, Point(x, y))
                grid[x, y] = fighter
                fighters.append(fighter)

    return grid, fighters
示例#17
0
    def propagate(point: Point, to: [Directions]):
        # print("Propagating from", point)
        soil[point.tuple()] = RUNNING_WATER

        if point.y == bottom:
            return True

        down = point + Directions.DOWN.value

        if soil.get(down.tuple()) is RUNNING_WATER:
            return True
        elif soil.get(down.tuple()) is None:
            if propagate(down, to=(Directions.LEFT, Directions.RIGHT)):
                return True

        propagations = [flow_to(point, direction) for direction in to]
        if not any(propagations):
            soil[point.tuple()] = STAGNANT_WATER
            return False

        not_stagant(point, Directions.LEFT)
        not_stagant(point, Directions.RIGHT)

        return True
示例#18
0
def flow_all(soil):
    sys.setrecursionlimit(10000)
    top = min(pos[Y] for pos in soil.keys())
    bottom = max(pos[Y] for pos in soil.keys())
    start = Point(500, top - 1)

    def propagate(point: Point, to: [Directions]):
        # print("Propagating from", point)
        soil[point.tuple()] = RUNNING_WATER

        if point.y == bottom:
            return True

        down = point + Directions.DOWN.value

        if soil.get(down.tuple()) is RUNNING_WATER:
            return True
        elif soil.get(down.tuple()) is None:
            if propagate(down, to=(Directions.LEFT, Directions.RIGHT)):
                return True

        propagations = [flow_to(point, direction) for direction in to]
        if not any(propagations):
            soil[point.tuple()] = STAGNANT_WATER
            return False

        not_stagant(point, Directions.LEFT)
        not_stagant(point, Directions.RIGHT)

        return True

    def flow_to(point, direction):
        new_point = point + direction.value
        content = soil.get(new_point.tuple())
        if content is RUNNING_WATER:
            return True
        elif content is None:
            return propagate(new_point, (direction, ))
        return False

    def not_stagant(point, direction):
        next_point = point + direction.value
        while soil.get(next_point.tuple()) is STAGNANT_WATER:
            soil[next_point.tuple()] = RUNNING_WATER
            next_point += direction.value

    propagate(start + Directions.DOWN.value,
              (Directions.LEFT, Directions.RIGHT))
示例#19
0
        return Point(self.right, self.top)

    @property
    def bottom_left(self):
        return Point(self.left, self.bottom)

    @property
    def bottom_right(self):
        return Point(self.right, self.bottom)

    def __contains__(self, item):
        return self.left <= item.x <= self.right and self.top <= item.y <= self.bottom


@pytest.mark.parametrize('rect,start,points', [
    (Rectangle(0, 1, 0, 1), Point(0, 0),
     [Point(0, 0), Point(0, 1),
      Point(1, 1), Point(1, 0)]),
    (Rectangle(0, 2, 0, 2), Point(1, 0), [
        Point(1, 0),
        Point(2, 0),
        Point(2, 1),
        Point(2, 2),
        Point(1, 2),
        Point(0, 2),
        Point(0, 1),
        Point(0, 0)
    ]),
])
def test_perimeter(rect, start, points):
    assert_that(list(rect.perimeter(start)), points)
示例#20
0
 def get_neighbors(self, point: Point):
     for x, y in neighbors:
         pos = Point(point.x + x, point.y + y)
         if pos.tuple() in self.grid:
             yield pos
示例#21
0
import sys

import pytest
from hamcrest import assert_that, is_

from y2018 import Directions, Point

ORIGIN = Point(0, 0)


def compute(data):
    wire1, wire2 = list(map(parse_path, data.strip().split('\n')))

    wire1_points, _ = crawl(wire1)
    wire2_points, _ = crawl(wire2)

    intersections = wire1_points.intersection(wire2_points)
    intersections.remove(ORIGIN)

    ordered = sorted(intersections, key=lambda p: p.manhattan_dist(ORIGIN))

    return ordered[0].manhattan_dist(ORIGIN)


def compute2(data):
    wire1, wire2 = list(map(parse_path, data.strip().split('\n')))

    wire1_points, steps_to1 = crawl(wire1)
    wire2_points, steps_to2 = crawl(wire2)

    intersections = wire1_points.intersection(wire2_points)
示例#22
0
 def top_right(self):
     return Point(self.right, self.top)
示例#23
0
 def bottom_left(self):
     return Point(self.left, self.bottom)
示例#24
0
    for y, line in enumerate(data.strip().splitlines()):
        for x, char in enumerate(line):
            if char == ASTEROID:
                asteroids[Point(x, y)] = 0
            w = x
        h = y
    return asteroids, w + 1, h + 1


@pytest.mark.parametrize('val,expect1, expect2', [
    ("""\
.#..#
.....
#####
....#
...##""", Point(3, 4), 8),
    ("""\
......#.#.
#..#.#....
..#######.
.#.#.###..
.#..#.....
..#....#.#
#..#....#.
.##.#..###
##...#..#.
.#....####""", Point(5, 8), 33),
    ("""\
#.#...#.#.
.###....#.
.#....#...
示例#25
0
 def bottom_right(self):
     return Point(self.right, self.bottom)
示例#26
0
    def test_extended_neighbors(self):
        assert_that(Point(2, 2).extended_neighbors, is_([
            Point(1, 1),
            Point(2, 1),
            Point(3, 1),
            Point(1, 2),
            Point(3, 2),
            Point(1, 3),
            Point(2, 3),
            Point(3, 3)
        ]))



@pytest.mark.parametrize('p1, p2, steps', [
    (Point(0,0), Point(0, 1), []),
    (Point(0,0), Point(0, 2), [Point(0, 1)]),
    (Point(1,0), Point(0, 0), []),
    (Point(2,0), Point(0, 0), [Point(1, 0)]),
    (Point(0,0), Point(1, 1), []),
    (Point(0,0), Point(2, 2), [Point(1, 1)]),
    (Point(0,0), Point(3, 9), [Point(1, 3), Point(2, 6)]),
    (Point(3,9), Point(0, 0), [Point(2, 6), Point(1, 3)]),
])
def test_raytrace(p1, p2, steps):
    assert_that(list(p1.raytrace(p2)), is_(steps))


@pytest.mark.parametrize('direction,rotation,result', [
    (Directions.UP, Rotations.CW, Directions.RIGHT),
    (Directions.RIGHT, Rotations.CW, Directions.DOWN),
示例#27
0
 def test_direction_to(self):
     assert_that(Point(2, 2).direction_to(Point(2, 1)), is_(Directions.UP))
     assert_that(Point(2, 2).direction_to(Point(3, 2)), is_(Directions.RIGHT))
     assert_that(Point(2, 2).direction_to(Point(1, 2)), is_(Directions.LEFT))
     assert_that(Point(2, 2).direction_to(Point(2, 3)), is_(Directions.DOWN))
示例#28
0
def parse(input):
    area = {}
    for y, line in enumerate(input.split("\n")):
        for x, state in enumerate(line):
            area[Point(x, y)] = States(state)
    return area
示例#29
0
    def test_next_state_no_neighbors_dont_count(self):
        area = parse(dedent("""\
            #"""))

        assert_that(next_state(area, Point(0, 0)), is_(States.OPEN))
示例#30
0
 def top_left(self):
     return Point(self.left, self.top)