コード例 #1
0
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:
コード例 #2
0
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)
コード例 #3
0
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:
コード例 #4
0
ファイル: 1.py プロジェクト: veratrum/aoc2020
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))
コード例 #5
0
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
コード例 #6
0
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 = []
コード例 #7
0
ファイル: 17.py プロジェクト: veratrum/aoc2020
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:
コード例 #8
0
ファイル: 7.py プロジェクト: veratrum/aoc2020
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)
コード例 #9
0
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
コード例 #10
0
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)
コード例 #11
0
ファイル: 13.py プロジェクト: veratrum/aoc2020
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)
コード例 #12
0
ファイル: 3.py プロジェクト: veratrum/aoc2020
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)
コード例 #13
0
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
コード例 #14
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]
コード例 #15
0
ファイル: 10.py プロジェクト: veratrum/aoc2020
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:
コード例 #16
0
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:
コード例 #17
0
ファイル: 14.py プロジェクト: veratrum/aoc2020
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():