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()))
def main(): rules = {} with Path('input', '19').open() as f: rulelines, messages = readchunks(f) for r in rulelines + ['8: 42 | 42 8', '11: 42 31 | 42 11 31']: i, text = r.split(': ') rules[int(i)] = Or.parse(rules, text) print(sum(1 for m in messages if rules[0].accept(m)))
def main(): with Path('input', '13').open() as f: dots, folds = readchunks(f) paper = Paper(tuple(map(int, d.split(','))) for d in dots) for fold in folds[:1]: axis, n = fold.split('=') paper.fold(0 if 'x' == axis[-1] else 1, int(n)) print(len(paper))
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())
def main(): with Path('input', '14').open() as f: (template, ), rules = readchunks(f) template = Template(template) rules = {x: y for x, _, y in (r.split() for r in rules)} for _ in range(10): template = Template(list(template.insert(rules))) print(template.answer())
def main(): valid = 0 with Path('input', '4').open() as f: for chunk in readchunks(f): p = {} for l in chunk: p.update(e.split(':') for e in l.split(' ')) valid += fields <= p.keys() print(valid)
def main(): with Path('input', '4').open() as f: i = readchunks(f) numbers, = ([int(n) for n in l.split(',')] for l in next(i)) boards = [Board(lines) for lines in i] for n in numbers: for b in boards: if b.fire(n): print(sum(b.unmarked()) * n) return
def main(): tiles = [] with Path('input', '20').open() as f: for chunk in readchunks(f): tiles.append(Tile.parse(chunk)) normedgetotiles = defaultdict(list) for t in tiles: for e in t.normedges: normedgetotiles[e].append(t) outertiles = defaultdict(int) for e, etiles in normedgetotiles.items(): if 1 == len(etiles): outertiles[etiles[0]] += 1 print(reduce(operator.mul, (t.n for t, k in outertiles.items() if k == 2)))
def main(): with Path('input', '4').open() as f: i = readchunks(f) numbers, = ([int(n) for n in l.split(',')] for l in next(i)) boards = [Board(lines) for lines in i] for n in numbers: boards_ = [] for b in boards: if not b.fire(n): boards_.append(b) if not boards_: print(sum(b.unmarked()) * n) break boards = boards_
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}))
def main(): oktickets = [] if True: with Path('input', '16').open() as f: for chunk in readchunks(f): if 'your ticket:' == chunk[0]: myticket = [int(w) for w in chunk[1].split(',')] elif 'nearby tickets:' == chunk[0]: for t in islice(chunk, 1, None): vals = [int(w) for w in t.split(',')] if all(any(f.accept(v) for f in fields) for v in vals): oktickets.append(vals) else: fields = [] for rule in chunk: name, ranges = rule.split(': ') ranges = ranges.split(' or ') fields.append( Field(name, [ range(min, max + 1) for r in ranges for min, max in [map(int, r.split('-'))] ])) indexsets = {f: set(range(len(fields))) for f in fields} indexes = {} while len(indexes) < len(fields): for t in oktickets: for index in range(len(fields)): for f, s in indexsets.items(): if not f.accept(t[index]): s.discard(index) for f, s in indexsets.items(): if 1 == len(s): i, = s indexes[f] = i for f in indexes: indexsets.pop(f, None) for s in indexsets.values(): s.difference_update(indexes.values()) print( reduce(operator.mul, (myticket[indexes[f]] for f in fields if f.name.startswith('departure'))))
def badvals(): with Path('input', '16').open() as f: for chunk in readchunks(f): if 'your ticket:' == chunk[0]: pass elif 'nearby tickets:' == chunk[0]: for t in islice(chunk, 1, None): vals = [int(w) for w in t.split(',')] for v in vals: if all(v not in r for ranges in fields.values() for r in ranges): yield v else: fields = {} for rule in chunk: name, ranges = rule.split(': ') ranges = ranges.split(' or ') fields[name] = [ range(min, max + 1) for r in ranges for min, max in [map(int, r.split('-'))] ]
def main(): with Path('input', '20').open() as f: tiles = [Tile(chunk[1:]) for chunk in readchunks(f)] void = Void(tiles) solution = {} def solve(x, y): for i, t in enumerate(tiles): for o in t.orientations(): if solution.get( (x - 1, y), void).acceptright(o) and solution.get( (x, y - 1), void).acceptbottom(o): tiles.pop(i) solution[x, y] = o return for rank in range(gridsize): solve(rank, rank) for file in range(rank + 1, gridsize): solve(file, rank) solve(rank, file) def gridrows(): for y in range(gridsize): for r in range(1, tilesize - 1): yield ''.join(solution[x, y].rows[r][c] for x in range(gridsize) for c in range(1, tilesize - 1)) grid = BaseTile(list(gridrows())) for o in nessie.orientations(): locations = list(grid.find(o)) if locations: break for loc in locations: grid.delete(o, *loc) print(grid.hashes())
def counts(): with Path('input', '6').open() as f: for group in readchunks(f): conjunction = set(ascii_lowercase) conjunction.intersection_update(*group) yield len(conjunction)
def main(): with Path('input', '22').open() as f: decks = [[int(l) for l in chunk[1:]] for chunk in readchunks(f)] print(sum(c * (1 + i) for i, c in enumerate(reversed(decks[consume(decks)]))))
def counts(): with Path('input', '6').open() as f: for group in readchunks(f): yield len(set(chain(*group)))