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":
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()
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
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)
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:
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):
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)
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
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():
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:
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):
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}.")
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]
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
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