## 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}')
## 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
## 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:
## 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 )
def loadROM(self, romPath: str): raw = fr.readAsList(romPath) self.rom = list(map(HCI, raw)) self.op = 0 self.acc = 0 self.status = 'on'
## 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)
## 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),
## 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):
## 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)
## 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'])
## 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)
## 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
## 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}')
## 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
## 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