Exemple #1
0
'''
Created on 4 Dec 2020

@author: Luke
'''
'''
Created on 4 Dec 2020

@author: Luke
'''

from AOC.config import config
config.set_wd(4)

import re

required_fields = ["byr", "iyr", "eyr", "hgt", "hcl", "ecl", "pid"]

def get_field(keyval):
    regex = r"([a-z]{3}):(.*)"
    m = re.match(regex, keyval)
    if m is None:
        raise RuntimeError(f"No match for {keyval}")
    return list(map(str.strip, m.groups()))

def validate(key, val):
    if key in ["byr", "iyr", "eyr"]:
        lims = {"byr":[1920, 2002], "iyr":[2010,2020], "eyr":[2020,2030]}
        if re.match(r"^[0-9]{4}$", val) is None:
            return False
        val = int(val)
Exemple #2
0
'''
Created on 4 Dec 2020

@author: Luke
'''

from AOC.config import config

config.set_wd(1)

with open("input.txt") as f:
    data = list(map(int, f.readlines()))

for i in data:
    for j in data:
        for k in data:
            if i + j + k == 2020:
                print(f"{i} * {j} * {k} = {i*j*k}")
Exemple #3
0
'''
Created on 12 Dec 2020

@author: Luke
'''

from AOC.config import config
config.set_wd(12)

import numpy as np
import re


def get_input(input_type):
    if input_type == "test":
        ret = ["F10", "N3", "F7", "R90", "F11"]
    else:
        with open("input.txt") as f:
            ret = list(map(str.strip, f.readlines()))
    return ret


class Ship(object):

    compass_to_direction = {
        "E": np.array([1, 0]),
        "N": np.array([0, 1]),
        "W": np.array([-1, 0]),
        "S": np.array([0, -1])
    }
    direction_to_compass = {
Exemple #4
0
'''
Created on 10 Dec 2020

@author: Luke
'''

from AOC.config import config
config.set_wd(10)

test_input_1 = [16, 10, 15, 5, 1, 11, 7, 19, 6, 12, 4]

test_input_2 = [
    28, 33, 18, 42, 31, 14, 46, 20, 48, 47, 24, 23, 49, 45, 19, 38, 39, 11, 1,
    32, 25, 35, 8, 17, 7, 9, 4, 2, 34, 10, 3
]


def run(input):
    input = sorted(input)
    diffs = []
    for i in range(len(input) - 1):
        diffs.append(input[i + 1] - input[i])
    diff_nos = {}
    for i in set(diffs):
        diff_nos[i] = len([d for d in diffs if d == i])
    # Add initial diff (smallest values) and finall diff (3)
    diff_nos[min(input)] += 1
    diff_nos[3] += 1
    return diff_nos

Exemple #5
0
'''
Created on 19 Dec 2020

@author: Luke
'''

from AOC.config import config
config.set_wd(19)
import re


def get_input(input_type):
    if input_type == "test1":
        rules = ['0: 1 2', '1: "a"', '2: 1 3 | 3 1', '3: "b"']
        messages = []
    elif input_type == "test2":
        rules = [
            '0: 4 1 5', '1: 2 3 | 3 2', '2: 4 4 | 5 5', '3: 4 5 | 5 4',
            '4: "a"', '5: "b"'
        ]
        messages = ["ababbb", "bababa", "abbbab", "aaabbb", "aaaabbb"]
    else:
        rules = []
        messages = []
        with open("input.txt") as f:
            for line in f:
                line = line.strip()
                if line == "": break
                rules.append(line)
            for line in f:
                messages.append(line.strip())
Exemple #6
0
'''
Created on 18 Dec 2020

@author: Luke
'''
import re

from AOC.config import config
config.set_wd(18)

import operator


def get_input(input_type):
    if input_type == "test1":
        return ["1 + 2 * 3 + 4 * 5 + 6"]
    elif input_type == "test2":
        return ["1 + (2 * 3) + (4 * (5 + 6))"]
    elif input_type == "test3":
        return ["2 * 3 + (4 * 5)"]
    elif input_type == "test4":
        return ["5 + (8 * 3 + 9 + 3 * 4 * 3)"]
    elif input_type == "test5":
        return ["5 * 9 * (7 * 3 * 3 + 9 * 3 + (8 + 6 * 4))"]
    elif input_type == "test6":
        return ["((2 + 4 * 9) * (6 + 9 * 8 + 6) + 6) + 2 + 4 * 2"]
    else:
        with open("input.txt") as f:
            return list(map(str.strip, f.readlines()))

Exemple #7
0
'''
Created on 16 Dec 2020

@author: Luke
'''

from AOC.config import config
config.set_wd(16)

import re
import numpy as np


def get_input(input_type):
    if input_type == "test":
        ret = {
            "rules":
            ["class: 0-1 or 4-19", "row: 0-5 or 8-19", "seat: 0-13 or 16-19"],
            "your_ticket": [11, 12, 13],
            "other_tickets": [[3, 9, 18], [15, 1, 5], [5, 14, 9]]
        }
    else:

        def get_rules(fh):
            rules = []
            for line in fh:
                if line.strip() == "": return rules
                rules.append(line.strip())

        def get_your_ticket(fh):
            header = next(fh).strip()
Exemple #8
0
'''
Created on 24 Dec 2020

@author: Luke
'''

from AOC.config import config
config.set_wd(24)

import numpy as np

class Tile(object):
    _tile_map = {}
    WHITE = 0
    BLACK = 1
    
    dir_map = {"e":np.array((1,0)),
                   "ne":np.array((0,1)),
                   "nw":np.array((-1,1)),
                   "w":np.array((-1,0)),
                   "sw":np.array((0,-1)),
                   "se":np.array((1,-1))}
    
    @staticmethod
    def parse_directions(directions):
        ret = []
        def get_next_direction(directions):
            for d in ["se", "sw", "ne", "nw", "w", "e"]:
                if directions.startswith(d):
                    directions = directions.replace(d, "", 1)
                    return(d, directions)
Exemple #9
0
'''
Created on 17 Dec 2020

@author: Luke
'''


from AOC.config import config
config.set_wd(17)

import numpy as np

def get_input(input_type):
    if input_type == "test":
        arr =[[".","#","."],
             [".",".","#"],
             ["#","#","#"]]
    else:
        arr = []
        with open("input.txt") as f:
            for line in f:
                arr.append(list(line.strip()))
    return np.array(arr, dtype="S1")


class ConwayCube(object):
    # Need to use byte form as numpy turns S1 into byte array and can only do element-wise
    # comparisons if comparing with byte object
    active = b"#"
    inactive = b"."
    def __init__(self, initial_state):
Exemple #10
0
'''
Created on 7 Dec 2020

@author: Luke
'''

from AOC.config import config
config.set_wd(7)

import re

bag_list = {}


class Bag(object):
    def __init__(self, description):
        global bag_list
        self.description = description
        self.parse_description()
        if self.colour in bag_list:
            raise RuntimeError(f"{self.colour} already in list")
        bag_list[self.colour] = self
        self.parents = []
        self.ancestors = []

    def parse_description(self):
        regex = r'([a-z]+ [a-z]+) bags contain (.*)\.'
        match = re.match(regex, self.description)
        if match is None:
            raise RuntimeError(f"Cannot parse description {self.description}")
        self.colour = match.group(1)
Exemple #11
0
'''
Created on 21 Dec 2020

@author: Luke
'''

from AOC.config import config
config.set_wd(21)

import re


def get_input(input_type):
    if input_type == "test":
        ret = [
            "mxmxvkd kfcds sqjhc nhms (contains dairy, fish)",
            "trh fvjkl sbzzf mxmxvkd (contains dairy)",
            "sqjhc fvjkl (contains soy)", "sqjhc mxmxvkd sbzzf (contains fish)"
        ]
    else:
        ret = []
        with open("input.txt") as f:
            for line in f:
                ret.append(line.strip())
    return ret


# For each allergen git a list of all foods that contain it
# Then intersection of foods are possible allergens
def get_allergen_foods(_input):
    allergen_d = {}
Exemple #12
0
'''
Created on 8 Dec 2020

@author: Luke
'''


from AOC.config import config
config.set_wd(8)

import copy

class Boot(object):
    def __init__(self):
        self.accumulator = 0
        self.index = 0
        self.original_instructions = []
        self.instructions = []
        self.run_indexes = []
        
    def parse_instructions(self, instructions):
        for i in instructions:
            (op, arg) = map(str.strip, i.split())
            arg = int(arg)
            self.original_instructions.append((op, arg))
        self.instructions = copy.copy(self.original_instructions)
    
    def can_switch_instruction(self, index):
        return self.original_instructions[index][0] in ("nop", "jmp")
    
    def switch_instruction(self, index):
Exemple #13
0
'''
Created on 9 Dec 2020

@author: Luke
'''

from AOC.config import config
config.set_wd(9)
import itertools
import numpy as np


class NumberChecker(object):
    def __init__(self, input_filename, N):
        self.N = N
        self.file_obj = open(input_filename)
        self.data = []
        self.all_data = []
        for _ in range(N):
            next_val = int(self.file_obj.readline().strip())
            self.data.append(next_val)
            self.all_data.append(next_val)

    def find_weakness(self):
        """
        Find contiguous sum in all data that sums to invalid number.
        Return sum of smallest and largest value
        """
        for start in itertools.count(start=0):
            for length in itertools.count(start=2):
                subset = self.all_data[start:start + length]
Exemple #14
0
'''
Created on 23 Dec 2020

@author: Luke
'''

from AOC.config import config
config.set_wd(23)


class Cups(object):
    def __init__(self, cups):
        self.cups = cups
        self.current_cup = cups[0]
        self.picked_three = None
        self.destinaion = None

    def set_three(self):
        three = []
        #print(f"Picking three - cups = {self.cups}, current cup = {self.current_cup}")
        for _ in range(3):
            three.append(
                self.cups.pop(
                    (self.cups.index(self.current_cup) + 1) % len(self.cups)))
        self.picked_three = three
        #print(f"Three = {self.picked_three}, cups = {self.cups}")

    def select_destination(self):
        #print("Selecting destination")
        dest = self.current_cup
        while True:
Exemple #15
0
'''
Created on 5 Dec 2020

@author: Luke
'''
'''
Created on 5 Dec 2020

@author: Luke
'''

from AOC.config import config
config.set_wd(5)

import math


def get_partitioner(length, low_char, high_char):
    def get_row(char_str):
        if not length == (2**len(char_str)):
            raise RuntimeError(
                f"Expected character string of length {int(math.log2(length))}"
            )
        row_low = 0
        row_high = length
        for c in char_str:
            if c == low_char:
                row_high = (row_low + row_high) // 2
            elif c == high_char:
                row_low = (row_low + row_high) // 2
            else:
Exemple #16
0
'''
Created on 20 Dec 2020

@author: Luke
'''

from AOC.config import config
config.set_wd(20)

import numpy as np
import re


class Tile(object):

    LEFT = 0
    UP = 1
    RIGHT = 2
    DOWN = 3

    def __init__(self, _id, tile):
        self.id = _id
        self.tile = tile
        self.unordered_borders = [
            tile[0, :], tile[-1, :], tile[:, 0], tile[:, -1]
        ]
        self.ordered_borders = [None] * 4
        self.unordered_neighbours = []
        self.ordered_neighbours = [None] * 4
        self.position = None
Exemple #17
0
'''
Created on 13 Dec 2020

@author: Luke
'''
'''
Created on 13 Dec 2020

@author: Luke
'''

from AOC.config import config
config.set_wd(13)

import numpy as np


def get_input(input_type):
    if input_type == "test1":
        ret = {"earliest_t": 939, "buses": "7,13,x,x,59,x,31,19".split(",")}
    elif input_type == "test2":
        ret = {"earliest_t": None, "buses": "17,x,13,19".split(",")}
    elif input_type == "test3":
        ret = {"earliest_t": None, "buses": "67,7,59,61".split(",")}
    elif input_type == "test4":
        ret = {"earliest_t": None, "buses": "67,x,7,59,61".split(",")}
    elif input_type == "test5":
        ret = {"earliest_t": None, "buses": "67,7,x,59,61".split(",")}
    elif input_type == "test6":
        ret = {"earliest_t": None, "buses": "1789,37,47,1889".split(",")}
    else:
Exemple #18
0
'''
Created on 14 Dec 2020

@author: Luke
'''


from AOC.config import config
config.set_wd(14)

import re
import numpy as np


class Memory(object):
    def __init__(self):
        self.bitmask = None
        self.memory = {}
        
    def set_bitmask(self, bitmask):
        self.bitmask = list(bitmask)
        
    def set_memory(self, address, value):
        for a in self.get_addresses(address):
            self.memory[a] = value
    
    def int_to_list(self, value, bitlen=36):
        """
        Create 36-bit list of 0s and 1s
        """
        ret = []
Exemple #19
0
'''
Created on 22 Dec 2020

@author: Luke
'''



from AOC.config import config
config.set_wd(22)


class Player(object):
    def __init__(self, _id, deck):
        # Index 0 = top of deck
        self.deck = deck
        self.id = _id

    def can_play(self):
        return bool(self.deck)

    def get_next(self):
        if self.deck:
            return self.deck.pop(0)
        else:
            return None
        
    def add_cards(self, cards):
        """
        Add back to deck - highest card on top
        """
Exemple #20
0
'''
Created on 15 Dec 2020

@author: Luke
'''


from AOC.config import config
config.set_wd(15)


def get_input(input_type):
    if input_type == "test1":
        return [0, 3, 6]
    elif input_type == "test2":
        return [1, 3, 2]
    elif input_type == "test3":
        return [2, 1, 3]
    elif input_type == "test4":
        return [1, 2, 3]
    elif input_type == "test5":
        return [2, 3, 1]
    elif input_type == "test6":
        return [3, 2, 1]
    elif input_type == "test7":
        return [3, 1, 2]
    else:
        return [9, 3, 1, 0, 8, 4]
    
class MemoryGame(object):
    def __init__(self, starting_nums):
Exemple #21
0
'''
Created on 6 Dec 2020

@author: Luke
'''

from AOC.config import config
config.set_wd(6)

import numpy as np


def num_all_yes(group):
    s = set(group[0])
    for ns in group[1:]:
        s = s.intersection(ns)
    return len(s)


group_any_yes = []
with open("input.txt") as f:
    group = []
    for line in f.readlines():
        line = line.rstrip()
        if line == "":
            group_any_yes.append(num_all_yes(group))
            group = []
        else:
            group.append(line)
    # Need to add final group!
    group_any_yes.append(num_all_yes(group))
Exemple #22
0
'''
Created on 4 Dec 2020

@author: Luke
'''
'''
Created on 4 Dec 2020

@author: Luke
'''

from AOC.config import config
config.set_wd(3)


def run(x_increment, y_increment):
    def process_line(x_coord, trees_encountered, line):
        if line[x_coord - 1] == "#":
            trees_encountered += 1
        x_coord += x_increment
        if x_coord > len(line):
            x_coord = x_coord % len(line)
        return (x_coord, trees_encountered)

    x_coord = 1
    trees_encountered = 0
    lineno = 0
    with open("input.txt") as f:
        for line in f.readlines():
            if (lineno % y_increment) == 0:
                (x_coord,