Esempio n. 1
0
from utils import file_into_list
import numpy as np
from itertools import chain, combinations
import re

def powerset(iterable):
    s = list(iterable)
    return chain.from_iterable(combinations(s, r) for r in range(len(s)+1))

program = file_into_list("day14/input.txt")
multiplier = 10
memory = np.zeros(2**multiplier, dtype=np.int)


def parse_mask(line):
    _, mask = line.split(" = ")
    floatmask_indexes = []
    reversed_mask = mask[::-1]
    for i in range(len(mask)):
        if reversed_mask[i] == "X":
            floatmask_indexes.append(i)
    ormask = mask.replace("X", "0")
    andmask = mask.replace("X", "1")
    floatmask_combinations = powerset(floatmask_indexes)
    return int(ormask, 2), int(andmask, 2), floatmask_indexes, floatmask_combinations

def parse_mask2(line):
    _, mask = line.split(" = ")
    floatmask_indexes = []
    for i in range(len(mask)):
        if mask[i] == "X":
Esempio n. 2
0
from utils import file_into_list

expenses = file_into_list("day1/input.txt", lambda l: int(l))
N = len(expenses)


def part_1():
    for i in range(N):
        for j in range(i, N):
            if expenses[i] + expenses[j] == 2020:
                print(f"found {expenses[i]} and {expenses[j]}")
                print(f"multiplied: {expenses[i] * expenses[j]}")
                break


def part_2():
    for i in range(N):
        for j in range(i, N):
            for k in range(j, N):
                if expenses[i] + expenses[j] + expenses[k] == 2020:
                    print(
                        f"found {expenses[i]} and {expenses[j]} and {expenses[k]}"
                    )
                    print(
                        f"multiplied: {expenses[i] * expenses[j] * expenses[k]}"
                    )
                    break


part_2()
Esempio n. 3
0
from utils import file_into_list
import re


def parse(instruction):
    match = re.match("^([A-Z])(\d+)$", instruction)
    if not match:
        raise AssertionError("foobar")
    return match.group(1), int(match.group(2))


instructions = [parse(i) for i in file_into_list("day12/input.txt")]


class State:
    def __init__(self, pos, rot):
        self.pos = pos
        self.rot = rot

    def manhattan(self):
        return abs(self.pos[0]) + abs(self.pos[1])
    
    def __str__(self):
        return f"Pos: {self.pos}, Rot: {self.rot}"

# rot 0 is east, 90 is north, 180 is west, 270 is south

def part_1():
    def north(value, state):
        state.pos[1] += value
Esempio n. 4
0
from utils import file_into_list
import numpy as np

exprs = file_into_list("day18/input.txt")


def ev(expr, i=0):
    acc = 0
    op = None
    while i < len(expr):
        c = expr[i]
        if c == "+" or c == "*":
            op = c
        elif c == "(":
            subresult, new_i = ev(expr, i + 1)
            if op == "+":
                acc += subresult
            elif op == "*":
                acc *= subresult
            elif op is None:
                acc += subresult
            i = new_i
        elif c == ")":
            return acc, i
        else:
            if op == "+":
                acc += int(c)
            elif op == "*":
                acc *= int(c)
            elif op is None:
                acc = int(c)
Esempio n. 5
0
from utils import file_into_list
import numpy as np
from itertools import product

init = file_into_list("day17/input.txt")

def char_to_int(char):
    if char == "#":
        return 1
    elif char == ".":
        return 0

init_int = []
for line in init:
    init_int.append(list(map(char_to_int, list(line))))


L = 30
def get_neighbours(xyz, diffs):
    neighbour_positions = [xyz+diff for diff in diffs]
    neighbour_positions = np.clip(np.array(neighbour_positions), 0, L - 1)
    return neighbour_positions

def advance(old_state, new_state, lut):
    new_state.fill(0)
    it = np.nditer(old_state, flags=['multi_index'])
    for v in it:
        idx = it.multi_index
        neighbours = lut[idx]
        s = np.sum(old_state[tuple(neighbours.T)])
        if v == 1:
Esempio n. 6
0
from utils import file_into_list
from copy import deepcopy

_input = list(map(lambda line: list(line), file_into_list("day11/input.txt")))
floor = "."
empty = "L"
occup = "#"
width = len(_input[0])
height = len(_input)


def get_neighbourhood(point, layout):
    diffs = [[-1, -1], [0, -1], [1, -1], [1, 0], [1, 1], [0, 1], [-1, 1],
             [-1, 0]]
    return [
        at(point[0] + diff[0], point[1] + diff[1], layout) for diff in diffs
    ]


def at(y, x, layout):
    if x < 0 or y < 0 or x >= width or y >= height:
        return None
    else:
        return layout[y][x]


def part_1(inp):
    while True:
        res = deepcopy(inp)
        changes = 0
        for y in range(height):
Esempio n. 7
0
from utils import file_into_list
import numpy as np

adapters = list(map(int, file_into_list("day10/input.txt")))

builtin = max(adapters) + 3

adapters.append(builtin)
adapters.append(0)
adapters = sorted(adapters)
L = len(adapters)


def part_1():
    count_ones = 0
    count_threes = 0
    for i in range(1, len(adapters)):
        if adapters[i] - adapters[i - 1] == 1:
            count_ones += 1
        if adapters[i] - adapters[i - 1] == 3:
            count_threes += 1

    print(count_ones * count_threes)


def part_2_naive():
    def fork(i):
        print(f"{i}\n")
        s = 0
        if i + 1 < L and adapters[i + 1] - adapters[i] <= 3:
            s += fork(i + 1)
Esempio n. 8
0
from utils import file_into_list, test, file_into_string

tests = file_into_list("day15/tests_2.txt")
tests = [line.split(" ") for line in tests]
inputs, expected = zip(*tests)

inputs = [list(map(int, i.split(","))) for i in inputs]
expected = list(map(int, expected))

def solve(starting_numbers, position=30000000):
    print("Starting")
    memory = {}
    res = None
    most_recent = starting_numbers[-1] 
    for i, n in enumerate(starting_numbers):
        memory[n] = [i+1]
    for i in range(len(starting_numbers) + 1, position+1):
        #print(i, most_recent, memory)
        if len(memory[most_recent]) == 1:
            #print(f"Saving {0} at {i}")
            if 0 not in memory:
                memory[0] = [i]
            memory[0] = [memory[0][-1], i]
            res = 0
        else:
            num = memory[most_recent][1] - memory[most_recent][0]
            #print(f"Saving {num} at {i}")
            if num not in memory:
                memory[num] = [i]
            memory[num] = [memory[num][-1], i]
            res = num
Esempio n. 9
0
import re
from utils import file_into_list 

input_lines = file_into_list("day2/input.txt")

def parse_line(line):
    split = re.split("^(\d+)-(\d+) (\w): (\w+)$", line)
    min_num = int(split[1])
    max_num = int(split[2])
    char = split[3]
    password = split[4]
    return min_num, max_num, char, password


def count_char_in_string(char, string):
    count = 0
    for c in string:
        if c == char:
            count = count + 1
    return count

def is_password_valid_1(min_num, max_num, char, password):
    num_actual = count_char_in_string(char, password)
    return num_actual >= min_num and num_actual <= max_num


def is_password_valid_2(first_occurence, second_occurence, char, password):
    return (password[first_occurence - 1] == char and password[second_occurence - 1] != char) or (password[first_occurence - 1] != char and password[second_occurence - 1] == char)


def part_1():
Esempio n. 10
0
from utils import file_into_list

preamble_length = 25

L = list(map(int, file_into_list("day9/input.txt")))


def part_1():
    for i, value in enumerate(L[preamble_length:]):
        i = preamble_length + i
        print(i, value)
        preceeding = L[i - preamble_length:i]
        print(preceeding)
        hit = False
        for num in preceeding:
            sub = value - num
            print(f"sub {sub}")
            if sub in preceeding:
                hit = True
        if hit is False:
            print(f"value {value} at position {i} is invalid")
            break


find_number = 70639851  # position 561
position = 561


def get_sequence(_list):
    curr_length = 2
    while True:
Esempio n. 11
0
import re
from utils import file_into_list

rules = file_into_list("day7/input.txt")

def part_1():
    current_candidates = {"shiny gold"}
    while True:
        prev_count = len(current_candidates)
        for rule in rules:
            children_with_counts = re.findall("(\d+) (\w+ \w+) bags?", rule)
            parent_bag = re.match("^\w+ \w+", rule).group(0)
            for count, child in children_with_counts:
                if child in current_candidates:
                    current_candidates.add(parent_bag)
        if prev_count == len(current_candidates):
            break
    return len(current_candidates)

def make_graph(rules):
    graph = {}
    for rule in rules:
        children_with_counts = re.findall("(\d+) (\w+ \w+) bags?", rule)
        parent_bag_name = re.match("^\w+ \w+", rule).group(0)
        graph[parent_bag_name] = children_with_counts
    return graph


def part_2():
    g = make_graph(rules)
    def count_bags(gr, name):
Esempio n. 12
0
from utils import file_into_list, test

boarding_passes = file_into_list("day5/input.txt")

numrows = 128
numcols = 8


def midpoint(_min, _max):
    return (_min + _max) // 2


def get_seat_coordinates(boarding_pass):
    min_row = 0
    max_row = 127

    for i in range(7):
        if boarding_pass[i] == "F":
            max_row = midpoint(min_row, max_row)
        elif boarding_pass[i] == "B":
            min_row = midpoint(min_row, max_row) + 1
        # print(f"Min row: {min_row}. Max row: {max_row}.")

    min_col = 0
    max_col = 7
    for i in range(7, 10):
        if boarding_pass[i] == "L":
            max_col = midpoint(min_col, max_col)
        elif boarding_pass[i] == "R":
            min_col = midpoint(min_col, max_col) + 1
        # print(f"Min col: {min_col}. Max col: {max_col}.")
Esempio n. 13
0
from utils import file_into_list
from functools import reduce

map_ = file_into_list("day3/input.txt")


def count_trees(_map, slope):
    dx = slope[0]
    dy = slope[1]
    x = 0
    y = 0
    max_y = len(map_)
    line_length = len(map_[0])

    trees_count = 0
    while y < max_y:
        if map_[y][x] == "#":
            trees_count = trees_count + 1
        x = (x + dx) % line_length
        y = y + dy

    return trees_count


def part_1():
    print(count_trees(map_, (3, 1)))


def part_2():
    slopes = [(1, 1), (3, 1), (5, 1), (7, 1), (1, 2)]
    counts = [count_trees(map_, slope) for slope in slopes]
Esempio n. 14
0
from utils import file_into_list
import re

instructions = file_into_list("day8/input.txt")


def parse_ins(line):
    match = re.match("^(\w+) ((?:-|\+)\d+)$", line)
    if not match:
        raise AssertionError("No match when parsing line")
    return match.groups()


parsed_instructions = [parse_ins(i) for i in instructions]


class State:
    acc = 0
    ic = 0
    visited = set()

    def __init__(self, acc, ic):
        self.acc = acc
        self.ic = ic
        self.visited = set()

    def __str__(self):
        return f"Acc: {self.acc}, Ic: {self.ic}, Visited: {self.visited}"


def accumulate(state, value):
import math
from utils import test, file_into_list

wire1, wire2 = file_into_list("day3/input.txt", lambda x: x.split(","))


def manhattan_distance_from_origin(coords):
    """
    Gives the manhattan distance to origin
    """
    return abs(coords[0]) + abs(coords[1])


def intersection(lst1, lst2):
    return list(set(lst1) & set(lst2))


def intersection_with_sums(lst1, lst2):
    """
    Finds the intersections between two lists along with the sum of indexes
    Very slow version
    """
    common_points = []
    for i, coord in enumerate(lst1):
        try:
            j = lst2.index(coord)
            if j > 0:
                common_points.append((coord, i+j))
        except ValueError:
            pass
    return common_points
Esempio n. 16
0
from utils import file_into_list, test
import numpy as np

inp = file_into_list("day13/input.txt")
ts = int(inp[0])
bus_ids = inp[1].split(",")


def part_1():
    count = 0
    success = False
    while success == False:
        dep = ts + count
        for bus_id in bus_ids:
            if bus_id == 'x':
                continue
            else:
                if dep % int(bus_id) == 0:
                    print(count, int(bus_id))
                    print(count * int(bus_id))
                    success = True
                    break
        count += 1


def sum_term(prev_ids, prev_divs):
    res = 0
    for i in range(len(prev_divs)):
        div = prev_divs[i]
        res += div * np.prod(prev_ids[:i])
    return res