示例#1
0
def make_naive_line(a, b, diag=False):
    import pdb

    pdb.set_trace()

    def anglebtw(a, b):
        # atan2 gives angle between origin and point; to get angle between two
        # points, move one to the origin and the other by the corresponding
        # amount, then use atan2 on the result. Subtracting one from the other
        # is the same as moving one to the origin and then moving the other the
        # same amount.
        c = b - a
        return math.degrees(math.atan2(c.y, c.x))

    def is_naive(a, b):
        return anglebtw(a, b) % 45 == 0

    if not is_naive(a, b):
        raise UserWarning("Not a naive line", a, b)
    points = set()
    diff = lambda a, b: (abs(b - a), get_sign(b - a))
    valx, sigx = diff(a.x, b.x)
    valy, sigy = diff(a.y, b.y)
    if valx == 0 or valy == 0 or diag:
        for i in range(max(valx, valy) + 1):
            new_point = aoc.Point(x=a.x + (i * sigx), y=a.y + (i * sigy))
            points.add(new_point)
    return points
示例#2
0
def explore(gridd, start, future, basin):
    dirs = [
        aoc.Point(x=start.x, y=start.y - 1),
        aoc.Point(x=start.x, y=start.y + 1),
        aoc.Point(x=start.x - 1, y=start.y),
        aoc.Point(x=start.x + 1, y=start.y),
    ]
    near = keyfilter(lambda x: x in dirs and x not in basin, gridd)
    for pt, data in near.items():
        if data and int(data[0]) not in (None, 9):
            if pt not in future:
                future.append(pt)
            if pt not in basin:
                basin.append(pt)

    for pt in future:
        basin = explore(gridd, pt, [], basin)

    return basin
示例#3
0
def make_line_diag(instr):
    a, b = instr
    points = set()
    if a.x == b.x:
        if a.y < b.y:
            fills = range(a.y, b.y + 1)
            for n in fills:
                points.add(aoc.Point(x=a.x, y=n))
        elif a.y > b.y:
            fills = range(b.y, a.y + 1)
            for n in fills:
                points.add(aoc.Point(x=a.x, y=n))
        else:
            points.add(aoc.Point(x=a.x, y=a.y))
    elif a.y == b.y:
        if a.x < b.x:
            fills = range(a.x, b.x + 1)
            for n in fills:
                points.add(aoc.Point(x=n, y=a.y))
        elif a.x > b.x:
            fills = range(b.x, a.x + 1)
            for n in fills:
                points.add(aoc.Point(x=n, y=a.y))
        else:
            points.add(aoc.Point(x=a.x, y=a.y))
    else:
        curr = a
        points.add(curr)
        while curr != b:
            if curr.x < b.x:
                curr = curr + aoc.Point(1, 0)
            elif curr.x > b.x:
                curr = curr - aoc.Point(1, 0)
            if curr.y < b.y:
                curr = curr + aoc.Point(0, 1)
            elif curr.y > b.y:
                curr = curr - aoc.Point(0, 1)
            points.add(curr)

    return points
示例#4
0
def make_line(instr):
    a, b = instr
    points = set()
    if a.x == b.x:
        if a.y < b.y:
            fills = range(a.y, b.y + 1)
            for n in fills:
                points.add(aoc.Point(x=a.x, y=n))
        elif a.y > b.y:
            fills = range(b.y, a.y + 1)
            for n in fills:
                points.add(aoc.Point(x=a.x, y=n))
        else:
            points.add(aoc.Point(x=a.x, y=a.y))
    elif a.y == b.y:
        if a.x < b.x:
            fills = range(a.x, b.x + 1)
            for n in fills:
                points.add(aoc.Point(x=n, y=a.y))
        elif a.x > b.x:
            fills = range(b.x, a.x + 1)
            for n in fills:
                points.add(aoc.Point(x=n, y=a.y))
        else:
            points.add(aoc.Point(x=a.x, y=a.y))
    return points
示例#5
0
def get_lows(data):
    grid = []
    gridd = {}
    for y, row in enumerate(data):
        for x, char in enumerate(row):
            grid.append(aoc.Point(x=x, y=y))
            gridd[aoc.Point(x=x, y=y)] = (char, None)
    for pt in gridd:
        above = gridd.get(aoc.Point(x=pt.x, y=pt.y - 1))
        below = gridd.get(aoc.Point(x=pt.x, y=pt.y + 1))
        left = gridd.get(aoc.Point(x=pt.x - 1, y=pt.y))
        right = gridd.get(aoc.Point(x=pt.x + 1, y=pt.y))
        adjs = lcompact([above, below, left, right])
        curr = int(gridd[pt][0])
        low = True
        for adj in adjs:
            if curr >= int(adj[0]):
                low = False
        if low:
            gridd[pt] = (gridd[pt][0], curr + 1)

    lows = lmap(lambda x: x,
                lfilter(lambda x: x[1][1] is not None, gridd.items()))

    return lows
示例#6
0
def process_two(data):
    grid = {}
    for y, row in enumerate(data):
        for x, char in enumerate(row):
            grid[aoc.Point(x=x, y=y)] = (char, None)
    lows = get_lows(data)

    basins = lmap(lambda x: explore(grid, x[0], [], [x[0]]), lows)
    sbasins = sorted(basins, key=len)
    threebasins = sbasins[-3:]
    return prod(map(len, threebasins))

    return data
示例#7
0
def parse_line(line):
    coords = splitstrip(line, "->")
    raw_points = [lmap(int, splitstrip(coord, ",")) for coord in coords]
    points = lmap(lambda x: aoc.Point(*x), raw_points)
    return points