예제 #1
0
## adventofcode.com
# Day 3
# https://adventofcode.com/2020/day/3

import fr

from typing import List

route = fr.readAsList('input3')


def countTrees(route: List[str], width: int, right: int, down: int) -> int:
    position = 0
    trees = 0
    for row in range(0, len(route), down):
        if route[row][position] == "#": trees += 1
        position = (position + right) % width

    return trees


routeA = countTrees(route, 31, 3, 1)
print(f'Answer 1: {routeA}')

routeB = countTrees(route, 31, 1, 1)
routeC = countTrees(route, 31, 5, 1)
routeD = countTrees(route, 31, 7, 1)
routeE = countTrees(route, 31, 1, 2)

treeProduct = routeA * routeB * routeC * routeD * routeE
print(f'Answer 2: {treeProduct}')
예제 #2
0
## adventofcode.com
# Day 7
# https://adventofcode.com/2020/day/7

import fr

from typing import List, Dict

inputs = fr.readAsList('input7-clean')


def parseRules(rules: List[str]) -> Dict[str, Dict[str, int]]:
    _rules = {}
    for line in rules:
        rList = line.split(',')

        # If there is only one item,
        # add an empty dictionary.
        if len(rList) == 1:
            _rules[rList[0]] = {}
            continue

        k = rList[0]
        vList = rList[1:]
        v = {}
        for i in range(0, len(vList), 2):
            v[vList[i + 1]] = int(vList[i])

        _rules[k] = v

    return _rules
예제 #3
0
## adventofcode.com
# Day 14
# https://adventofcode.com/2020/day/14

import fr

answer1 = 'unknown'
answer2 = 'unknown'

inputs: list[str] = fr.readAsList('input14')


def itob36(value: int) -> str:
    """Converts an int to a 36-character binary string"""
    return f'{str(bin(value))[2:]:0>36}'


def mask36(bstr: str, _mask: str) -> str:
    """Masks a 36-character binary string with the provided mask."""
    if len(bstr) != len(_mask):
        print("Error: Binary/Mask Length Mismatch")
        return "err"

    blist = list(bstr)
    for i in range(len(_mask)):
        blist[i] = _mask[i] if _mask[i] != 'X' else bstr[i]

    return ''.join(blist)


def b36toi(bstr: str) -> int:
예제 #4
0
## adventofcode.com
# Day 17
# https://adventofcode.com/2020/day/17

import fr

answer1 = 'unknown'
answer2 = 'unknown'

inputs: list[str] = fr.readAsList('input17-test')

class P3:
  '''Describes the position of a Conway Cube.'''
  def __init__(self,x:int, y:int, z:int):
    self.x = x
    self.y = y
    self.z = z

  def __str__(self):
    return f'({self.x}, {self.y}, {self.z})'

  def __repr__(self):
    return self.__str__()

def addP3(a: P3, b: P3) -> P3:
  '''Adds two P3s together and returns a new P3.'''
  return P3(
    a.x + b.x,
    a.y + b.y,
    a.z + b.z
  )
예제 #5
0
 def loadROM(self, romPath: str):
     raw = fr.readAsList(romPath)
     self.rom = list(map(HCI, raw))
     self.op = 0
     self.acc = 0
     self.status = 'on'
예제 #6
0
## adventofcode.com
# Day 13
# https://adventofcode.com/2020/day/13

import fr
import math
from typing import List, Dict, Tuple

answer1 = 'unknown'
answer2 = 'unknown'

inputs = fr.readAsList('input13')

timestamp = int(inputs[0])
busses = inputs[1].split(',')
minDeparture = math.inf
minBus = math.inf
maxBus = 0

for bus in busses:
    if bus != 'x':
        busID = int(bus)
        busDeparture = math.ceil(timestamp / busID) * busID
        if busDeparture < minDeparture:
            minDeparture = busDeparture
            minBus = busID

        maxBus = max(maxBus, busID)

answer1 = minBus * (minDeparture - timestamp)
예제 #7
0
## adventofcode.com
# Day 11
# https://adventofcode.com/2020/day/11

import fr
from typing import List, Dict, Tuple

answer1 = 'unknown'
answer2 = 'unknown'

inputs = fr.readAsList('input11')

# The following rules are applied to every seat simultaneously:
# - If a seat is empty (L) and there are no occupied seats adjacent to it, the
#   seat becomes occupied.
# - If a seat is occupied (#) and four or more seats adjacent to it are also
#   occupied, the seat becomes empty.
# - Otherwise, the seat's state does not change.
# Floor (.) never changes; seats don't move, and nobody sits on the floor.

width = len(inputs[0])
height = len(inputs)

print(f'Seat layout: {width}x{height}')

seatsAdjacent: Dict[Tuple[int, int], bool] = {}  # Current seat adjacency.
seatsVisible: Dict[Tuple[int, int], bool] = {}  # Current seat visibility.
offsets = ([
    (-1, -1),
    (0, -1),
    (1, -1),
예제 #8
0
## adventofcode.com
# Day 12
# https://adventofcode.com/2020/day/12

import fr
from typing import List, Dict, Tuple

answer1 = 'unknown'
answer2 = 'unknown'

inputs = fr.readAsList('input12')

# BOW --------------


class Ship:
    x: int = 0
    y: int = 0
    facing: str = 'E'

    _directions = {'N': (0, 1), 'E': (1, 0), 'S': (0, -1), 'W': (-1, 0)}
    _left = {'N': 'W', 'W': 'S', 'S': 'E', 'E': 'N'}
    _right = {'N': 'E', 'E': 'S', 'S': 'W', 'W': 'N'}

    def turnLeft(self, angle: int):
        turns = int(angle / 90)
        for i in range(turns):
            del i
            self.facing = self._left[self.facing]

    def turnRight(self, angle: int):
예제 #9
0
## adventofcode.com
# Day 16
# https://adventofcode.com/2020/day/16

import fr

answer1 = 'unknown'
answer2 = 'unknown'

# inputs: list[str] = fr.readAsList('input16')

fields_input = fr.readAsList('input16-fields')
nearby_input = fr.readAsList('input16-nearby-tickets')

valid_set: set[int] = set()


def fieldSet(field: str) -> set[int]:
    '''Takes a field definition and returns a set containing
  the valid values of the field.'''

    # Saved as a comma separated list
    # Name is unneeded, so just grab the ranges
    raw_ranges = field.split(',')[1:]
    values: set[int] = set()

    for field_range in raw_ranges:
        range_values = field_range.split('-')
        range_set = set(range(int(range_values[0]), int(range_values[1]) + 1))
        values = values.union(range_set)
예제 #10
0
## adventofcode.com
# Day 4
# https://adventofcode.com/2020/day/4

import fr
import re

from typing import List

passports = fr.readAsList('input4-clean')

requiredFields = {'byr', 'iyr', 'eyr', 'hgt', 'hcl', 'ecl', 'pid'}


def validatePassportFields(passport: str) -> (bool, dict):
    data = passport.split(',')
    # build set of keys
    keys = set()
    passportDict = {}
    for key in range(0, len(data), 2):
        keys.add(data[key])
        passportDict[data[key]] = data[key + 1].strip()

    fields = requiredFields.intersection(passportDict.keys())

    return len(fields) == len(requiredFields), passportDict


def validatePassportData(passport: dict) -> bool:
    return (validateBirthYear(passport['byr'])
            and validateIssueYear(passport['iyr'])
예제 #11
0
## adventofcode.com
# Day 6
# https://adventofcode.com/2020/day/6

import fr

from typing import List

customs = fr.readAsList('input6-clean')

answers = list(map(chr, range(97, 123)))


def totalUnions() -> int:
    unions = 0
    for group in customs:
        for answer in answers:
            if answer in group: unions += 1

    return unions


def totalIntersections() -> int:
    intersections = 0
    for group in customs:
        g = group.split(',')
        sets: List[set] = list(map(lambda s: set(s), g))
        intr = set(answers)
        for answer in sets:
            intr = intr.intersection(answer)
예제 #12
0
## adventofcode.com
# Day 2
# https://adventofcode.com/2020/day/2

import fr

from typing import List

passwords = fr.readAsList('input2-clean')


def checkPasswordA(password: str):
    args = password.split(',')
    min = int(args[0])
    max = int(args[1])
    match = args[2]
    pw: str = args[3]

    num = pw.count(match)
    return num <= max and num >= min


def checkPasswordB(password: str):
    args = password.split(',')
    indexA = int(args[0]) - 1
    indexB = int(args[1]) - 1
    match: str = args[2]
    pw: str = args[3]

    validA = 1 if pw[indexA] == match else 0
    validB = 1 if pw[indexB] == match else 0
예제 #13
0
## adventofcode.com
# Day 5
# https://adventofcode.com/2020/day/5

import fr

from typing import List

boardingPasses = fr.readAsList('input5')


def parseSeatCode(code: str) -> int:
    row = int(code[:-3].replace('F', '0').replace('B', '1'), 2)
    col = int(code[-3:].replace('L', '0').replace('R', '1'), 2)

    return row * 8 + col


seats = list(map(parseSeatCode, boardingPasses))

print(f'Answer 1: {max(seats)}')

seats.sort()
seatId = seats[0]

for seat in seats:
    if seat != seatId: break
    seatId += 1

print(f'Answer 2: {seatId}')
예제 #14
0
## adventofcode.com
# Day 10
# https://adventofcode.com/2020/day/10

import fr
from typing import List, Dict

answer1 = 'unknown'
answer2 = 'unknown'

inputs = list(map(int, fr.readAsList('input10')))
inputs.append(0)
inputs.sort()
diffs = [0, 0, 0, 1]

for i in range(1, len(inputs)):
    diffs[inputs[i] - inputs[i - 1]] += 1

answer1 = diffs[1] * diffs[3]

# Build a map containing the possible paths
# any node is part of
paths: Dict[int, int] = {0: 1}

for i in range(1, len(inputs)):
    n = inputs[i]  # value of current node
    p = 0  # number of paths the node is part of
    p = (paths.get(n - 1, 0) + paths.get(n - 2, 0) + paths.get(n - 3, 0))

    paths[n] = p
예제 #15
0
## adventofcode.com
# Day 1
# https://adventofcode.com/2020/day/1

import fr

from typing import List

lines = fr.readAsList('input1')
values = [int(line) for line in lines]


def findSum2(l: List[int], sum: int):
    start = 0
    for value in l:

        target = sum - value

        if target in values[start:]:
            return target, value

        start += 1

    return -1, -1


def findSum3(l: List[int], sum: int):
    start = 0
    for value in l:

        target = sum - value