visited.append(pointer) [(op, args)] = instruction[pointer].items() step = int(args) if pointer == i: op = 'nop' if op == 'jmp' else 'jmp' if op == 'acc': accumulator += step pointer += 1 elif op == 'jmp': pointer += step elif op == 'nop': pointer += 1 return visited, pointer, accumulator boot_code = load_day(8) parse_data(boot_code) # part a visited, _, accumulator = terminate() print(accumulator) # part b for i in visited: [(op, args)] = instruction[i].items() if op in ('nop', 'jmp'): _, j, accumulator = terminate(i) if j >= len(instruction): print(accumulator) break
# Source: https://github.com/sijmn/aoc2020/blob/master/python/day14.py from data import load_day data = load_day(14) mem = {} for line in data: l, r = line.split(' = ') if l == 'mask': and_mask = int(r.replace('X', '1'), base=2) or_mask = int(r.replace('X', '0'), base=2) else: value = int(r) value &= and_mask # each bit of output is 1 if x AND y is 1, otherwise it's 0 value |= or_mask # each bit of output is 0 if x AND y is 0, otheriwse it's 1 mem[int(l[4:-1])] = value print(sum(mem.values()))
from data import load_day def count_trees(lines, rise, run): line_size = len(lines[0]) x, tree_count = 0, 0 for line in lines[::rise]: tree_count += line[x] == '#' x = (x + run) % line_size return tree_count lines = load_day(3) # part a print(count_trees(lines, 1, 3)) # 276 # part b print(count_trees(lines, 1, 1) * \ count_trees(lines, 1, 3) * \ count_trees(lines, 1, 5) * \ count_trees(lines, 1, 7) * \ count_trees(lines, 2, 1))
_letter = letter[0] res.append(Password(int(_min), int(_max), _letter, password)) return res def password_range_policy_validator(content): count = 0 for ele in content: freq = ele.password.count(ele.letter) if ele.min <= freq <= ele.max: count += 1 print(count) def password_position_policy_validator(content): count = 0 for ele in content: try: # ^ XOR operator sets bit to 1 if one of two bits is 1 if (ele.password[ele.min-1] == ele.letter) ^ \ (ele.password[ele.max-1] == ele.letter): count += 1 except IndexError: continue print(count) lines = load_day(2) content = parse(lines) password_range_policy_validator(content) password_position_policy_validator(content)
def calculate_min_wait_time(ts, buses): wait_times = [bus - ts % bus for bus in buses] bus_index = wait_times.index(min(wait_times)) return buses[bus_index] * min(wait_times) def calculate_subsequent_departures(buses): ''' We need to find a number such that it's divisible by the first bus, then second bus + index, and so on. Take 7, 13, x, x, 59... for an example. At 77, 77 % 7 = 0, and 78 % 13 = 0. So, the n is where n % 7 = 0, (n + 1) % 13 = 0, and (n + 4) % 59 = 0. Note that all bus IDs are prime numbers so we can just iterate with the LCM until it meets our codition. The maximum solution is the product of all numbers. ''' time, step = 0, 1 for delta, bus in buses.items(): while ( time + delta ) % bus: # if not divisible, enter while loop; if divisible, we found the LCM, exit while loop time += step # add step until time + delta is divisible by bus ID step *= bus # lcm of previous numbers is added to step to ensure that the next number will be divisible by previous AND current return time data = load_day(13) ts = int(data[0]) buses = {i: int(bus) for i, bus in enumerate(data[1].split(',')) if bus != 'x'} print(calculate_min_wait_time(ts, list(buses.values()))) print(calculate_subsequent_departures(buses))
import re from data import load_day data = load_day(16) partition = [i for i, ele in enumerate(data) if len(ele) == 0] # entities is separated by empty string rules = data[:partition[0]] my_ticket = data[partition[0] + 2:partition[1]] nearby_tickets = data[partition[1] + 2:] # print(rules, my_ticket, nearby_tickets) invalid = [] for ticket in nearby_tickets: tickets = [int(t) for t in ticket.split(',')] for ticket in tickets: result = [] for rule in rules: rule = re.match(r'(.*): (.*)', rule).groups()[1].split() rule_1 = rule[0].split('-') rule_2 = rule[2].split('-') if int(rule_1[0]) <= ticket <= int(rule_1[1]) or \ int(rule_2[0]) <= ticket <= int(rule_2[1]): result.append(True) else: result.append(False) if not any(result):
def calculate(postfix_exp): result = [] for token in postfix_exp: if token.isnumeric(): result.append(token) else: a = int(result.pop()) b = int(result.pop()) c = a * b if token == '*' else a + b result.append(c) return result.pop() data = load_day(18) results_1, results_2 = [], [] for infix_exp in data: tokenized_infix_exp = tokenize(infix_exp) # part 1 - addition and multiplication have the same presedence precedence_1 = {'(': 0, '*': 1, '+': 1} postfix_exp_1 = convert_to_postfix(tokenized_infix_exp, precedence=precedence_1) results_1.append(calculate(postfix_exp_1)) # part 2 - addition is evaluated before multiplication precedence_2 = {'(': 0, '*': 1, '+': 2} postfix_exp_2 = convert_to_postfix(tokenized_infix_exp, precedence=precedence_2) results_2.append(calculate(postfix_exp_2)) print(sum(results_1))
invalid = None for i in data[preamble_length:]: seen = set() for j in preamble: if i - j in seen: preamble.popleft() preamble.append(i) break seen.add(j) else: invalid = i break return invalid data = [int(x) for x in load_day(9)] # part a invalid = find_invalid_number(data, preamble_length=5) print(invalid) # part b l = r = total = 0 while total != invalid: while total < invalid: total += data[r] r += 1 while total > invalid: total -= data[l] l += 1 print(min(data[l:r]) + max(data[l:r]))
for col in range(col_size): adjacents = get_adjacents(grid, row, col, row_size, col_size) if grid[row][col] == "L" and "#" not in adjacents: new_row += "#" elif grid[row][col] == "#" and adjacents.count("#") >= 4: new_row += "L" else: new_row += grid[row][col] new_grid.append(new_row) return new_grid seating = load_day(11) default_grid = [] for i in seating: row = [] for char in i: row.append(char) default_grid.append(row) row_size = len(default_grid) col_size = len(default_grid[0]) # part a process = True while process: occupied_grid = get_occupied_seats(default_grid, row_size, col_size) if occupied_grid == default_grid:
from data import load_day def memory_game(seen, last, limit): for i in range(len(seen), limit): # tmp = last # last = i - seen.get(last, i) # seen[tmp] = i seen[last], last = i, i - seen.get(last, i) return last data = load_day(15) data = [int(ele) for ele in data[0].split(',')] last = data[-1] seen = {num: turn + 1 for turn, num in enumerate(data)} # part one print(memory_game(seen.copy(), last, 2020)) # part two -- takes 12 seconds print(memory_game(seen.copy(), last, 30000000))
for i in range(len(data) - 1): diff = data[i + 1] - data[i] if diff <= 3: rating[diff] += 1 return rating[1] * ( rating[3] + 1 ) # built-in adapter is always 3 higher than the highest adapter def get_total_paths(data): paths = defaultdict(int) paths[0] = 1 for adapter in sorted(data): for diff in range(1, 4): next = adapter + diff if next in data: paths[next] += paths[adapter] x = max(paths, key=int) return paths[x] data = load_day(10) data = [int(x) for x in data] # part a print(multiply_jolt_differences(data)) # part b print(get_total_paths(data))
bags = defaultdict(dict) def parse_data(luggage_rules): for rule in luggage_rules: outside_bag = re.match(r'(.*) bags contain', rule).groups()[0] for count, inside_bag in re.findall(r'(\d+) (\w+ \w+) bags?', rule): bags[outside_bag][inside_bag] = int(count) return bags answer = set() def search(color): for bag in bags: if color in bags[bag]: answer.add(bag) search(bag) return len(answer) def count(color): total = 1 for bag in bags[color]: multiplier = bags[color][bag] total += multiplier * count(bag) return total luggage_rules = load_day(7) parse_data(luggage_rules) bag = 'shiny gold' # part a print(search(bag)) # part b print(count(bag)-1)
return min(_min, _max) if df == min_char else max(_min, _max) def get_seat_ids(boarding_passes): seat_ids = [] for bp in boarding_passes: rows = bp[:6] deciding_factor = bp[6] cols = bp[7:] row = seat_id_calculator(rows, 0, 127, 'F', 'B', deciding_factor) col = seat_id_calculator(cols, 0, 7, 'L', 'R', deciding_factor) unique_seat_id = row * 8 + col seat_ids.append(unique_seat_id) return seat_ids def find_my_seat(seat_ids): return [ seat for seat in range(min(seat_ids), max(seat_ids)) if seat not in seat_ids ][0] boarding_passes = load_day(5) seat_ids = get_seat_ids(boarding_passes) # part a print(max(seat_ids)) # part b print(find_my_seat(seat_ids))
return list(map(int, lines)) def multiply_two_sum(target, nums): difference = {} for num in nums: if num in difference: print(num * difference[num]) else: difference[target-num] = num def multiply_three_sum(target, nums): nums.sort() for i in range(len(nums)): l, r = i + 1, len(nums)-1 while l < r: _sum = nums[i] + nums[l] + nums[r] if _sum == target: print(nums[i] * nums[l] * nums[r]) break if _sum > target: r -= 1 elif _sum < target: l += 1 lines = load_day(1) content = parse(lines) param={'target': 2020, 'nums': content} multiply_two_sum(**param) multiply_three_sum(**param)
one_passport.append(line) return passports_with_all_required_fields def count_valid_passports(fields, passports): no_of_valid_passport = 0 for passport in passports: fields = passport.split(' ') parsed_fields = dict(field.split(':') for field in fields) no_of_valid_passport += all( v(parsed_fields[k]) for k, v in required_passport_fields.items()) return no_of_valid_passport passports = load_day(4) required_passport_fields = { 'byr': lambda x: 1920 <= int(x) <= 2002, 'iyr': lambda x: 2010 <= int(x) <= 2020, 'eyr': lambda x: 2020 <= int(x) <= 2030, 'hgt': lambda x: (x.endswith('cm') and 150 <= int(x[:-2]) <= 193) or (x.endswith('in') and 59 <= int(x[:-2]) <= 76), 'hcl': lambda x: re.match('^#[0-9a-f]{6}$', x), 'ecl': lambda x: x in ['amb', 'blu', 'brn', 'gry', 'grn', 'hzl', 'oth'], 'pid':