Ejemplo n.º 1
0
def main():
    weights = {}
    for y, line in enumerate(Path('input', '15').read_text().splitlines()):
        for x, c in enumerate(line):
            weights[Vector([x, y])] = int(c)
    target = Vector([x, y])
    cursor = Vector([0, 0])
    state = State(weights, cursor)
    while cursor != target:
        cursor = state.update(cursor)
    print(state.costs[target])
Ejemplo n.º 2
0
def main():
    with Path('input', '19').open() as f:
        scanners = [
            Scanner([Vector(map(int, p.split(','))) for p in chunk[1:]])
            for chunk in readchunks(f)
        ]
    scanners[0].loc = zero
    oriented = {scanners[0]}
    while True:
        toorient = [s for s in scanners if s not in oriented]
        if not toorient:
            break
        oriented_ = set()
        for s in toorient:
            for t in oriented:
                if s.reorient(t):
                    oriented_.add(s)
                    break
        oriented |= oriented_

    def distances():
        for i, s in enumerate(scanners):
            for t in scanners[i + 1:]:
                yield (s.loc - t.loc).manhattan()

    print(max(distances()))
Ejemplo n.º 3
0
def main():
    d = Diagram()
    with Path('input', '5').open() as f:
        for line in f:
            start, _, end = line.split()
            d.line(*(Vector(map(int, p.split(','))) for p in [start, end]))
    print(sum(1 for n in d.points.values() if n >= 2))
Ejemplo n.º 4
0
def main():
    with Path('input', '20').open() as f:
        (algo,), lines = readchunks(f)
    algo = ['#' == c for c in algo]
    image = Image({Vector([x, y]): '#' == c for y, l in enumerate(lines) for x, c in enumerate(l)})
    for _ in range(50):
        image.apply(algo)
    print(image.lit())
Ejemplo n.º 5
0
def main():
    grid = Grid()
    for y, line in enumerate(Path('input', '11').read_text().splitlines()):
        for x, c in enumerate(line):
            grid[Vector([x, y])] = int(c)
    s = 1
    while True:
        if len(grid) == grid.step():
            print(s)
            break
        s += 1
Ejemplo n.º 6
0
def main():
    grid = Grid()
    for y, line in enumerate(Path('input', '9').read_text().splitlines()):
        for x, c in enumerate(line):
            if '9' != c:
                grid.add(Vector([x, y]))
    basins = []
    while grid:
        basins.append(grid.takebasin())
    basins.sort()
    print(reduce(mul, basins[-3:]))
Ejemplo n.º 7
0
def main():
    lines = Path('input', '25').read_text().splitlines()
    floor = Floor(len(lines[0]), len(lines))
    for y, l in enumerate(lines):
        for x, c in enumerate(l):
            if '.' != c:
                (floor.east if '>' == c else floor.south).add(Vector([x, y]))
    n = 1
    while floor.step():
        n += 1
    print(n)
Ejemplo n.º 8
0
def main():
    weights = {}
    for y, line in enumerate(Path('input', '15').read_text().splitlines()):
        for x, c in enumerate(line):
            weights[Vector([x, y])] = int(c)
    w = x + 1
    h = y + 1
    ww = hh = 5
    weights_ = weights.copy()
    for yy in range(hh):
        for xx in range(ww):
            if xx or yy:
                for (x, y), weight in weights_.items():
                    weights[Vector([xx * w + x, yy * h + y])] = (weight + xx + yy - 1) % 9 + 1
    target = Vector([ww * w - 1, hh * h - 1])
    cursor = Vector([0, 0])
    state = State(weights, cursor)
    while cursor != target:
        cursor = state.update(cursor)
    print(state.costs[target])
Ejemplo n.º 9
0
class Grid(dict):

    kernel = [Vector([intcos(k), intsin(k)]) for k in range(4)]

    def _islow(self, k):
        for d in self.kernel:
            n = self.get(k + d)
            if n is not None and n <= self[k]:
                return
        return True

    def lowpoints(self):
        for k, n in self.items():
            if self._islow(k):
                yield n
Ejemplo n.º 10
0
class Grid(set):

    kernel = [Vector([intcos(k), intsin(k)]) for k in range(4)]

    def takebasin(self):
        points = [self.pop()]
        n = 1
        while points:
            points_ = []
            for p in points:
                for d in self.kernel:
                    q = p + d
                    if q in self:
                        self.remove(q)
                        points_.append(q)
                        n += 1
            points = points_
        return n
Ejemplo n.º 11
0
def main():
    with Path('input', '19').open() as f:
        scanners = [
            Scanner([Vector(map(int, p.split(','))) for p in chunk[1:]])
            for chunk in readchunks(f)
        ]
    oriented = {scanners[0]}
    while True:
        toorient = [s for s in scanners if s not in oriented]
        if not toorient:
            break
        oriented_ = set()
        for s in toorient:
            for t in oriented:
                if s.reorient(t):
                    oriented_.add(s)
                    break
        oriented |= oriented_
    print(len({b for s in scanners for b in s.beacons}))
Ejemplo n.º 12
0
class Grid(dict):

    kernel = [Vector([x, y]) for x in range(-1, 2) for y in range(-1, 2) if x or y]

    def step(self):
        for p in self:
            self[p] += 1
        flashed = set()
        while True:
            points = {p for p, e in self.items() if p not in flashed and e > 9}
            if not points:
                for f in flashed:
                    self[f] = 0
                return len(flashed)
            flashed |= points
            for p in points:
                for d in self.kernel:
                    q = p + d
                    if q in self:
                        self[q] += 1
Ejemplo n.º 13
0
#!/usr/bin/env python3

from adventlib import intcos, intsin, Vector
from collections import defaultdict
from heapq import heappop, heappush
from pathlib import Path

inf = float('inf')
steps = [Vector([intcos(x), intsin(x)]) for x in range(4)]

class State:

    def __init__(self, weights, cursor):
        self.costs = {}
        self.rcosts = defaultdict(set)
        self.allcosts = []
        for p in weights:
            self._put(p, 0 if p == cursor else inf)
        self.weights = weights

    def _put(self, p, cost):
        self.costs[p] = cost
        s = self.rcosts[cost]
        if not s:
            heappush(self.allcosts, cost)
        s.add(p)

    def _remove(self, p):
        cost = self.costs.pop(p)
        self.rcosts[cost].remove(p)
        return cost
Ejemplo n.º 14
0
 def step(self):
     return self._step(self.east, Vector([1, 0])) + self._step(
         self.south, Vector([0, 1]))
Ejemplo n.º 15
0
def _getmap(u, v):
    (a, i), = ([a, i] for i in range(3) for a in [-1, 1] if a * u[i] == v[0])
    (b, j), = ([a, i] for i in range(3) for a in [-1, 1] if a * u[i] == v[1])
    (c, k), = ([a, i] for i in range(3) for a in [-1, 1] if a * u[i] == v[2])
    return lambda u: Vector([a * u[i], b * u[j], c * u[k]])
Ejemplo n.º 16
0
#!/usr/bin/env python3

from adventlib import readchunks, Vector
from pathlib import Path


def _getmap(u, v):
    (a, i), = ([a, i] for i in range(3) for a in [-1, 1] if a * u[i] == v[0])
    (b, j), = ([a, i] for i in range(3) for a in [-1, 1] if a * u[i] == v[1])
    (c, k), = ([a, i] for i in range(3) for a in [-1, 1] if a * u[i] == v[2])
    return lambda u: Vector([a * u[i], b * u[j], c * u[k]])


zero = Vector([0, 0, 0])


class Scanner:
    def __init__(self, beacons):
        self.characters = [{
            tuple(sorted(map(abs, b - o))): b
            for b in beacons
        } for o in beacons]
        assert all(len(c) == len(beacons) for c in self.characters)
        self.beacons = beacons

    def reorient(self, that):
        for c in self.characters:
            for d in that.characters:
                keys = c.keys() & d.keys()
                if len(keys) >= 12:
                    co = c[0, 0, 0]
Ejemplo n.º 17
0
#!/usr/bin/env python3

from adventlib import readchunks, Vector
from pathlib import Path

tile = [Vector([x, y]) for y in range(-1, 2) for x in range(-1, 2)]
infinity = Vector([float('inf')] * 2)

class Image:

    border = 0

    def __init__(self, pixels):
        self.pixels = pixels

    def _number(self, p, borderpixels_add = lambda q: None):
        n = 0
        for d in tile:
            q = p + d
            if q in self.pixels:
                k = self.pixels[q]
            else:
                borderpixels_add(q)
                k = self.border
            n = (n << 1) + k
        return n

    def apply(self, algo):
        pixels = {}
        borderpixels = set()
        for p in self.pixels:
Ejemplo n.º 18
0
def main():
    grid = Grid()
    for y, line in enumerate(Path('input', '11').read_text().splitlines()):
        for x, c in enumerate(line):
            grid[Vector([x, y])] = int(c)
    print(sum(grid.step() for _ in range(100)))
Ejemplo n.º 19
0
def main():
    grid = Grid()
    for y, line in enumerate(Path('input', '9').read_text().splitlines()):
        for x, c in enumerate(line):
            grid[Vector([x, y])] = int(c)
    print(sum(1 + n for n in grid.lowpoints()))