from code.utils import parse_input inputs = parse_input(13, '\n', sample=False) # part one dt = int(inputs[0]) buses = [int(b) for b in inputs[1].split(',') if b.isnumeric()] diff = None cb = None for bus in buses: ct = ((int(dt / bus) + 1) * bus) - dt if not diff or ct < diff: diff = ct cb = bus print(diff * cb) # part two buses2 = [] for bus in inputs[1].split(','): if bus.isnumeric(): buses2.append(int(bus)) else: buses2.append(0) pairs = [ ] # pairs is a terrible name. This is really something like "buses_with_offsets" for i in range(len(buses2)): pairs.append([buses2[i], i]) pairs = list(reversed(sorted(pairs)))
from code.utils import parse_input import re input = parse_input(17, '\n', sample=False) XYZW_OFFSETS = [] for ix in (0, -1, 1): for iy in (0, -1, 1): for iz in (0, -1, 1): for iw in (0, -1, 1): XYZW_OFFSETS.append([ix, iy, iz, iw]) XYZW_OFFSETS.remove([0,0,0,0]) print(f'num_neighbors is {len(XYZW_OFFSETS)}') def is_active(x, y, z, w, state): if (x not in state or y not in state[x] or z not in state[x][y] or w not in state[x][y][z]): return False return state[x][y][z][w] == '#' def calc_new_state(x, y, z, w, state): active_neighbors = 0 for xo, yo, zo, wo in XYZW_OFFSETS: if is_active(x+xo, y+yo, z+zo, w+wo, state): active_neighbors += 1
from code.utils import parse_input import re nums = parse_input(15, '\n', sample=False) nums = [int(n) for n in nums[0].split(',')] max_turn = 2020 # 30000000 last_spoken = {} spoken_once = set() spoken_multi = set() last_num = None def add_or_remove_from_spoken_once(num): if num not in spoken_once and num not in spoken_multi: spoken_once.add(num) elif num in spoken_once: spoken_once.remove(num) spoken_multi.add(num) def add_to_spoken(num, index): if num not in last_spoken: last_spoken[num] = [index] else: before = last_spoken[num] last_spoken[num] = [before[-1], index] def get_diff(num): if num not in last_spoken: return None
from code.utils import parse_input import re bags = parse_input(7, '\n') ### part one bag_map = {} bag_count_map = {} for bag in bags: [bag_type, raw_sub] = re.match('(.*)bags contain (.*).', bag).groups() bag_type = bag_type.strip() raw_sub = raw_sub.split(', ') sub_bags = [] set_sub_bags = set() for raw in raw_sub: if raw == 'no other bags': sub_bags.append([0, None]) else: validated = re.match('(\d+) (.*) bags?', raw).groups() sub_bags.append(list(validated)) set_sub_bags.add(validated[1]) bag_map[bag_type] = list(set_sub_bags) bag_count_map[bag_type] = sub_bags def contains_gold(bag): if bag not in bag_map: return False if 'shiny gold' in bag_map[bag]:
from code.utils import parse_input import re players = parse_input(22, '\n\n', sample=False) def get_cards(player_input): cards = player_input.split('\n')[1:] cards = [int(c) for c in cards] return cards player_cards = [get_cards(i) for i in players] # part one while len(player_cards[0]) > 0 and len(player_cards[1]) > 0: p1 = player_cards[0].pop(0) p2 = player_cards[1].pop(0) if p1 > p2: player_cards[0].append(p1) player_cards[0].append(p2) elif p2 > p1: player_cards[1].append(p2) player_cards[1].append(p1) else: import ipdb ipdb.set_trace() winning_deck = player_cards[0] + player_cards[1] total = 0
from code.utils import parse_input import re input = parse_input(19, '\n\n', sample=False) rules = input[0].split('\n') lines = input[1].split('\n') meta_rules = {} straight_rules = {} cache = {} def parse_rules(rules): for rule in rules: index, logic = rule.split(': ') if "\"" in logic: straight_rules[index] = logic[1] else: options = logic.split(" | ") for op in options: op = op.split(" ") if index not in meta_rules: meta_rules[index] = [] meta_rules[index].append(op) def add_to_cache(rule_num, matched): if rule_num not in cache: cache[rule_num] = {matched} else: cache[rule_num].add(matched)
from code.utils import parse_input import re cup_nums = parse_input(23, '\n', sample=False)[0] cup_nums = [int(c) for c in cup_nums] # part one solution # moves = 100 # num_followers = 3 # # current_value = cup_nums[0] # # def find_index(val): # try: # return cup_nums.index(val) # except: # return None # # # for m in range(moves): # followers = [] # for f in range(num_followers): # followers.append(cup_nums.pop( (find_index(current_value)+1) % len(cup_nums))) # # dest_val = current_value - 1 # dest_i = find_index(dest_val) # end = False # while not end and dest_i is None: # dest_val -= 1 # dest_i = find_index(dest_val) # if dest_val <= 0: # dest_val = max(cup_nums)
from code.utils import parse_input import re lines = parse_input(14, '\n', sample=False) def binary_to_int(answer_list): return [int(a, 2) for a in answer_list] def all_permutations(astring): if not astring: return [''] prefix = '' suffix = astring while len(suffix) > 0 and suffix[0] != 'X': prefix += suffix[0] suffix = suffix[1:] if not suffix: fset = set() fset.add(prefix) return fset answers = set() suffix_permutations = all_permutations(suffix[1:]) for perm in suffix_permutations: answers.add(prefix + '0' + perm) answers.add(prefix + '1' + perm)
from code.utils import parse_input input = parse_input(24, '\n', sample=False) final_tiles = {} valid_directions = ['e', 'se', 'sw', 'w', 'nw', 'ne'] get_offsets = { 'e': [0, 2], 'w': [0, -2], 'se': [-2, 1], 'nw': [2, -1], 'sw': [-2, -1], 'ne': [2, 1] } def parse_dirs(line): dirs = [] curr = '' for c in line: curr += c if curr in valid_directions: dirs.append(curr) curr = '' return dirs def get_pos(dirs):
from code.utils import parse_input import re foods = parse_input(21, '\n', sample=False) all_allergens = {} all_ingredients = [] set_ingredients = set() for i in range(len(foods)): food = foods[i] [ingredients, allergens] = food.split(' (contains ') ingredients = ingredients.split(' ') all_ingredients.append(ingredients) for ing in ingredients: set_ingredients.add(ing) allergens = allergens[:-1].split(', ') for allergen in allergens: if allergen not in all_allergens: all_allergens[allergen] = [] all_allergens[allergen].append(i) def intersect(indices): inter = set(all_ingredients[indices[0]]) for i in indices[1:]: inter = inter.intersection(set(all_ingredients[i])) return inter