from aoc import aopen with aopen(9) as f: values = [int(x) for x in f.readlines()] n = 25 for i, x in enumerate(values[n:]): previous = values[i:i + n] valid = False for p in previous: if p * 2 != x and x - p in previous: valid = True break if not valid: secret = x print(secret) break for i, x in enumerate(values): total = x found = [x] for j, y in enumerate(values[i + 1:]): total += y found.append(y) if total == secret: print(min(found) + max(found)) break elif total > secret:
from aoc import aopen with aopen(15) as f: numbers = [int(x) for x in f.read().split(',')] def findValue(limit): sequence = numbers.copy() last1 = {k: i + 1 for i, k in enumerate(sequence)} last2 = {k: None for k in sequence} i = len(sequence) + 1 last = sequence[-1] while i <= limit: if last2[last] is None: x = 0 else: x = last1[last] - last2[last] if x in last1: last2[x] = last1[x] else: last2[x] = None last1[x] = i last = x i += 1 print(x) findValue(2020) findValue(30000000)
from aoc import aopen import re rules = {} with aopen(19) as f: rulesLines, lines = [x.split('\n') for x in f.read().split('\n\n')] for rule in rulesLines: if '"' in rule: m = re.match(r'(\d+): \"(\w)\"', rule) i = int(m.group(1)) rules[i] = m.group(2) else: m = re.match(r'(\d+): ', rule) i = int(m.group(1)) rest = rule[m.end(1) + 2:] rest = rest.split('|') rest = [[int(y) for y in x.split(' ') if y not in ['', ' ']] for x in rest] rules[i] = rest def checkRule(i, s): rule = rules[i] if len(s) == 0: return False, '' if isinstance(rule, str): return rule == s[0], s[1:] valid = False for conditionalRule in rule:
from aoc import aopen with aopen(1) as f: values = [int(x) for x in f.readlines()] valuesReverse = set() for value in values: valuesReverse.add(value) for value in values: if 2020 - value in valuesReverse: print(value * (2020 - value)) for i, value in enumerate(values): for value2 in values[i + 1:]: if 2020 - value - value2 in valuesReverse: print(value * value2 * (2020 - value - value2))
from aoc import aopen import re with aopen(4) as f: passports = f.read().split('\n\n') fields = ['byr', 'iyr', 'eyr', 'hgt', 'hcl', 'ecl', 'pid'] total = 0 for passport in passports: found = 0 for field in fields: if field + ':' in passport: found += 1 if found == 7: total += 1 print(total) total = 0 for passport in passports: found = 0 valid = True for field in fields: s = re.search(field + ':(\S+)', passport) if not s: valid = False continue x = s.group(1) if field in ('byr', 'iyr', 'eyr', 'pid') and not re.match(r'[0-9]+', x): valid = False
from aoc import aopen import re from collections import defaultdict with aopen(16) as f: constraintStrings, yourTicket, tickets = f.read().split('\n\n') constraints = [] for constraint in constraintStrings.split('\n'): m = re.search(r'(.+): (\d+)-(\d+) or (\d+)-(\d+)', constraint) constraints.append([m.group(1)] + [int(m.group(i)) for i in range(2, 6)]) yourTicket = [int(x) for x in yourTicket.split('\n')[1].split(',')] tickets = [[int(x) for x in ticket.split(',')] for ticket in tickets.split('\n')[1:]] def isValidForAny(value): for c in constraints: if isValidFor(value, c): return True return False def isValidFor(value, c): return c[1] <= value <= c[2] or c[3] <= value <= c[4] total = 0 validTickets = []
from aoc import aopen import re from collections import defaultdict from copy import deepcopy field = defaultdict(lambda: defaultdict(lambda: defaultdict(lambda: '.'))) field4 = defaultdict( lambda: defaultdict(lambda: defaultdict(lambda: defaultdict(lambda: '.')))) with aopen(17) as f: initialData = [[c for c in line] for line in f.read().split('\n')] for i, row in enumerate(initialData): for j, x in enumerate(row): field[0][i][j] = x field4[0][0][i][j] = x def getBounds(data): minZ = minY = minX = 99999 maxZ = maxY = maxX = -99999 for z in list(data.keys()): plane = data[z] for y in list(plane.keys()): row = plane[y] for x in list(row.keys()): if row[x] == '.': continue if x < minX: minX = x if x > maxX: maxX = x if y < minY:
from aoc import aopen import re with aopen(7) as f: lines = f.readlines() bags = [] bagsDict = {} for line in lines: name = re.search(r'^(.*) bags contain', line).group(1) remainder = line.partition('contain ')[2].strip('.\n') if remainder == 'no other bags': inside = [] else: inside = [(int(re.search(r'^(\d+) (.*) bags?$', segment).group(1)), re.search(r'^(\d+) (.*) bags?$', segment).group(2)) for segment in remainder.split(', ')] bags.append((name, inside)) bagsDict[name] = inside found = set(['shiny gold']) oldFound = set() while found != oldFound: oldFound = set(found) for bag, inside in bags: insideBags = set(x[1] for x in inside) if bag in found: continue if not insideBags.isdisjoint(found): found.add(bag) print(len(found) - 1)
from aoc import aopen from collections import defaultdict import re lines = [] with aopen(21) as f: strings = f.readlines() for line in strings: m = re.match(r'(.*) \(contains (.*)\)', line) lines.append([m.group(1).split(' '), m.group(2).split(', ')]) def findPotentialAllergens(lines): allergensReverse = defaultdict(list) for line in lines: ingredients, allergens = line for allergen in allergens: allergensReverse[allergen].append(list(ingredients)) potentialAllergens = set() for allergen, ingredients in allergensReverse.items(): for ingredientList in ingredients: for i in ingredientList: valid = True for testIngredientList in ingredients: if not i in testIngredientList: valid = False if valid: potentialAllergens.add(i) return potentialAllergens
from aoc import aopen import re with aopen(18) as f: lines = f.readlines() lines = [line.replace(' ', '').replace('\n', '') for line in lines] def findCloseBracket(line): opens = 0 for i, c in enumerate(line): if c == '(': opens += 1 elif c == ')': opens -= 1 if opens == 0: return i def process(line): i = 0 result = -1 while i < len(line): c = line[i] value = None if c == '(': j = i + findCloseBracket(line[i:]) value = process(line[i + 1:j]) line = line[:i] + line[j + 1:] elif c in '1234567890': value = int(c)
from aoc import aopen with aopen(13) as f: depart, buses = f.readlines() depart = int(depart) buses = [int(x) if x != 'x' else -1 for x in buses.split(',')] def part1(): x = depart while True: targetBus = -1 for bus in buses: if bus == -1: continue if x % bus == 0: targetBus = bus break if targetBus != -1: break x += 1 print(targetBus * (x - depart)) def part2(): values = [] for i, bus in enumerate(buses): if bus != -1: values.append((bus, i)) values = sorted(values)
from aoc import aopen with aopen(3) as f: trees = [[c == '#' for c in x] for x in f.readlines()] y = 0 total = 0 for x in range(len(trees)): if trees[x][y]: total += 1 y += 3 y %= 31 print(total) slopes = ((1, 1), (3, 1), (5, 1), (7, 1), (1, 2)) result = 1 for slope in slopes: y = 0 total = 0 for x in range(0, len(trees), slope[1]): if trees[x][y]: total += 1 y += slope[0] y %= 31 result *= total print(result)
from aoc import aopen import re with aopen(8) as f: p = re.compile(r'(\w+) ([+-])(\d+)') lines = [] for line in f.readlines(): m = p.match(line) lines.append((m.group(1), int(m.group(3)) * (-1 if m.group(2) == '-' else 1))) instructions = { 'acc': lambda ip, ac, x: (ip + 1, ac + x), 'jmp': lambda ip, ac, x: (ip + x, ac), 'nop': lambda ip, ac, x: (ip + 1, ac), } ip = 0 ac = 0 traversed = set() while ip not in traversed: traversed.add(ip) line = lines[ip] ip, ac = instructions[line[0]](ip, ac, line[1]) print(ac) for i in range(len(lines)): if lines[i][0] == 'acc': continue ip = 0
from aoc import aopen with aopen(12) as f: moves = f.readlines() directionKeys = ['N', 'S', 'E', 'W'] directionValues = {'N': 0, 'S': 180, 'E': 90, 'W': 270} rotationKeys = ['L', 'R'] rotationValues = {'L': -1, 'R': 1} def doMove(position, direction, value): if direction == 0: position[1] += value elif direction == 90: position[0] += value elif direction == 180: position[1] -= value if direction == 270: position[0] -= value def sailShip(): direction = 90 position = [0, 0] for move in moves: action = move[0] value = int(move[1:]) if action in directionKeys: moveDirection = directionValues[action]
from aoc import aopen from functools import cache with aopen(10) as f: values = sorted([int(x) for x in f.readlines()]) x = 0 ones = 0 threes = 1 for value in values: delta = value - x if delta == 1: ones += 1 elif delta == 3: threes += 1 x = value values = [0] + values print(ones * threes) @cache def f(i): if i == len(values) - 1: return 1 result = 0 for j in range(i + 1, i + 4): if j >= len(values): break elif values[j] - values[i] <= 3:
from aoc import aopen import re with aopen(2) as f: strings = list(f.readlines()) total = 0 for s in strings: m = re.match(r'(\d+)-(\d+) (\w): (\w+)', s) a = int(m.group(1)) b = int(m.group(2)) letter = m.group(3) code = m.group(4) c = code.count(letter) if a <= c <= b: total += 1 print(total) total = 0 for s in strings: m = re.match(r'(\d+)-(\d+) (\w): (\w+)', s) a = int(m.group(1)) b = int(m.group(2)) letter = m.group(3) code = m.group(4) found = 0 for i in [a, b]: if code[i - 1] == letter: found += 1 if found == 2:
from aoc import aopen import re with aopen(14) as f: lines = f.readlines() def part1(): variables = {} for i, line in enumerate(lines): if 'mask' in line: mask = line.partition(' = ')[2][:-1][::-1] else: m = re.match(r'mem\[(\d+)\] = (\d+)\n', line) v = int(m.group(1)) x = '{:b}'.format(int(m.group(2)))[::-1].ljust(36, '0') result = 0 p = 1 for c1, c2 in zip(x, mask): if c2 == 'X': result += p * int(c1) else: result += p * int(c2) p *= 2 variables[v] = result print(sum(variables.values())) def part2():