def solution(): bingo = get_input("input.prod").split('\n\n') drawn_nums = clean_calling_numbers(bingo[0]) playing_boards = get_clean_boards(bingo[1:]) for i in range(4): playing_boards = call_number(playing_boards, drawn_nums[i]) winner = -1 last_number_called = -1 for num in drawn_nums[4:]: playing_boards = call_number(playing_boards, num) winner = check_for_winner(playing_boards) if winner > -1: last_number_called = num break winning_board = playing_boards[winner] sum_ = 0 for row in winning_board: for num in row: if not num[1]: sum_ += num[0] return sum_ * last_number_called
def get_product() -> int: ''' The puzzle was to get the product of multiple routes. This helper function keeps track of, and then returns, the product. ''' tree_map = get_input() slopes = [{ 'rise': 1, 'run': 1 }, { 'rise': 1, 'run': 3 }, { 'rise': 1, 'run': 5 }, { 'rise': 1, 'run': 7 }, { 'rise': 2, 'run': 1 }] product = 1 for slope in slopes: product *= count_trees(slope['rise'], slope['run'], tree_map) return product
def b_plot(files, ax, n_i, max_energy, msize, marker): """Plot alpha as a function of B""" values = [] count = 0 avg_deltaE = 0 for f in files: b, d, n = get_input(f) max_e = find_max_e(f) if max_energy else 0 if not max_energy: regex = r"""alpha_max_e_""" if re.compile(regex).search(f): continue if int(n) == n_i and max_energy == max_e: values.append([b, np.asscalar(np.loadtxt(f))]) if max_energy: avg_deltaE += max_e else: avg_deltaE += np.loadtxt(f.replace('alpha', 'stable'))[1] count += 1 if not count: print('No values for N =', n_i, 'and max energy', max_energy) return avg_deltaE = avg_deltaE / count print('Found', count, 'values for N =', n_i, 'and avg deltaE', avg_deltaE) # Plot the results ax.plot(np.array(values)[:, 0], np.array(values)[:, 1], linestyle='', label=r'$\Delta E\approx' + '{:.2f}'.format(avg_deltaE) + ', N=' + str(n_i) + '$', markersize=msize, marker=marker)
def debug_program() -> int: ''' We were told that the program bug was that exactly one operation was flipped, and that it was either a NOP to a JMP, or a JMP to a NOP. We'll iterate by line number, and for the given line in the program, first copy the program, then check the operation at the line, flip it if it is NOP or JMP. Then execute the program, and make sure it does not get caught in an infinite loop. We were told the program would only execute each instruction once, so the first repeat is considered an infinite loop. Return the accumulator value of the successfully run program. ''' program = get_input() for line_number in range(len(program)): program_copy = program.copy() (op, value, _) = parse_instruction(program_copy[line_number]) if op == 'acc': continue # Flip operation and write new instruction op = 'jmp' if op == 'nop' else 'nop' program_copy[line_number] = op + ' ' + str(value) accumulator = execute_program(program_copy) if accumulator > 0: return accumulator return -1
def solve(n_tiles): data = get_input('input.prod') G = [] for line in data: G.append([int(x) for x in line]) R = len(G) C = len(G[0]) DR = [-1, 0, 1, 0] DC = [0, 1, 0, -1] D = [[None for _ in range(n_tiles * C)] for _ in range(n_tiles * R)] Q = [(0, 0, 0)] while Q: (dist, r, c) = heapq.heappop(Q) if r < 0 or r >= n_tiles * R or c < 0 or c >= n_tiles * C: continue val = G[r % R][c % C] + (r // R) + (c // C) while val > 9: val -= 9 rc_cost = dist + val if D[r][c] is None or rc_cost < D[r][c]: D[r][c] = rc_cost else: continue if r == n_tiles * R - 1 and c == n_tiles * C - 1: break for d in range(4): rr = r + DR[d] cc = c + DC[d] heapq.heappush(Q, (D[r][c], rr, cc)) return D[n_tiles * R - 1][n_tiles * C - 1] - G[0][0]
def exectue_program() -> int: ''' This will execute the given program (puzzle input), and keep track of the accumulator value. Then it will return the accumulator value at the first repeated instruction. ''' program = get_input() accumulator = line_number = 0 while line_number < len(program): (op, value, was_executed) = parse_instruction(program[line_number]) if was_executed: break program[line_number] += ' executed' if op == 'acc': accumulator += value line_number += 1 elif op == 'jmp': line_number += value else: line_number += 1 return accumulator
def find_contiguous_subset(): ''' Given our input for part 1, we found an number that didn't fit the given criteria. We are then told that there exists a contiguous set of numbers in the input that will add to the invalid number. However, we were not told the subset size that will sum to the number. Starting with a set of 2, we'll loop though the input to find a subset of consecutive numbers that sum to the invalid number, incrementing the size of the subset with each loop. ''' values = get_input() invalid = find_invalid_number(values) subset_length = 2 while subset_length <= len(values): itr = 0 while itr + subset_length <= len(values): contiguous_subset = values[itr:itr + subset_length] if sum(contiguous_subset) == invalid: low, high = get_min_max(contiguous_subset) return low + high itr += 1 subset_length += 1
def get_octopi_map(): data = get_input("input.prod") o_map = list() for datum in data: o_map.append([int(flash_level) for flash_level in datum]) return o_map
def solution(): polymer, rules_raw = get_input("input.prod").split("\n\n") rules = parse_rules(rules_raw) frequencies = count_characters(polymer, rules) return max(frequencies.values()) - min(frequencies.values())
def solution(): initial_points, instructions = get_input("input.prod").split("\n\n") paper = place_initial(initial_points) instr_set = parse_instructions(instructions) paper = follow_instructions(paper, [instr_set[0]]) return count_dots(paper)
def day_18(): equations = get_input().splitlines() sum_ = 0 for equation in equations: equation = resolve_parens(equation) sum_ += int(calculate(equation)) return sum_
def solution(): polymer, rules_raw = get_input("input.prod").split("\n\n") rules = parse_rules(rules_raw) for _ in range(10): polymer = insertion(polymer, rules) return calc_difference(polymer)
def solution(): depths = [int(x) for x in get_input("input.prod")] total = 0 for i in range(4, len(depths)): if depths[i] > depths[i - 3]: total += 1 return total
def day_10(): values = get_input() dict = {1: 0, 2: 0, 3: 0} values.sort() dict[values[0]] += 1 for itr in range(len(values) - 1): dict[values[itr + 1] - values[itr]] += 1 dict[3] += 1 return dict[1] * dict[3]
def solution(): parens = get_input("input.prod") position = 0 floor = 0 for char in parens: floor += 1 if char == "(" else -1 position += 1 if floor == -1: return position
def solution(): fish = get_input("input.prod") for day in range(80): for i in range(len(fish)): fish[i] -= 1 if fish[i] == -1: fish[i] = 6 fish.append(8) return len(fish)
def find_seat_equilibrium(): seat_map = get_input() while True: next_seats = build_next_seat_map(seat_map) if next_seats == seat_map: break else: seat_map = next_seats return count_seats_occupied(seat_map)
def get(return_eigv=False, return_ket=False, return_index=False, return_cmax=False, return_H=False): """Return the eigenvalues and optionally the eigenvectors, the number operator form of the states(ket), the state index of the states, the max coefficient index and the Hamiltonian""" # Load files H = readH('npz') # read the Hamiltonian # Save to npz to save sapce if not isfile('hamilt.npz'): np.savez_compressed('hamilt.npz', H=H) remove('hamilt.bin') b, d, n = get_input() n = int(n) index = np.array([(n1, n2) for n1 in range(n) for n2 in range(n - n1)]) # Get eigenvalues and eigenvectors if isfile('eigensystem.npz'): print('Used cached result for: B =', b, 'D =', d, 'N =', n) eigensystem = np.load('eigensystem.npz') E = eigensystem['E'] eigenvectors = eigensystem['eigenvectors'] else: start = timer() E, eigenvectors = linalg.eigh(H, turbo=True) end = timer() print('Diagonalisation for N =', n, ':', end - start, 'seconds') # Save the results np.savez_compressed('eigensystem.npz', E=E, eigenvectors=eigenvectors) eigenvectors = np.transpose(eigenvectors) # each eigenvector is on one row # max coefficient in eigenvector c_max = np.empty(eigenvectors.shape[0], dtype=int) # The index of the largest coefficient for i in range(eigenvectors.shape[0]): c_max[i] = np.argmax(np.abs(eigenvectors[i])) results = (E, ) if return_eigv: results += (eigenvectors, ) if return_ket: results += (index[c_max], ) if return_index: results += (index, ) if return_cmax: results += (c_max, ) if return_H: results += (H, ) return results
def solution(): inputs = get_input("input.prod") lowest = 999999999 for i in range(min(inputs), max(inputs) + 1): sum_ = 0 for inp in inputs: sum_ += abs(i - inp) if sum_ < lowest: lowest = sum_ return lowest
def solution(): signals = get_input("input.prod") sum_ = 0 for signal in signals: codes, output = signal.split(" | ") codes = list(map(''.join, map(sorted, codes.split()))) output = list(map(''.join, map(sorted, output.split()))) digits = decode_wires(codes) sum_ += get_output(digits, output) return sum_
def solution(): inputs = get_input("input.prod") lowest = 999999999 for i in range(min(inputs), max(inputs) + 1): sum_ = 0 for inp in inputs: # The sum of integers between the two: (n * (n + 1)) / 2 fuel_burned = int((abs(i - inp) * (abs(i - inp) + 1)) / 2) sum_ += fuel_burned if sum_ < lowest: lowest = sum_ return lowest
def generate_dist_map(): data = get_input("input.prod") dist_map = {} city_col = [] for datum in data: [cities, distance] = datum.split(' = ') [city1, city2] = cities.split(' to ') if city1 not in city_col: city_col.append(city1) if city2 not in city_col: city_col.append(city2) dist_map[cities] = int(distance) dist_map[city2 + " to " + city1] = int(distance) return city_col, dist_map
def solution(): height_map = [] # Generate 2d array of heights for height in get_input("input.prod"): height_map.append([int(x) for x in height]) # Collect local minimums to sum later local_mins = [] for x in range(len(height_map)): for y in range(len(height_map[0])): if is_low_point(height_map, x, y): local_mins.append(height_map[x][y]) # len(local_mins) is the +1 on each min return sum(local_mins) + len(local_mins)
def anyone_answered_yes(): ''' We received a collection of questionnaires, where the groups of people are separated by a blank line, and an individual's answer is separated by a newline. We iterate through, and find all questions that were answered 'yes' (exist in the questionnaire for the individual) for the whole group. Then, return the sum of questions answered by each group. ''' questionnaires = get_input() count = 0 for questionnaire in questionnaires: for question in questions: if question in questionnaire: count += 1 return count
def solution(): instructions = get_input("input.prod") aim = 0 distance = 0 depth = 0 for instr in instructions: [direction, vector] = instr.split(" ") if direction == "forward": distance += int(vector) depth += aim * int(vector) elif direction == "down": aim += int(vector) else: aim -= int(vector) return distance * depth
def get_passports(): input_ = get_input() passports = [] tempstring = "" for passport in input_: if passport != '': tempstring += passport else: passports.append(tempstring) tempstring = "" # Add remaining passport if any. if tempstring: passports.append(tempstring) return passports
def sum_masked_values(): ''' Read the instructions to assign values to memory addresses, after the mask had been applied to those values. Then sum the values in the addresses. ''' values = get_input() memory = {} for val in values: if 'mask = ' in val: mask = val[7:] else: match = re.search(r'mem\[(\d+)\] = (\d+)', val) memory[int(match.group(1))] = apply_mask(int(match.group(2)), mask) return sum(list(memory.values()))
def day_17(): values = get_input().splitlines() cube = [] grid = [] for val in values: grid.append([c for c in val]) cube.append(grid) for _ in range(6): cube = add_layers(cube) cube = flip_cubes(cube) count = 0 for x in cube: for y in x: for z in y: if z == '#': count += 1 return count
def day_16(): groups = get_input().split('\n\n') rules = parse_rules(groups[0]) my_ticket = [int(n) for n in groups[1].split('\n')[1].split(',')] other_tickets = groups[2].split('\n')[1:-1] other_tickets = filter_tickets(rules, other_tickets) column_map = determine_columns(rules, other_tickets) product = 1 for col, name in column_map.items(): if 'departure' in name.pop(): product *= my_ticket[col] return product
def solution(): data = get_input("input.prod") hydro_map = {} for datum in data: [first, second] = datum.split(' -> ') [x1, y1] = [int(x) for x in first.split(',')] [x2, y2] = [int(x) for x in second.split(',')] hydro_map = handle_line(hydro_map, x1, y1, x2, y2) count = 0 for hydro in hydro_map.values(): if hydro > 1: count += 1 return count