├── .gitignore ├── 2019_01_p1.py ├── 2019_01_p2.py ├── 2019_02_p1.py ├── 2019_02_p2.py ├── 2019_03_p1.py ├── 2019_03_p2.py ├── 2019_04_p1.py ├── 2019_04_p2.py ├── 2019_05_p1.py ├── 2019_05_p2.py ├── 2019_06_p1.py ├── 2019_06_p2.py ├── 2019_07_p1.py ├── 2019_07_p2.py ├── 2019_08_animation.py ├── 2019_08_p1.py ├── 2019_08_p2.py ├── 2019_09_p1.py ├── 2019_09_p2.py ├── 2019_10_p1.py ├── 2019_10_p2.py ├── 2019_11_animation.py ├── 2019_11_p1.py ├── 2019_11_p2.py ├── 2019_12_p1.py ├── 2019_12_p2.py ├── 2019_13_p1.py ├── 2019_13_p2.py ├── 2019_14_p1.py ├── 2019_14_p2.py ├── 2019_15_animation.py ├── 2019_15_p1.py ├── 2019_15_p2.py ├── 2019_16_p1.py ├── 2019_16_p2.py ├── 2019_17_p1.py ├── 2019_17_p2.py ├── 2019_18_p1.py ├── 2019_18_p2.py ├── 2019_19_p1.py ├── 2019_19_p2.py ├── 2019_20_p1.py ├── 2019_20_p2.py ├── 2019_21_p1.py ├── 2019_21_p2.py ├── 2019_22_p1.py ├── 2019_22_p2.py ├── 2019_23_animation.py ├── 2019_23_p1.py ├── 2019_23_p2.py ├── 2019_24_p1.py ├── 2019_24_p2.py ├── 2019_25_p1.py ├── LICENSE ├── README.md ├── aoc.py ├── extras ├── README.md ├── day_11_hull.gif ├── day_15_area.gif ├── day_23_network.gif └── day_8_bios.gif └── files ├── input01 ├── input02 ├── input03 ├── input04 ├── input05 ├── input06 ├── input07 ├── input08 ├── input09 ├── input10 ├── input11 ├── input12 ├── input13 ├── input14 ├── input15 ├── input16 ├── input17 ├── input18 ├── input19 ├── input20 ├── input21 ├── input22 ├── input23 ├── input24 └── input25 /.gitignore: -------------------------------------------------------------------------------- 1 | __pycache__/ -------------------------------------------------------------------------------- /2019_01_p1.py: -------------------------------------------------------------------------------- 1 | from aoc import read_file, timer 2 | 3 | def calc_cost(mass): 4 | return mass // 3 - 2 5 | 6 | @timer 7 | def solve(): 8 | input = read_file("01") 9 | mass = [int(x) for x in input] 10 | return sum([calc_cost(m) for m in mass]) 11 | 12 | result = solve() 13 | print(f"Solution: {result}") -------------------------------------------------------------------------------- /2019_01_p2.py: -------------------------------------------------------------------------------- 1 | from aoc import read_file, timer 2 | 3 | def calc_cost(mass): 4 | return mass // 3 - 2 5 | 6 | @timer 7 | def solve(): 8 | input = read_file("01") 9 | mass = [int(x) for x in input] 10 | 11 | result = 0 12 | 13 | for m in mass: 14 | while (m := calc_cost(m)) > 0: 15 | result += m 16 | 17 | return result 18 | 19 | result = solve() 20 | print(f"Solution: {result}") -------------------------------------------------------------------------------- /2019_02_p1.py: -------------------------------------------------------------------------------- 1 | from aoc import read_file, timer 2 | 3 | @timer 4 | def solve(): 5 | input = read_file("02")[0].split(",") 6 | input = [int(x) for x in input] 7 | 8 | pos = 0 9 | input[1] = 12 10 | input[2] = 2 11 | 12 | while input[pos] != 99: 13 | if input[pos] == 1: 14 | input[input[pos+3]] = input[input[pos+1]] + input[input[pos+2]] 15 | 16 | if input[pos] == 2: 17 | input[input[pos+3]] = input[input[pos+1]] * input[input[pos+2]] 18 | 19 | pos += 4 20 | 21 | return input[0] 22 | 23 | result = solve() 24 | print(f"Solution: {result}") -------------------------------------------------------------------------------- /2019_02_p2.py: -------------------------------------------------------------------------------- 1 | from aoc import read_file, timer 2 | 3 | @timer 4 | def solve(): 5 | input = read_file("02")[0].split(",") 6 | input_store = [int(x) for x in input] 7 | 8 | for noun in range(100): 9 | for verb in range(100): 10 | input = input_store[:] 11 | pos = 0 12 | input[1] = noun 13 | input[2] = verb 14 | 15 | while input[pos] != 99: 16 | if input[pos] == 1: 17 | input[input[pos+3]] = input[input[pos+1]] + input[input[pos+2]] 18 | 19 | if input[pos] == 2: 20 | input[input[pos+3]] = input[input[pos+1]] * input[input[pos+2]] 21 | 22 | pos += 4 23 | 24 | if input[0] == 19690720: 25 | return 100 * noun + verb 26 | 27 | result = solve() 28 | print(f"Solution: {result}") -------------------------------------------------------------------------------- /2019_03_p1.py: -------------------------------------------------------------------------------- 1 | from aoc import read_file, timer 2 | 3 | def manhattan(pos): 4 | return abs(pos[0]) + abs(pos[1]) 5 | 6 | def get_wire_positions(wire): 7 | x, y = 0, 0 8 | positions = set() 9 | 10 | for i in range(len(wire)): 11 | for _ in range(int(wire[i][1:])): 12 | direction = wire[i][0] 13 | 14 | if direction == "R": 15 | x +=1 16 | elif direction == "L": 17 | x -=1 18 | elif direction == "D": 19 | y +=1 20 | elif direction == "U": 21 | y -=1 22 | 23 | positions.add((x, y)) 24 | 25 | return positions 26 | 27 | @timer 28 | def solve(): 29 | input = read_file("03") 30 | wire_1 = input[0].split(",") 31 | wire_2 = input[1].split(",") 32 | 33 | positions_1 = get_wire_positions(wire_1) 34 | positions_2 = get_wire_positions(wire_2) 35 | 36 | crossings = positions_1.intersection(positions_2) 37 | 38 | return min(manhattan(pos) for pos in crossings) 39 | 40 | result = solve() 41 | print(f"Solution: {result}") -------------------------------------------------------------------------------- /2019_03_p2.py: -------------------------------------------------------------------------------- 1 | from aoc import read_file, timer 2 | from collections import defaultdict 3 | 4 | def get_wire_positions(wire): 5 | x, y = 0, 0 6 | positions = set() 7 | 8 | for i in range(len(wire)): 9 | for _ in range(int(wire[i][1:])): 10 | direction = wire[i][0] 11 | 12 | if direction == "R": 13 | x +=1 14 | elif direction == "L": 15 | x -=1 16 | elif direction == "D": 17 | y +=1 18 | elif direction == "U": 19 | y -=1 20 | 21 | positions.add((x, y)) 22 | 23 | return positions 24 | 25 | def get_distance_for_crossings(wire, crossings): 26 | crossing = defaultdict(int) 27 | distance = 0 28 | x, y = 0, 0 29 | 30 | for i in range(len(wire)): 31 | for _ in range(int(wire[i][1:])): 32 | direction = wire[i][0] 33 | 34 | if direction == "R": 35 | x +=1 36 | elif direction == "L": 37 | x -=1 38 | elif direction == "D": 39 | y +=1 40 | elif direction == "U": 41 | y -=1 42 | 43 | distance += 1 44 | 45 | if (x, y) in crossings: 46 | crossing[(x, y)] = distance 47 | 48 | return crossing 49 | 50 | @timer 51 | def solve(): 52 | input = read_file("03") 53 | wire_1 = input[0].split(",") 54 | wire_2 = input[1].split(",") 55 | 56 | x1, y1, x2, y2 = 0, 0, 0, 0 57 | 58 | positions_1 = get_wire_positions(wire_1) 59 | positions_2 = get_wire_positions(wire_2) 60 | 61 | crossings = positions_1.intersection(positions_2) 62 | 63 | crossing_distance_1 = get_distance_for_crossings(wire_1, crossings) 64 | crossing_distance_2 = get_distance_for_crossings(wire_2, crossings) 65 | 66 | return min(crossing_distance_1[crossing] + crossing_distance_2[crossing] for crossing in crossings) 67 | 68 | result = solve() 69 | print(f"Solution: {result}") -------------------------------------------------------------------------------- /2019_04_p1.py: -------------------------------------------------------------------------------- 1 | from aoc import read_file, timer 2 | 3 | def increases(num): 4 | num = list(str(num)) 5 | 6 | if num == sorted(num): 7 | return True 8 | return False 9 | 10 | def all_digits_unique(num): 11 | num = str(num) 12 | return len(num) == len(set(num)) 13 | 14 | @timer 15 | def solve(): 16 | input = read_file("04") 17 | start, end = [int(num) for num in input[0].split("-")] 18 | 19 | return sum(increases(num) and not all_digits_unique(num) for num in range(start, end+1)) 20 | 21 | result = solve() 22 | print(f"Solution: {result}") -------------------------------------------------------------------------------- /2019_04_p2.py: -------------------------------------------------------------------------------- 1 | from aoc import read_file, timer 2 | 3 | def increases(num): 4 | num = list(str(num)) 5 | 6 | if num == sorted(num): 7 | return True 8 | return False 9 | 10 | def has_double(num): 11 | num = list(str(num)) 12 | 13 | for i in range(5): 14 | if num[i] == num[i+1] and \ 15 | (i == 0 or num[i] != num[i-1]) and \ 16 | (i == 4 or num[i] != num[i+2]): 17 | return True 18 | return False 19 | 20 | @timer 21 | def solve(): 22 | input = read_file("04") 23 | start, end = [int(num) for num in input[0].split("-")] 24 | 25 | return sum(increases(num) and has_double(num) for num in range(start, end+1)) 26 | 27 | result = solve() 28 | print(f"Solution: {result}") 29 | -------------------------------------------------------------------------------- /2019_05_p1.py: -------------------------------------------------------------------------------- 1 | from aoc import read_file, timer 2 | 3 | def split_instruction(instruction): 4 | instruction = f"{instruction:05}" 5 | return instruction[3:], instruction[0:3] 6 | 7 | def get_values(input, pos, op, modes): 8 | mode_a, mode_b, mode_c = modes 9 | values = [] 10 | 11 | if op in ["01", "02", "04"]: 12 | if mode_c == "0": 13 | values.append(input[input[pos+1]]) 14 | else: 15 | values.append(input[pos+1]) 16 | 17 | if op in ["01", "02"]: 18 | if mode_b == "0": 19 | values.append(input[input[pos+2]]) 20 | else: 21 | values.append(input[pos+2]) 22 | 23 | if op in []: 24 | if mode_a == "0": 25 | values.append(input[input[pos+3]]) 26 | else: 27 | values.append(input[pos+3]) 28 | 29 | return values 30 | 31 | @timer 32 | def solve(): 33 | prog = read_file("05")[0].split(",") 34 | prog = [int(x) for x in prog] 35 | 36 | ip = 0 37 | input = 1 38 | 39 | while prog[ip] != 99: 40 | op, modes = split_instruction(prog[ip]) 41 | values = get_values(prog, ip, op, modes) 42 | 43 | if op == "01": # Addition 44 | prog[prog[ip+3]] = values[0] + values[1] 45 | ip += 4 46 | 47 | if op == "02": # Multiplication 48 | prog[prog[ip+3]] = values[0] * values[1] 49 | ip += 4 50 | 51 | if op == "03": # Read and Store prog 52 | prog[prog[ip+1]] = input 53 | ip += 2 54 | 55 | if op == "04": # Print Output 56 | print(values[0]) 57 | ip += 2 58 | 59 | result = solve() 60 | -------------------------------------------------------------------------------- /2019_05_p2.py: -------------------------------------------------------------------------------- 1 | from aoc import read_file, timer 2 | 3 | def split_instruction(instruction): 4 | instruction = f"{instruction:05}" 5 | return instruction[3:], instruction[0:3] 6 | 7 | def get_values(input, pos, op, modes): 8 | mode_a, mode_b, mode_c = modes 9 | values = [] 10 | 11 | if op in ["01", "02", "04", "05", "06", "07", "08"]: 12 | if mode_c == "0": 13 | values.append(input[input[pos+1]]) 14 | else: 15 | values.append(input[pos+1]) 16 | 17 | if op in ["01", "02", "05", "06", "07", "08"]: 18 | if mode_b == "0": 19 | values.append(input[input[pos+2]]) 20 | else: 21 | values.append(input[pos+2]) 22 | 23 | if op in []: 24 | if mode_a == "0": 25 | values.append(input[input[pos+3]]) 26 | else: 27 | values.append(input[pos+3]) 28 | 29 | return values 30 | 31 | @timer 32 | def solve(): 33 | prog = read_file("05")[0].split(",") 34 | prog = [int(x) for x in prog] 35 | 36 | ip = 0 37 | input = 5 38 | 39 | while prog[ip] != 99: 40 | op, modes = split_instruction(prog[ip]) 41 | values = get_values(prog, ip, op, modes) 42 | 43 | if op == "01": # Addition 44 | prog[prog[ip+3]] = values[0] + values[1] 45 | ip += 4 46 | 47 | if op == "02": # Multiplication 48 | prog[prog[ip+3]] = values[0] * values[1] 49 | ip += 4 50 | 51 | if op == "03": # Read and Store prog 52 | prog[prog[ip+1]] = input 53 | ip += 2 54 | 55 | if op == "04": # Print Output 56 | print(values[0]) 57 | ip += 2 58 | 59 | if op == "05": # Jump-if-True 60 | if values[0]: 61 | ip = values[1] 62 | else: 63 | ip += 3 64 | 65 | if op == "06": # Jump-if-False 66 | if not values[0]: 67 | ip = values[1] 68 | else: 69 | ip += 3 70 | 71 | if op == "07": # Less than 72 | if values[0] < values[1]: 73 | prog[prog[ip+3]] = 1 74 | else: 75 | prog[prog[ip+3]] = 0 76 | ip += 4 77 | 78 | if op == "08": # Equals 79 | if values[0] == values[1]: 80 | prog[prog[ip+3]] = 1 81 | else: 82 | prog[prog[ip+3]] = 0 83 | ip += 4 84 | 85 | result = solve() 86 | -------------------------------------------------------------------------------- /2019_06_p1.py: -------------------------------------------------------------------------------- 1 | from aoc import read_file, timer 2 | 3 | def get_pos(orbits, planet): 4 | pos = 0 5 | while planet in orbits.keys(): 6 | planet = orbits[planet] 7 | pos += 1 8 | return pos 9 | 10 | def get_all_planets(input): 11 | return set(planet for line in input for planet in line.split(")")) 12 | 13 | def generate_orbit_dict(input): 14 | orbits = {} 15 | 16 | for line in input: 17 | planets = line.split(")") 18 | orbits[planets[1]] = planets[0] 19 | 20 | return orbits 21 | 22 | def solve(): 23 | input = read_file("06") 24 | 25 | orbits = generate_orbit_dict(input) 26 | all_planets = get_all_planets(input) 27 | 28 | return sum(get_pos(orbits, k) for k in all_planets) 29 | 30 | result = solve() 31 | print(f"Solution: {result}") 32 | -------------------------------------------------------------------------------- /2019_06_p2.py: -------------------------------------------------------------------------------- 1 | from aoc import read_file, timer 2 | 3 | def get_planet_position(orbits, planet): 4 | pos = 0 5 | while planet in orbits.keys(): 6 | planet = orbits[planet] 7 | pos += 1 8 | return pos 9 | 10 | def get_planets(orbits, positions, planet): 11 | planets = [] 12 | 13 | while planet in orbits.keys(): 14 | planet = orbits[planet] 15 | planets.append(planet) 16 | 17 | return planets 18 | 19 | def get_all_planets(input): 20 | return set(planet for line in input for planet in line.split(")")) 21 | 22 | def get_all_positions(all_planets, orbits): 23 | positions = {} 24 | 25 | for planet in all_planets: 26 | positions[planet] = get_planet_position(orbits, planet) 27 | 28 | return positions 29 | 30 | def generate_orbit_dict(input): 31 | orbits = dict() 32 | 33 | for line in input: 34 | planets = line.split(")") 35 | orbits[planets[1]] = planets[0] 36 | 37 | return orbits 38 | 39 | def solve(): 40 | input = read_file("06") 41 | 42 | orbits = generate_orbit_dict(input) 43 | all_planets = get_all_planets(input) 44 | positions = get_all_positions(all_planets, orbits) 45 | 46 | san = get_planets(orbits, positions, "SAN") 47 | you = get_planets(orbits, positions, "YOU") 48 | 49 | maximum = max(positions[planet] for planet in set(san).intersection(set(you))) 50 | 51 | return positions["SAN"] + positions["YOU"] - 2 * maximum - 2 52 | 53 | result = solve() 54 | print(f"Solution: {result}") 55 | -------------------------------------------------------------------------------- /2019_07_p1.py: -------------------------------------------------------------------------------- 1 | from aoc import read_file, timer 2 | from itertools import permutations 3 | 4 | def split_instruction(instruction): 5 | instruction = f"{instruction:05}" 6 | return instruction[3:], instruction[0:3] 7 | 8 | def get_values(input, pos, op, modes): 9 | mode_a, mode_b, mode_c = modes 10 | values = [] 11 | 12 | if op in ["01", "02", "04", "05", "06", "07", "08"]: 13 | if mode_c == "0": 14 | values.append(input[input[pos+1]]) 15 | else: 16 | values.append(input[pos+1]) 17 | 18 | if op in ["01", "02", "05", "06", "07", "08"]: 19 | if mode_b == "0": 20 | values.append(input[input[pos+2]]) 21 | else: 22 | values.append(input[pos+2]) 23 | 24 | if op in []: 25 | if mode_a == "0": 26 | values.append(input[input[pos+3]]) 27 | else: 28 | values.append(input[pos+3]) 29 | 30 | return values 31 | 32 | def run_amp(phase, input, prog): 33 | input_counter = 0 34 | ip = 0 35 | 36 | while prog[ip] != 99: 37 | op, modes = split_instruction(prog[ip]) 38 | values = get_values(prog, ip, op, modes) 39 | 40 | if op == "01": # Addition 41 | prog[prog[ip+3]] = values[0] + values[1] 42 | ip += 4 43 | 44 | if op == "02": # Multiplication 45 | prog[prog[ip+3]] = values[0] * values[1] 46 | ip += 4 47 | 48 | if op == "03": # Read and Store prog 49 | if not input_counter: 50 | prog[prog[ip+1]] = phase 51 | else: 52 | prog[prog[ip+1]] = input 53 | input_counter += 1 54 | ip += 2 55 | 56 | if op == "04": # Print Output 57 | output = values[0] 58 | ip += 2 59 | 60 | if op == "05": # Jump-if-True 61 | if values[0]: 62 | ip = values[1] 63 | else: 64 | ip += 3 65 | 66 | if op == "06": # Jump-if-False 67 | if not values[0]: 68 | ip = values[1] 69 | else: 70 | ip += 3 71 | 72 | if op == "07": # Less than 73 | if values[0] < values[1]: 74 | prog[prog[ip+3]] = 1 75 | else: 76 | prog[prog[ip+3]] = 0 77 | ip += 4 78 | 79 | if op == "08": # Equals 80 | if values[0] == values[1]: 81 | prog[prog[ip+3]] = 1 82 | else: 83 | prog[prog[ip+3]] = 0 84 | ip += 4 85 | return output 86 | 87 | 88 | def solve(): 89 | prog = read_file("07")[0].split(",") 90 | prog = [int(x) for x in prog] 91 | 92 | max_thrust = 0 93 | 94 | for phases in permutations(range(5), 5): 95 | output = 0 96 | 97 | for phase in phases: 98 | output = run_amp(phase, output, prog) 99 | max_thrust = max(max_thrust, output) 100 | 101 | return max_thrust 102 | 103 | result = solve() 104 | print(f"Solution: {result}") -------------------------------------------------------------------------------- /2019_07_p2.py: -------------------------------------------------------------------------------- 1 | from aoc import read_file, timer 2 | from itertools import permutations 3 | 4 | class Amp: 5 | def __init__(self, prog): 6 | self.prog = prog[:] 7 | self.ip = 0 8 | self.output = 0 9 | self.input_counter = 0 10 | self.halt = False 11 | 12 | def split_instruction(instruction): 13 | instruction = f"{instruction:05}" 14 | return instruction[3:], instruction[0:3] 15 | 16 | def get_values(input, pos, op, modes): 17 | mode_a, mode_b, mode_c = modes 18 | values = [] 19 | 20 | if op in ["01", "02", "04", "05", "06", "07", "08"]: 21 | if mode_c == "0": 22 | values.append(input[input[pos+1]]) 23 | else: 24 | values.append(input[pos+1]) 25 | 26 | if op in ["01", "02", "05", "06", "07", "08"]: 27 | if mode_b == "0": 28 | values.append(input[input[pos+2]]) 29 | else: 30 | values.append(input[pos+2]) 31 | 32 | if op in []: 33 | if mode_a == "0": 34 | values.append(input[input[pos+3]]) 35 | else: 36 | values.append(input[pos+3]) 37 | 38 | return values 39 | 40 | def run_amp(phase, input, amp): 41 | while amp.prog[amp.ip] != 99: 42 | op, modes = split_instruction(amp.prog[amp.ip]) 43 | values = get_values(amp.prog, amp.ip, op, modes) 44 | 45 | if op == "01": # Addition 46 | amp.prog[amp.prog[amp.ip+3]] = values[0] + values[1] 47 | amp.ip += 4 48 | 49 | if op == "02": # Multiplication 50 | amp.prog[amp.prog[amp.ip+3]] = values[0] * values[1] 51 | amp.ip += 4 52 | 53 | if op == "03": # Read and Store input 54 | if not amp.input_counter: 55 | amp.prog[amp.prog[amp.ip+1]] = phase 56 | else: 57 | amp.prog[amp.prog[amp.ip+1]] = input 58 | 59 | amp.input_counter += 1 60 | amp.ip += 2 61 | 62 | if op == "04": # Print Output 63 | amp.output = values[0] 64 | amp.ip += 2 65 | return amp 66 | 67 | if op == "05": # Jump-if-True 68 | if values[0]: 69 | amp.ip = values[1] 70 | else: 71 | amp.ip += 3 72 | 73 | if op == "06": # Jump-if-False 74 | if not values[0]: 75 | amp.ip = values[1] 76 | else: 77 | amp.ip += 3 78 | 79 | if op == "07": # Less than 80 | if values[0] < values[1]: 81 | amp.prog[amp.prog[amp.ip+3]] = 1 82 | else: 83 | amp.prog[amp.prog[amp.ip+3]] = 0 84 | amp.ip += 4 85 | 86 | if op == "08": # Equals 87 | if values[0] == values[1]: 88 | amp.prog[amp.prog[amp.ip+3]] = 1 89 | else: 90 | amp.prog[amp.prog[amp.ip+3]] = 0 91 | amp.ip += 4 92 | 93 | amp.halt = True 94 | return amp 95 | 96 | @timer 97 | def solve(): 98 | prog = read_file("07")[0].split(",") 99 | prog = [int(x) for x in prog] 100 | max_thrust = 0 101 | 102 | for phases in permutations(range(5, 10), 5): 103 | amps = [Amp(prog) for i in range(5)] 104 | active = 0 105 | 106 | while not amps[4].halt: 107 | amps[active] = run_amp(phases[active], amps[active-1].output, amps[active]) 108 | active = (active + 1) % 5 109 | 110 | max_thrust = max(max_thrust, amps[4].output) 111 | return max_thrust 112 | 113 | result = solve() 114 | print(f"Solution: {result}") 115 | 116 | -------------------------------------------------------------------------------- /2019_08_animation.py: -------------------------------------------------------------------------------- 1 | from aoc import read_file, timer 2 | from collections import defaultdict 3 | from os import path 4 | from PIL import Image, ImageDraw 5 | 6 | def extract_layers(raw, size): 7 | layers = defaultdict(list) 8 | layer = -1 9 | 10 | for i in range(len(raw)): 11 | if not i % size: 12 | layer += 1 13 | layers[layer].append(raw[i]) 14 | 15 | return layers 16 | 17 | def print_image(layers): 18 | scale = 20 19 | for layer in range(100): 20 | img = Image.new('RGBA', (25*scale, 6*scale), (255, 0, 0, 0)) 21 | draw = ImageDraw.Draw(img) 22 | for y in range(6): 23 | for x in range(25): 24 | pos = x + y * 25 25 | if layers[layer][pos] == 0: 26 | draw.ellipse((x*scale, y*scale, x*scale+scale-1, y*scale+scale-1), fill=(255, 255, 255)) 27 | elif layers[layer][pos] == 1: 28 | draw.ellipse((x*scale, y*scale, x*scale+scale-1, y*scale+scale-1), fill=(0, 0, 0)) 29 | file_path = path.join('images', f"BIOS{100-layer:03}.png") 30 | img.save(file_path, 'PNG') 31 | 32 | @timer 33 | def solve(): 34 | input = read_file("08") 35 | input = [int(x) for x in input[0]] 36 | 37 | size = 25 * 6 38 | layers = extract_layers(input, size) 39 | 40 | print_image(layers) 41 | 42 | solve() -------------------------------------------------------------------------------- /2019_08_p1.py: -------------------------------------------------------------------------------- 1 | from aoc import read_file, timer 2 | from collections import defaultdict 3 | 4 | def extract_layers(raw, size): 5 | layers = defaultdict(list) 6 | layer = -1 7 | 8 | for i in range(len(raw)): 9 | if not i % size: 10 | layer += 1 11 | layers[layer].append(raw[i]) 12 | 13 | return layers 14 | 15 | @timer 16 | def solve(): 17 | input = read_file("08") 18 | input = [int(x) for x in input[0]] 19 | 20 | size = 25 * 6 21 | layers = extract_layers(input, size) 22 | 23 | zero_counts = [pixels.count(0) for pixels in layers.values()] 24 | result_layer = zero_counts.index(min(zero_counts)) 25 | 26 | return layers[result_layer].count(1) * layers[result_layer].count(2) 27 | 28 | result = solve() 29 | print(f"Solution: {result}") -------------------------------------------------------------------------------- /2019_08_p2.py: -------------------------------------------------------------------------------- 1 | from aoc import read_file, timer 2 | from collections import defaultdict 3 | 4 | def extract_layers(raw, size): 5 | layers = defaultdict(list) 6 | layer = -1 7 | 8 | for i in range(len(raw)): 9 | if not i % size: 10 | layer += 1 11 | layers[layer].append(raw[i]) 12 | 13 | return layers 14 | 15 | def print_image(layers): 16 | for y in range(6): 17 | for x in range(25): 18 | pos = x + y * 25 19 | for lay in range(100): 20 | if layers[lay][pos] == 2: 21 | continue 22 | if layers[lay][pos] == 1: 23 | print("#", end="") 24 | else: 25 | print(" ", end="") 26 | break 27 | print() 28 | 29 | @timer 30 | def solve(): 31 | input = read_file("08") 32 | input = [int(x) for x in input[0]] 33 | 34 | size = 25 * 6 35 | layers = extract_layers(input, size) 36 | 37 | print_image(layers) 38 | 39 | solve() -------------------------------------------------------------------------------- /2019_09_p1.py: -------------------------------------------------------------------------------- 1 | from aoc import read_file, timer 2 | from collections import defaultdict 3 | 4 | class Booster: 5 | def __init__(self, prog): 6 | self.prog = prog 7 | self.ip = 0 8 | self.output = 0 9 | self.rel_base = 0 10 | 11 | def split_instruction(instruction): 12 | instruction = f"{instruction:05}" 13 | return instruction[3:], instruction[0:3] 14 | 15 | def get_values(input, pos, op, modes, booster): 16 | mode_a, mode_b, mode_c = modes 17 | values = [] 18 | offset = 0 19 | 20 | if op in ["01", "02", "04", "05", "06", "07", "08", "09"]: 21 | if mode_c == "0": 22 | values.append(input[input[pos+1]]) 23 | elif mode_c == "1": 24 | values.append(input[pos+1]) 25 | elif mode_c == "2": 26 | values.append(input[input[pos+1]+booster.rel_base]) 27 | 28 | if op in ["01", "02", "05", "06", "07", "08"]: 29 | if mode_b == "0": 30 | values.append(input[input[pos+2]]) 31 | elif mode_b == "1": 32 | values.append(input[pos+2]) 33 | elif mode_b == "2": 34 | values.append(input[input[pos+2]+booster.rel_base]) 35 | 36 | if op in []: 37 | if mode_a == "0": 38 | values.append(input[input[pos+3]]) 39 | elif mode_a == "1": 40 | values.append(input[pos+3]) 41 | elif mode_a == "2": 42 | values.append(input[input[pos+3]+booster.rel_base]) 43 | 44 | if op in ["01", "02", "07", "08"]: 45 | if mode_a == "2": 46 | offset = booster.rel_base 47 | 48 | if op in ["03"]: 49 | if mode_c == "2": 50 | offset = booster.rel_base 51 | 52 | return values, offset 53 | 54 | def run_booster(input, booster): 55 | while booster.prog[booster.ip] != 99: 56 | op, modes = split_instruction(booster.prog[booster.ip]) 57 | values, offset = get_values(booster.prog, booster.ip, op, modes, booster) 58 | 59 | if op == "01": # Addition 60 | booster.prog[booster.prog[booster.ip+3] + offset] = values[0] + values[1] 61 | booster.ip += 4 62 | 63 | if op == "02": # Multiplication 64 | booster.prog[booster.prog[booster.ip+3] + offset] = values[0] * values[1] 65 | booster.ip += 4 66 | 67 | if op == "03": # Read and Store input 68 | booster.prog[booster.prog[booster.ip+1] + offset] = input 69 | booster.ip += 2 70 | 71 | if op == "04": # Print Output 72 | booster.output = values[0] 73 | print(booster.output) 74 | booster.ip += 2 75 | 76 | if op == "05": # Jump-if-True 77 | if values[0]: 78 | booster.ip = values[1] 79 | else: 80 | booster.ip += 3 81 | 82 | if op == "06": # Jump-if-False 83 | if not values[0]: 84 | booster.ip = values[1] 85 | else: 86 | booster.ip += 3 87 | 88 | if op == "07": # Less than 89 | if values[0] < values[1]: 90 | booster.prog[booster.prog[booster.ip+3] + offset] = 1 91 | else: 92 | booster.prog[booster.prog[booster.ip+3] + offset] = 0 93 | booster.ip += 4 94 | 95 | if op == "08": # Equals 96 | if values[0] == values[1]: 97 | booster.prog[booster.prog[booster.ip+3] + offset] = 1 98 | else: 99 | booster.prog[booster.prog[booster.ip+3] + offset] = 0 100 | booster.ip += 4 101 | 102 | if op == "09": # Adjust Relative Base 103 | booster.rel_base += values[0] 104 | booster.ip += 2 105 | 106 | return booster 107 | 108 | def create_program(input): 109 | prog = defaultdict(int) 110 | 111 | for i in range(len(input)): 112 | prog[i] = int(input[i]) 113 | 114 | return prog 115 | 116 | @timer 117 | def solve(): 118 | input = read_file("09")[0].split(",") 119 | prog = create_program(input) 120 | 121 | booster = Booster(prog) 122 | booster = run_booster(1, booster) 123 | 124 | return(booster.output) 125 | 126 | result = solve() 127 | print(f"Solution: {result}") 128 | 129 | -------------------------------------------------------------------------------- /2019_09_p2.py: -------------------------------------------------------------------------------- 1 | from aoc import read_file, timer 2 | from collections import defaultdict 3 | 4 | class Booster: 5 | def __init__(self, prog): 6 | self.prog = prog 7 | self.ip = 0 8 | self.output = 0 9 | self.rel_base = 0 10 | 11 | def split_instruction(instruction): 12 | instruction = f"{instruction:05}" 13 | return instruction[3:], instruction[0:3] 14 | 15 | def get_values(input, pos, op, modes, booster): 16 | mode_a, mode_b, mode_c = modes 17 | values = [] 18 | offset = 0 19 | 20 | if op in ["01", "02", "04", "05", "06", "07", "08", "09"]: 21 | if mode_c == "0": 22 | values.append(input[input[pos+1]]) 23 | elif mode_c == "1": 24 | values.append(input[pos+1]) 25 | elif mode_c == "2": 26 | values.append(input[input[pos+1]+booster.rel_base]) 27 | 28 | if op in ["01", "02", "05", "06", "07", "08"]: 29 | if mode_b == "0": 30 | values.append(input[input[pos+2]]) 31 | elif mode_b == "1": 32 | values.append(input[pos+2]) 33 | elif mode_b == "2": 34 | values.append(input[input[pos+2]+booster.rel_base]) 35 | 36 | if op in []: 37 | if mode_a == "0": 38 | values.append(input[input[pos+3]]) 39 | elif mode_a == "1": 40 | values.append(input[pos+3]) 41 | elif mode_a == "2": 42 | values.append(input[input[pos+3]+booster.rel_base]) 43 | 44 | if op in ["01", "02", "07", "08"]: 45 | if mode_a == "2": 46 | offset = booster.rel_base 47 | 48 | if op in ["03"]: 49 | if mode_c == "2": 50 | offset = booster.rel_base 51 | 52 | return values, offset 53 | 54 | def run_booster(input, booster): 55 | while booster.prog[booster.ip] != 99: 56 | op, modes = split_instruction(booster.prog[booster.ip]) 57 | values, offset = get_values(booster.prog, booster.ip, op, modes, booster) 58 | 59 | if op == "01": # Addition 60 | booster.prog[booster.prog[booster.ip+3] + offset] = values[0] + values[1] 61 | booster.ip += 4 62 | 63 | if op == "02": # Multiplication 64 | booster.prog[booster.prog[booster.ip+3] + offset] = values[0] * values[1] 65 | booster.ip += 4 66 | 67 | if op == "03": # Read and Store input 68 | booster.prog[booster.prog[booster.ip+1] + offset] = input 69 | booster.ip += 2 70 | 71 | if op == "04": # Print Output 72 | booster.output = values[0] 73 | print(booster.output) 74 | booster.ip += 2 75 | 76 | if op == "05": # Jump-if-True 77 | if values[0]: 78 | booster.ip = values[1] 79 | else: 80 | booster.ip += 3 81 | 82 | if op == "06": # Jump-if-False 83 | if not values[0]: 84 | booster.ip = values[1] 85 | else: 86 | booster.ip += 3 87 | 88 | if op == "07": # Less than 89 | if values[0] < values[1]: 90 | booster.prog[booster.prog[booster.ip+3] + offset] = 1 91 | else: 92 | booster.prog[booster.prog[booster.ip+3] + offset] = 0 93 | booster.ip += 4 94 | 95 | if op == "08": # Equals 96 | if values[0] == values[1]: 97 | booster.prog[booster.prog[booster.ip+3] + offset] = 1 98 | else: 99 | booster.prog[booster.prog[booster.ip+3] + offset] = 0 100 | booster.ip += 4 101 | 102 | if op == "09": # Adjust Relative Base 103 | booster.rel_base += values[0] 104 | booster.ip += 2 105 | 106 | return booster 107 | 108 | def create_program(input): 109 | prog = defaultdict(int) 110 | 111 | for i in range(len(input)): 112 | prog[i] = int(input[i]) 113 | 114 | return prog 115 | 116 | @timer 117 | def solve(): 118 | input = read_file("09")[0].split(",") 119 | prog = create_program(input) 120 | 121 | booster = Booster(prog) 122 | booster = run_booster(2, booster) 123 | 124 | return(booster.output) 125 | 126 | result = solve() 127 | print(f"Solution: {result}") 128 | 129 | -------------------------------------------------------------------------------- /2019_10_p1.py: -------------------------------------------------------------------------------- 1 | from aoc import read_file, timer 2 | 3 | def greatest_common_divisor(x, y): 4 | if not x: 5 | return abs(y) 6 | if not y: 7 | return abs(x) 8 | 9 | while y: 10 | x, y = y, x % y 11 | return abs(x) 12 | 13 | # Get all directions where an asteroid can be seen from station 14 | def get_directions(station, asteroids): 15 | directions = set() 16 | for asteroid in asteroids: 17 | if asteroid == station: 18 | continue 19 | 20 | vec = (asteroid[0] - station[0], asteroid[1] - station[1]) 21 | gcd = greatest_common_divisor(vec[0], vec[1]) 22 | vec = (vec[0] // gcd, vec[1] // gcd) 23 | 24 | directions.add(vec) 25 | 26 | return directions 27 | 28 | @timer 29 | def solve(): 30 | input = read_file("10") 31 | size_x, size_y = len(input[0]), len(input) 32 | 33 | asteroids = [(x, y) for y in range(size_y) for x in range(size_x) if input[y][x] == "#"] 34 | 35 | return max([len(get_directions(station, asteroids)) for station in asteroids]) 36 | 37 | result = solve() 38 | print(f"Solution: {result}") 39 | 40 | 41 | -------------------------------------------------------------------------------- /2019_10_p2.py: -------------------------------------------------------------------------------- 1 | from aoc import read_file, timer 2 | from math import atan, degrees 3 | 4 | from collections import defaultdict 5 | 6 | def greatest_common_divisor(x, y): 7 | if not x: 8 | return abs(y) 9 | if not y: 10 | return abs(x) 11 | 12 | while y: 13 | x, y = y, x % y 14 | return abs(x) 15 | 16 | # Get all directions where an asteroid can be seen from station 17 | def get_directions(station, asteroids): 18 | directions = set() 19 | for asteroid in asteroids: 20 | if asteroid == station: 21 | continue 22 | 23 | vec = (asteroid[0] - station[0], asteroid[1] - station[1]) 24 | gcd = greatest_common_divisor(vec[0], vec[1]) 25 | vec = (vec[0] // gcd, vec[1] // gcd) 26 | 27 | directions.add(vec) 28 | 29 | return directions 30 | 31 | def get_best_station(asteroids): 32 | asteroids_in_los = [len(get_directions(station, asteroids)) for station in asteroids] 33 | station_id = asteroids_in_los.index(max(asteroids_in_los)) 34 | return asteroids[station_id] 35 | 36 | def calc_angle(vector): 37 | if vector[1] == 0: 38 | return 90 39 | return degrees(atan(vector[0]/vector[1])) 40 | 41 | def split_quadrants(directions): 42 | quadrants = [] 43 | quadrants.append([x for x in directions if x[0] >= 0 and x[1] < 0]) 44 | quadrants.append([x for x in directions if x[0] > 0 and x[1] >= 0]) 45 | quadrants.append([x for x in directions if x[0] <= 0 and x[1] > 0]) 46 | quadrants.append([x for x in directions if x[0] < 0 and x[1] <= 0]) 47 | return quadrants 48 | 49 | def shoot(quadrants, station, asteroids, size_x, size_y): 50 | target_amount = len(asteroids) - 200 51 | while True: 52 | for quadrant in quadrants: 53 | for direction in quadrant: 54 | multi = 1 55 | while True: 56 | coord = (station[0] + direction[0] * multi, station[1] + direction[1] * multi) 57 | 58 | if coord[0] < 0 or coord[0] > size_x or \ 59 | coord[1] < 0 or coord[1] > size_y: 60 | break 61 | 62 | if coord in asteroids: 63 | asteroids.remove(coord) 64 | 65 | if len(asteroids) == target_amount: 66 | return coord[0]*100 + coord[1] 67 | break 68 | multi += 1 69 | 70 | @timer 71 | def solve(): 72 | input = read_file("10") 73 | size_x, size_y = len(input[0]), len(input) 74 | 75 | asteroids = [(x, y) for y in range(size_y) for x in range(size_x) if input[y][x] == "#"] 76 | station = get_best_station(asteroids) 77 | 78 | directions = list(get_directions(station, asteroids)) 79 | directions.sort(key = lambda direction:calc_angle(direction), reverse = True) 80 | 81 | quadrants = split_quadrants(directions) 82 | 83 | return shoot(quadrants, station, asteroids, size_x, size_y) 84 | 85 | result = solve() 86 | print(f"Solution: {result}") 87 | -------------------------------------------------------------------------------- /2019_11_animation.py: -------------------------------------------------------------------------------- 1 | from aoc import read_file, timer 2 | from collections import defaultdict 3 | from PIL import Image, ImageDraw 4 | 5 | class Painter: 6 | def __init__(self, prog): 7 | self.prog = prog 8 | self.ip = 0 9 | self.output = 0 10 | self.rel_base = 0 11 | self.halt = False 12 | 13 | def split_instruction(instruction): 14 | instruction = f"{instruction:05}" 15 | return instruction[3:], instruction[0:3] 16 | 17 | def get_values(input, pos, op, modes, painter): 18 | mode_a, mode_b, mode_c = modes 19 | values = [] 20 | offset = 0 21 | 22 | if op in ["01", "02", "04", "05", "06", "07", "08", "09"]: 23 | if mode_c == "0": 24 | values.append(input[input[pos+1]]) 25 | elif mode_c == "1": 26 | values.append(input[pos+1]) 27 | elif mode_c == "2": 28 | values.append(input[input[pos+1]+painter.rel_base]) 29 | 30 | if op in ["01", "02", "05", "06", "07", "08"]: 31 | if mode_b == "0": 32 | values.append(input[input[pos+2]]) 33 | elif mode_b == "1": 34 | values.append(input[pos+2]) 35 | elif mode_b == "2": 36 | values.append(input[input[pos+2]+painter.rel_base]) 37 | 38 | if op in []: 39 | if mode_a == "0": 40 | values.append(input[input[pos+3]]) 41 | elif mode_a == "1": 42 | values.append(input[pos+3]) 43 | elif mode_a == "2": 44 | values.append(input[input[pos+3]+painter.rel_base]) 45 | 46 | if op in ["01", "02", "07", "08"]: 47 | if mode_a == "2": 48 | offset = painter.rel_base 49 | 50 | if op in ["03"]: 51 | if mode_c == "2": 52 | offset = painter.rel_base 53 | 54 | return values, offset 55 | 56 | def run_booster(input, painter): 57 | while painter.prog[painter.ip] != 99: 58 | op, modes = split_instruction(painter.prog[painter.ip]) 59 | values, offset = get_values(painter.prog, painter.ip, op, modes, painter) 60 | 61 | if op == "01": # Addition 62 | painter.prog[painter.prog[painter.ip+3] + offset] = values[0] + values[1] 63 | painter.ip += 4 64 | 65 | if op == "02": # Multiplication 66 | painter.prog[painter.prog[painter.ip+3] + offset] = values[0] * values[1] 67 | painter.ip += 4 68 | 69 | if op == "03": # Read and Store input 70 | painter.prog[painter.prog[painter.ip+1] + offset] = input 71 | painter.ip += 2 72 | 73 | if op == "04": # Print Output 74 | painter.output = values[0] 75 | #print(painter.output) 76 | painter.ip += 2 77 | return painter 78 | 79 | if op == "05": # Jump-if-True 80 | if values[0]: 81 | painter.ip = values[1] 82 | else: 83 | painter.ip += 3 84 | 85 | if op == "06": # Jump-if-False 86 | if not values[0]: 87 | painter.ip = values[1] 88 | else: 89 | painter.ip += 3 90 | 91 | if op == "07": # Less than 92 | if values[0] < values[1]: 93 | painter.prog[painter.prog[painter.ip+3] + offset] = 1 94 | else: 95 | painter.prog[painter.prog[painter.ip+3] + offset] = 0 96 | painter.ip += 4 97 | 98 | if op == "08": # Equals 99 | if values[0] == values[1]: 100 | painter.prog[painter.prog[painter.ip+3] + offset] = 1 101 | else: 102 | painter.prog[painter.prog[painter.ip+3] + offset] = 0 103 | painter.ip += 4 104 | 105 | if op == "09": # Adjust Relative Base 106 | painter.rel_base += values[0] 107 | painter.ip += 2 108 | 109 | painter.halt = True 110 | return painter 111 | 112 | def create_program(input): 113 | prog = defaultdict(int) 114 | 115 | for i in range(len(input)): 116 | prog[i] = int(input[i]) 117 | 118 | return prog 119 | 120 | def turn_and_move(pos, dir, turn): 121 | if turn == 0: 122 | dir = (dir - 1) % 4 123 | else: 124 | dir = (dir + 1) % 4 125 | 126 | if dir == 0: # up 127 | pos = (pos[0], pos[1] - 1) 128 | elif dir == 1: # right 129 | pos = (pos[0]+1, pos[1]) 130 | elif dir == 2: # down 131 | pos = (pos[0], pos[1] + 1) 132 | elif dir == 3: # left 133 | pos = (pos[0] - 1, pos[1]) 134 | 135 | return pos, dir 136 | 137 | def draw_panel(panel, robot, step): 138 | scale = 12 139 | 140 | img = Image.new('RGBA', (40*scale, 6*scale), (255, 0, 0, 0)) 141 | draw = ImageDraw.Draw(img) 142 | for y in range(6): 143 | for x in range(40): 144 | if panel[(x, y)] == 0: 145 | draw.ellipse((x*scale, y*scale, x*scale+scale-1, y*scale+scale-1), fill=(255, 255, 255)) 146 | elif panel[(x, y)] == 1: 147 | draw.ellipse((x*scale, y*scale, x*scale+scale-1, y*scale+scale-1), fill=(0, 0, 0)) 148 | 149 | draw.ellipse((robot[0]*scale, robot[1]*scale, robot[0]*scale+scale-1, robot[1]*scale+scale-1), fill=(255, 0, 0)) 150 | 151 | img.save(f"images\Panel{250-step}.png", 'PNG') 152 | 153 | @timer 154 | def solve(): 155 | input = read_file("11")[0].split(",") 156 | prog = create_program(input) 157 | 158 | panel = defaultdict(int) 159 | painter = Painter(prog) 160 | 161 | dir = 0 162 | pos = (-1, 0) 163 | panel[(-1, 0)] = 1 164 | step = 0 165 | 166 | while not painter.halt: 167 | painter = run_booster(panel[pos], painter) 168 | color = painter.output 169 | painter = run_booster(panel[pos], painter) 170 | turn = painter.output 171 | 172 | panel[pos] = color 173 | 174 | pos, dir = turn_and_move(pos, dir, turn) 175 | 176 | draw_panel(panel, pos, step) 177 | step += 1 178 | 179 | solve() -------------------------------------------------------------------------------- /2019_11_p1.py: -------------------------------------------------------------------------------- 1 | from aoc import read_file, timer 2 | from collections import defaultdict 3 | 4 | class Painter: 5 | def __init__(self, prog): 6 | self.prog = prog 7 | self.ip = 0 8 | self.output = 0 9 | self.rel_base = 0 10 | self.halt = False 11 | 12 | def split_instruction(instruction): 13 | instruction = f"{instruction:05}" 14 | return instruction[3:], instruction[0:3] 15 | 16 | def get_values(input, pos, op, modes, painter): 17 | mode_a, mode_b, mode_c = modes 18 | values = [] 19 | offset = 0 20 | 21 | if op in ["01", "02", "04", "05", "06", "07", "08", "09"]: 22 | if mode_c == "0": 23 | values.append(input[input[pos+1]]) 24 | elif mode_c == "1": 25 | values.append(input[pos+1]) 26 | elif mode_c == "2": 27 | values.append(input[input[pos+1]+painter.rel_base]) 28 | 29 | if op in ["01", "02", "05", "06", "07", "08"]: 30 | if mode_b == "0": 31 | values.append(input[input[pos+2]]) 32 | elif mode_b == "1": 33 | values.append(input[pos+2]) 34 | elif mode_b == "2": 35 | values.append(input[input[pos+2]+painter.rel_base]) 36 | 37 | if op in []: 38 | if mode_a == "0": 39 | values.append(input[input[pos+3]]) 40 | elif mode_a == "1": 41 | values.append(input[pos+3]) 42 | elif mode_a == "2": 43 | values.append(input[input[pos+3]+painter.rel_base]) 44 | 45 | if op in ["01", "02", "07", "08"]: 46 | if mode_a == "2": 47 | offset = painter.rel_base 48 | 49 | if op in ["03"]: 50 | if mode_c == "2": 51 | offset = painter.rel_base 52 | 53 | return values, offset 54 | 55 | def run_booster(input, painter): 56 | while painter.prog[painter.ip] != 99: 57 | op, modes = split_instruction(painter.prog[painter.ip]) 58 | values, offset = get_values(painter.prog, painter.ip, op, modes, painter) 59 | 60 | if op == "01": # Addition 61 | painter.prog[painter.prog[painter.ip+3] + offset] = values[0] + values[1] 62 | painter.ip += 4 63 | 64 | if op == "02": # Multiplication 65 | painter.prog[painter.prog[painter.ip+3] + offset] = values[0] * values[1] 66 | painter.ip += 4 67 | 68 | if op == "03": # Read and Store input 69 | painter.prog[painter.prog[painter.ip+1] + offset] = input 70 | painter.ip += 2 71 | 72 | if op == "04": # Print Output 73 | painter.output = values[0] 74 | #print(painter.output) 75 | painter.ip += 2 76 | return painter 77 | 78 | if op == "05": # Jump-if-True 79 | if values[0]: 80 | painter.ip = values[1] 81 | else: 82 | painter.ip += 3 83 | 84 | if op == "06": # Jump-if-False 85 | if not values[0]: 86 | painter.ip = values[1] 87 | else: 88 | painter.ip += 3 89 | 90 | if op == "07": # Less than 91 | if values[0] < values[1]: 92 | painter.prog[painter.prog[painter.ip+3] + offset] = 1 93 | else: 94 | painter.prog[painter.prog[painter.ip+3] + offset] = 0 95 | painter.ip += 4 96 | 97 | if op == "08": # Equals 98 | if values[0] == values[1]: 99 | painter.prog[painter.prog[painter.ip+3] + offset] = 1 100 | else: 101 | painter.prog[painter.prog[painter.ip+3] + offset] = 0 102 | painter.ip += 4 103 | 104 | if op == "09": # Adjust Relative Base 105 | painter.rel_base += values[0] 106 | painter.ip += 2 107 | 108 | painter.halt = True 109 | return painter 110 | 111 | def create_program(input): 112 | prog = defaultdict(int) 113 | 114 | for i in range(len(input)): 115 | prog[i] = int(input[i]) 116 | 117 | return prog 118 | 119 | def turn_and_move(pos, dir, turn): 120 | if turn == 0: 121 | dir = (dir - 1) % 4 122 | else: 123 | dir = (dir + 1) % 4 124 | 125 | if dir == 0: # up 126 | pos = (pos[0], pos[1] + 1) 127 | elif dir == 1: # right 128 | pos = (pos[0]+1, pos[1]) 129 | elif dir == 2: # down 130 | pos = (pos[0], pos[1] - 1) 131 | elif dir == 3: # left 132 | pos = (pos[0] - 1, pos[1]) 133 | 134 | return pos, dir 135 | 136 | @timer 137 | def solve(): 138 | input = read_file("11")[0].split(",") 139 | prog = create_program(input) 140 | 141 | panel = defaultdict(int) 142 | painted = defaultdict(int) 143 | painter = Painter(prog) 144 | 145 | dir = 0 146 | pos = (0, 0) 147 | 148 | while not painter.halt: 149 | painter = run_booster(panel[pos], painter) 150 | color = painter.output 151 | painter = run_booster(panel[pos], painter) 152 | turn = painter.output 153 | 154 | painted[pos] = 1 155 | panel[pos] = color 156 | 157 | pos, dir = turn_and_move(pos, dir, turn) 158 | 159 | return len(painted) 160 | 161 | result = solve() 162 | print(f"Solution: {result}") -------------------------------------------------------------------------------- /2019_11_p2.py: -------------------------------------------------------------------------------- 1 | from aoc import read_file, timer 2 | from collections import defaultdict 3 | 4 | class Painter: 5 | def __init__(self, prog): 6 | self.prog = prog 7 | self.ip = 0 8 | self.output = 0 9 | self.rel_base = 0 10 | self.halt = False 11 | 12 | def split_instruction(instruction): 13 | instruction = f"{instruction:05}" 14 | return instruction[3:], instruction[0:3] 15 | 16 | def get_values(input, pos, op, modes, painter): 17 | mode_a, mode_b, mode_c = modes 18 | values = [] 19 | offset = 0 20 | 21 | if op in ["01", "02", "04", "05", "06", "07", "08", "09"]: 22 | if mode_c == "0": 23 | values.append(input[input[pos+1]]) 24 | elif mode_c == "1": 25 | values.append(input[pos+1]) 26 | elif mode_c == "2": 27 | values.append(input[input[pos+1]+painter.rel_base]) 28 | 29 | if op in ["01", "02", "05", "06", "07", "08"]: 30 | if mode_b == "0": 31 | values.append(input[input[pos+2]]) 32 | elif mode_b == "1": 33 | values.append(input[pos+2]) 34 | elif mode_b == "2": 35 | values.append(input[input[pos+2]+painter.rel_base]) 36 | 37 | if op in []: 38 | if mode_a == "0": 39 | values.append(input[input[pos+3]]) 40 | elif mode_a == "1": 41 | values.append(input[pos+3]) 42 | elif mode_a == "2": 43 | values.append(input[input[pos+3]+painter.rel_base]) 44 | 45 | if op in ["01", "02", "07", "08"]: 46 | if mode_a == "2": 47 | offset = painter.rel_base 48 | 49 | if op in ["03"]: 50 | if mode_c == "2": 51 | offset = painter.rel_base 52 | 53 | return values, offset 54 | 55 | def run_booster(input, painter): 56 | while painter.prog[painter.ip] != 99: 57 | op, modes = split_instruction(painter.prog[painter.ip]) 58 | values, offset = get_values(painter.prog, painter.ip, op, modes, painter) 59 | 60 | if op == "01": # Addition 61 | painter.prog[painter.prog[painter.ip+3] + offset] = values[0] + values[1] 62 | painter.ip += 4 63 | 64 | if op == "02": # Multiplication 65 | painter.prog[painter.prog[painter.ip+3] + offset] = values[0] * values[1] 66 | painter.ip += 4 67 | 68 | if op == "03": # Read and Store input 69 | painter.prog[painter.prog[painter.ip+1] + offset] = input 70 | painter.ip += 2 71 | 72 | if op == "04": # Print Output 73 | painter.output = values[0] 74 | #print(painter.output) 75 | painter.ip += 2 76 | return painter 77 | 78 | if op == "05": # Jump-if-True 79 | if values[0]: 80 | painter.ip = values[1] 81 | else: 82 | painter.ip += 3 83 | 84 | if op == "06": # Jump-if-False 85 | if not values[0]: 86 | painter.ip = values[1] 87 | else: 88 | painter.ip += 3 89 | 90 | if op == "07": # Less than 91 | if values[0] < values[1]: 92 | painter.prog[painter.prog[painter.ip+3] + offset] = 1 93 | else: 94 | painter.prog[painter.prog[painter.ip+3] + offset] = 0 95 | painter.ip += 4 96 | 97 | if op == "08": # Equals 98 | if values[0] == values[1]: 99 | painter.prog[painter.prog[painter.ip+3] + offset] = 1 100 | else: 101 | painter.prog[painter.prog[painter.ip+3] + offset] = 0 102 | painter.ip += 4 103 | 104 | if op == "09": # Adjust Relative Base 105 | painter.rel_base += values[0] 106 | painter.ip += 2 107 | 108 | painter.halt = True 109 | return painter 110 | 111 | def create_program(input): 112 | prog = defaultdict(int) 113 | 114 | for i in range(len(input)): 115 | prog[i] = int(input[i]) 116 | 117 | return prog 118 | 119 | def turn_and_move(pos, dir, turn): 120 | if turn == 0: 121 | dir = (dir - 1) % 4 122 | else: 123 | dir = (dir + 1) % 4 124 | 125 | if dir == 0: # up 126 | pos = (pos[0], pos[1] + 1) 127 | elif dir == 1: # right 128 | pos = (pos[0]+1, pos[1]) 129 | elif dir == 2: # down 130 | pos = (pos[0], pos[1] - 1) 131 | elif dir == 3: # left 132 | pos = (pos[0] - 1, pos[1]) 133 | 134 | return pos, dir 135 | 136 | def draw_panel(panel): 137 | top, right, bottom, left = -1e8, -1e8, 1e8, 1e8 138 | for position, value in panel.items(): 139 | if value: 140 | top = max(top, position[1]) 141 | right = max(right, position[0]) 142 | bottom = min(bottom, position[1]) 143 | left = min(left, position[0]) 144 | 145 | for y in range(top, bottom-1, -1): 146 | for x in range(left, right+1): 147 | if panel[(x, y)] == 1: 148 | print("#", end="") 149 | if panel[(x, y)] == 0: 150 | print(" ", end="") 151 | print() 152 | 153 | @timer 154 | def solve(): 155 | input = read_file("11")[0].split(",") 156 | prog = create_program(input) 157 | 158 | panel = defaultdict(int) 159 | painter = Painter(prog) 160 | 161 | dir = 0 162 | pos = (0, 0) 163 | panel[(0, 0)] = 1 164 | 165 | while not painter.halt: 166 | painter = run_booster(panel[pos], painter) 167 | color = painter.output 168 | painter = run_booster(panel[pos], painter) 169 | turn = painter.output 170 | 171 | panel[pos] = color 172 | 173 | pos, dir = turn_and_move(pos, dir, turn) 174 | 175 | draw_panel(panel) 176 | 177 | solve() -------------------------------------------------------------------------------- /2019_12_p1.py: -------------------------------------------------------------------------------- 1 | from aoc import read_file, timer 2 | from re import findall 3 | 4 | def extract_ints(line): 5 | return [int(x) for x in findall(r'-?\d+', line)] 6 | 7 | def apply_gravity(moons, velocities): 8 | for m_1 in range(3): 9 | for m_2 in range(m_1+1, 4): 10 | for dim in range(3): 11 | if moons[m_1][dim] > moons[m_2][dim]: 12 | velocities[m_1][dim] -= 1 13 | velocities[m_2][dim] += 1 14 | elif moons[m_1][dim] < moons[m_2][dim]: 15 | velocities[m_1][dim] += 1 16 | velocities[m_2][dim] -= 1 17 | 18 | def apply_velocity(moons, velocities): 19 | for m in range(4): 20 | for dim in range(3): 21 | moons[m][dim] += velocities[m][dim] 22 | 23 | def calculate_energy(moons, velocities): 24 | e = 0 25 | for i in range(4): 26 | pot = sum([abs(moon) for moon in moons[i]]) 27 | kin = sum([abs(velocity) for velocity in velocities[i]]) 28 | e += pot * kin 29 | return e 30 | 31 | @timer 32 | def solve(): 33 | input = read_file("12") 34 | 35 | moons = [extract_ints(line) for line in input] 36 | velocities = [[0 for x in range(3)] for y in range(4)] 37 | 38 | for _ in range(1000): 39 | apply_gravity(moons, velocities) 40 | apply_velocity(moons, velocities) 41 | 42 | return calculate_energy(moons, velocities) 43 | 44 | result = solve() 45 | print(f"Solution: {result}") -------------------------------------------------------------------------------- /2019_12_p2.py: -------------------------------------------------------------------------------- 1 | from aoc import read_file, timer 2 | from re import findall 3 | 4 | def extract_ints(line): 5 | return [int(x) for x in findall(r'-?\d+', line)] 6 | 7 | def get_prime_factors(n): 8 | i = 2 9 | factors = [] 10 | while i * i <= n: 11 | if n % i: 12 | i += 1 13 | else: 14 | n //= i 15 | factors.append(i) 16 | if n > 1: 17 | factors.append(n) 18 | return factors 19 | 20 | def calculate_lcm(steps): 21 | primes_per_dimension = [get_prime_factors(step) for step in steps] 22 | all_primes = set([prime for primes in primes_per_dimension for prime in primes]) 23 | 24 | lcm = 1 25 | for prime in all_primes: 26 | amount = max(primes_per_dimension[dim].count(prime) for dim in range(3)) 27 | lcm *= prime**amount 28 | return lcm 29 | 30 | def apply_gravity(moons_dim, velocities_dim): 31 | for m_1 in range(3): 32 | for m_2 in range(m_1+1, 4): 33 | if moons_dim[m_1] > moons_dim[m_2]: 34 | velocities_dim[m_1] -= 1 35 | velocities_dim[m_2] += 1 36 | elif moons_dim[m_1] < moons_dim[m_2]: 37 | velocities_dim[m_1] += 1 38 | velocities_dim[m_2] -= 1 39 | 40 | def apply_velocity(moons_dim, velocities_dim): 41 | for m in range(4): 42 | moons_dim[m] += velocities_dim[m] 43 | 44 | def matches_start_state(moons, velocities, moons_dim, velocities_dim, dim): 45 | for i in range(4): 46 | if moons[i][dim] != moons_dim[i] or \ 47 | velocities[i][dim] != velocities_dim[i]: 48 | return False 49 | return True 50 | 51 | @timer 52 | def solve(): 53 | input = read_file("12") 54 | 55 | moons = [extract_ints(line) for line in input] 56 | velocities = [[0 for x in range(3)] for y in range(4)] 57 | 58 | steps = [0, 0, 0] 59 | 60 | for dim in range(3): 61 | moons_dim = [moon[dim] for moon in moons] 62 | velocities_dim = [velocity[dim] for velocity in velocities] 63 | 64 | while True: 65 | apply_gravity(moons_dim, velocities_dim) 66 | apply_velocity(moons_dim, velocities_dim) 67 | 68 | steps[dim] += 1 69 | 70 | if matches_start_state(moons, velocities, moons_dim, velocities_dim, dim): 71 | break 72 | 73 | return calculate_lcm(steps) 74 | 75 | result = solve() 76 | print(f"Solution: {result}") -------------------------------------------------------------------------------- /2019_13_p1.py: -------------------------------------------------------------------------------- 1 | from aoc import read_file, timer 2 | from collections import defaultdict 3 | 4 | class Game: 5 | def __init__(self, prog): 6 | self.prog = prog 7 | self.ip = 0 8 | self.output = 0 9 | self.rel_base = 0 10 | self.halt = False 11 | 12 | def split_instruction(instruction): 13 | instruction = f"{instruction:05}" 14 | return instruction[3:], instruction[0:3] 15 | 16 | def get_values(input, pos, op, modes, game): 17 | mode_a, mode_b, mode_c = modes 18 | values = [] 19 | offset = 0 20 | 21 | if op in ["01", "02", "04", "05", "06", "07", "08", "09"]: 22 | if mode_c == "0": 23 | values.append(input[input[pos+1]]) 24 | elif mode_c == "1": 25 | values.append(input[pos+1]) 26 | elif mode_c == "2": 27 | values.append(input[input[pos+1]+game.rel_base]) 28 | 29 | if op in ["01", "02", "05", "06", "07", "08"]: 30 | if mode_b == "0": 31 | values.append(input[input[pos+2]]) 32 | elif mode_b == "1": 33 | values.append(input[pos+2]) 34 | elif mode_b == "2": 35 | values.append(input[input[pos+2]+game.rel_base]) 36 | 37 | if op in []: 38 | if mode_a == "0": 39 | values.append(input[input[pos+3]]) 40 | elif mode_a == "1": 41 | values.append(input[pos+3]) 42 | elif mode_a == "2": 43 | values.append(input[input[pos+3]+game.rel_base]) 44 | 45 | if op in ["01", "02", "07", "08"]: 46 | if mode_a == "2": 47 | offset = game.rel_base 48 | 49 | if op in ["03"]: 50 | if mode_c == "2": 51 | offset = game.rel_base 52 | 53 | return values, offset 54 | 55 | def run_game(game, input = 0): 56 | while game.prog[game.ip] != 99: 57 | op, modes = split_instruction(game.prog[game.ip]) 58 | values, offset = get_values(game.prog, game.ip, op, modes, game) 59 | 60 | if op == "01": # Addition 61 | game.prog[game.prog[game.ip+3] + offset] = values[0] + values[1] 62 | game.ip += 4 63 | 64 | if op == "02": # Multiplication 65 | game.prog[game.prog[game.ip+3] + offset] = values[0] * values[1] 66 | game.ip += 4 67 | 68 | if op == "03": # Read and Store input 69 | game.prog[game.prog[game.ip+1] + offset] = input 70 | game.ip += 2 71 | 72 | if op == "04": # Print Output 73 | game.output = values[0] 74 | game.ip += 2 75 | return game 76 | 77 | if op == "05": # Jump-if-True 78 | if values[0]: 79 | game.ip = values[1] 80 | else: 81 | game.ip += 3 82 | 83 | if op == "06": # Jump-if-False 84 | if not values[0]: 85 | game.ip = values[1] 86 | else: 87 | game.ip += 3 88 | 89 | if op == "07": # Less than 90 | if values[0] < values[1]: 91 | game.prog[game.prog[game.ip+3] + offset] = 1 92 | else: 93 | game.prog[game.prog[game.ip+3] + offset] = 0 94 | game.ip += 4 95 | 96 | if op == "08": # Equals 97 | if values[0] == values[1]: 98 | game.prog[game.prog[game.ip+3] + offset] = 1 99 | else: 100 | game.prog[game.prog[game.ip+3] + offset] = 0 101 | game.ip += 4 102 | 103 | if op == "09": # Adjust Relative Base 104 | game.rel_base += values[0] 105 | game.ip += 2 106 | 107 | game.halt = True 108 | return game 109 | 110 | def create_program(input): 111 | prog = defaultdict(int) 112 | 113 | for i in range(len(input)): 114 | prog[i] = int(input[i]) 115 | 116 | return prog 117 | 118 | @timer 119 | def solve(): 120 | input = read_file("13")[0].split(",") 121 | prog = create_program(input) 122 | game = Game(prog) 123 | result = 0 124 | 125 | while not game.halt: 126 | for i in range(3): 127 | run_game(game) 128 | if game.output == 2: 129 | result += 1 130 | 131 | return result 132 | 133 | result = solve() 134 | print(f"Solution: {result}") -------------------------------------------------------------------------------- /2019_13_p2.py: -------------------------------------------------------------------------------- 1 | from aoc import read_file, timer 2 | from collections import defaultdict 3 | 4 | class Game: 5 | def __init__(self, prog): 6 | self.prog = prog 7 | self.ip = 0 8 | self.output = 0 9 | self.rel_base = 0 10 | self.halt = False 11 | 12 | def split_instruction(instruction): 13 | instruction = f"{instruction:05}" 14 | return instruction[3:], instruction[0:3] 15 | 16 | def get_values(input, pos, op, modes, game): 17 | mode_a, mode_b, mode_c = modes 18 | values = [] 19 | offset = 0 20 | 21 | if op in ["01", "02", "04", "05", "06", "07", "08", "09"]: 22 | if mode_c == "0": 23 | values.append(input[input[pos+1]]) 24 | elif mode_c == "1": 25 | values.append(input[pos+1]) 26 | elif mode_c == "2": 27 | values.append(input[input[pos+1]+game.rel_base]) 28 | 29 | if op in ["01", "02", "05", "06", "07", "08"]: 30 | if mode_b == "0": 31 | values.append(input[input[pos+2]]) 32 | elif mode_b == "1": 33 | values.append(input[pos+2]) 34 | elif mode_b == "2": 35 | values.append(input[input[pos+2]+game.rel_base]) 36 | 37 | if op in []: 38 | if mode_a == "0": 39 | values.append(input[input[pos+3]]) 40 | elif mode_a == "1": 41 | values.append(input[pos+3]) 42 | elif mode_a == "2": 43 | values.append(input[input[pos+3]+game.rel_base]) 44 | 45 | if op in ["01", "02", "07", "08"]: 46 | if mode_a == "2": 47 | offset = game.rel_base 48 | 49 | if op in ["03"]: 50 | if mode_c == "2": 51 | offset = game.rel_base 52 | 53 | return values, offset 54 | 55 | def run_game(game, input = 0): 56 | while game.prog[game.ip] != 99: 57 | op, modes = split_instruction(game.prog[game.ip]) 58 | values, offset = get_values(game.prog, game.ip, op, modes, game) 59 | 60 | if op == "01": # Addition 61 | game.prog[game.prog[game.ip+3] + offset] = values[0] + values[1] 62 | game.ip += 4 63 | 64 | if op == "02": # Multiplication 65 | game.prog[game.prog[game.ip+3] + offset] = values[0] * values[1] 66 | game.ip += 4 67 | 68 | if op == "03": # Read and Store input 69 | game.prog[game.prog[game.ip+1] + offset] = input 70 | game.ip += 2 71 | 72 | if op == "04": # Print Output 73 | game.output = values[0] 74 | game.ip += 2 75 | return game 76 | 77 | if op == "05": # Jump-if-True 78 | if values[0]: 79 | game.ip = values[1] 80 | else: 81 | game.ip += 3 82 | 83 | if op == "06": # Jump-if-False 84 | if not values[0]: 85 | game.ip = values[1] 86 | else: 87 | game.ip += 3 88 | 89 | if op == "07": # Less than 90 | if values[0] < values[1]: 91 | game.prog[game.prog[game.ip+3] + offset] = 1 92 | else: 93 | game.prog[game.prog[game.ip+3] + offset] = 0 94 | game.ip += 4 95 | 96 | if op == "08": # Equals 97 | if values[0] == values[1]: 98 | game.prog[game.prog[game.ip+3] + offset] = 1 99 | else: 100 | game.prog[game.prog[game.ip+3] + offset] = 0 101 | game.ip += 4 102 | 103 | if op == "09": # Adjust Relative Base 104 | game.rel_base += values[0] 105 | game.ip += 2 106 | 107 | game.halt = True 108 | return game 109 | 110 | def create_program(input): 111 | prog = defaultdict(int) 112 | 113 | for i in range(len(input)): 114 | prog[i] = int(input[i]) 115 | 116 | return prog 117 | 118 | def get_joy(ball, paddle): 119 | if ball > paddle: 120 | return 1 121 | elif ball == paddle: 122 | return 0 123 | else: 124 | return -1 125 | 126 | @timer 127 | def solve(): 128 | input = read_file("13")[0].split(",") 129 | prog = create_program(input) 130 | prog[0] = 2 131 | 132 | game = Game(prog) 133 | ball, paddle = 0, 0 134 | coord = defaultdict(int) 135 | 136 | while not game.halt: 137 | for output in ["x", "y", "tile"]: 138 | run_game(game, get_joy(ball, paddle)) 139 | coord[output] = game.output 140 | if coord["tile"] == 3: 141 | paddle = coord["x"] 142 | elif coord["tile"] == 4: 143 | ball = coord["x"] 144 | if coord["x"] == -1: 145 | score = coord["tile"] 146 | 147 | return score 148 | 149 | result = solve() 150 | print(f"Solution: {result}") -------------------------------------------------------------------------------- /2019_14_p1.py: -------------------------------------------------------------------------------- 1 | from aoc import read_file, timer 2 | from collections import defaultdict 3 | 4 | def produce(comp, amount, requirements, rest = None): 5 | if rest == None: 6 | rest = defaultdict(int) 7 | 8 | for prod, sources in requirements.items(): 9 | if prod[1] == comp: 10 | break 11 | 12 | made = rest[prod[1]] 13 | 14 | if not (amount - made) % prod[0]: 15 | rest[prod[1]] = 0 16 | a = (amount - made) // prod[0] 17 | else: 18 | rest[prod[1]] = prod[0] - ((amount - made) % prod[0]) 19 | a = (amount - made) // prod[0] + 1 20 | 21 | ore = 0 22 | 23 | for source in sources: 24 | if source[1] == "ORE": 25 | ore += source[0]*a 26 | else: 27 | cost = produce(source[1], source[0]*a, requirements, rest) 28 | ore += cost 29 | 30 | return ore 31 | 32 | @timer 33 | def solve(): 34 | input = read_file("14") 35 | requirements = defaultdict(list) 36 | 37 | for line in input: 38 | parts = line.replace(",", "").split(" ") 39 | for i in range((len(parts) - 3) // 2): 40 | requirements[(int(parts[-2]), parts[-1])].append((int(parts[i*2]), parts[i*2+1])) 41 | 42 | return produce("FUEL", 1, requirements) 43 | 44 | result = solve() 45 | print(f"Solution: {result}") -------------------------------------------------------------------------------- /2019_14_p2.py: -------------------------------------------------------------------------------- 1 | from aoc import read_file, timer 2 | from collections import defaultdict 3 | 4 | def produce(comp, amount, requirements, rest = None): 5 | if rest == None: 6 | rest = defaultdict(int) 7 | 8 | for prod, sources in requirements.items(): 9 | if prod[1] == comp: 10 | break 11 | 12 | made = rest[prod[1]] 13 | 14 | if not (amount - made) % prod[0]: 15 | rest[prod[1]] = 0 16 | a = (amount - made) // prod[0] 17 | else: 18 | rest[prod[1]] = prod[0] - ((amount - made) % prod[0]) 19 | a = (amount - made) // prod[0] + 1 20 | 21 | ore = 0 22 | 23 | for source in sources: 24 | if source[1] == "ORE": 25 | ore += source[0]*a 26 | else: 27 | cost = produce(source[1], source[0]*a, requirements, rest) 28 | ore += cost 29 | 30 | return ore 31 | 32 | @timer 33 | def solve(): 34 | input = read_file("14") 35 | 36 | req = defaultdict(list) 37 | 38 | for line in input: 39 | line = list(line) 40 | while "," in line: 41 | line.remove(",") 42 | line = "".join(line) 43 | 44 | x = line.split(" ") 45 | comps = (len(x) - 3) // 2 46 | for i in range(comps): 47 | req[(int(x[-2]), x[-1])].append((int(x[i*2]), x[i*2+1])) 48 | 49 | available = 1000000000000 50 | 51 | low = available // produce("FUEL", 1, req) 52 | high = 2 * low 53 | 54 | while high - low > 1: 55 | middle = (high + low) // 2 56 | cost = produce("FUEL", middle, req) 57 | if cost <= available: 58 | low = middle 59 | else: 60 | high = middle 61 | 62 | return low 63 | 64 | 65 | result = solve() 66 | print(f"Solution: {result}") -------------------------------------------------------------------------------- /2019_16_p1.py: -------------------------------------------------------------------------------- 1 | from aoc import read_file, timer 2 | from collections import deque 3 | 4 | @timer 5 | def solve(): 6 | input = read_file("16")[0] 7 | elements = [int(num) for num in input] 8 | 9 | for phase in range(100): 10 | for pos in range(len(elements)): 11 | pattern = deque([p for p in [0, 1, 0, -1] for _ in range(pos+1)]) 12 | pattern.rotate(-1) 13 | 14 | res = 0 15 | for i in range(len(elements)): 16 | res += elements[i] * pattern[0] 17 | pattern.rotate(-1) 18 | elements[pos] = abs(res) % 10 19 | 20 | return "".join(str(x) for x in elements[:8]) 21 | 22 | result = solve() 23 | print(f"Solution: {result}") 24 | 25 | -------------------------------------------------------------------------------- /2019_16_p2.py: -------------------------------------------------------------------------------- 1 | from aoc import read_file, timer 2 | 3 | @timer 4 | def solve(): 5 | input = read_file("16")[0] 6 | offset = int(input[:7]) 7 | elements = [int(num) for _ in range(10000) for num in input][offset:] 8 | 9 | for _ in range(100): 10 | for i in range(-2, -len(elements)-1, -1): 11 | elements[i] = (elements[i] + elements[i+1]) % 10 12 | 13 | return "".join([str(x) for x in elements[:8]]) 14 | 15 | result = solve() 16 | print(f"Solution: {result}") -------------------------------------------------------------------------------- /2019_17_p1.py: -------------------------------------------------------------------------------- 1 | from aoc import read_file, timer 2 | from collections import defaultdict 3 | 4 | class Game: 5 | def __init__(self, prog): 6 | self.prog = prog 7 | self.ip = 0 8 | self.output = 0 9 | self.rel_base = 0 10 | self.halt = False 11 | 12 | def split_instruction(instruction): 13 | instruction = f"{instruction:05}" 14 | return instruction[3:], instruction[0:3] 15 | 16 | def get_values(input, pos, op, modes, game): 17 | mode_a, mode_b, mode_c = modes 18 | values = [] 19 | offset = 0 20 | 21 | if op in ["01", "02", "04", "05", "06", "07", "08", "09"]: 22 | if mode_c == "0": 23 | values.append(input[input[pos+1]]) 24 | elif mode_c == "1": 25 | values.append(input[pos+1]) 26 | elif mode_c == "2": 27 | values.append(input[input[pos+1]+game.rel_base]) 28 | 29 | if op in ["01", "02", "05", "06", "07", "08"]: 30 | if mode_b == "0": 31 | values.append(input[input[pos+2]]) 32 | elif mode_b == "1": 33 | values.append(input[pos+2]) 34 | elif mode_b == "2": 35 | values.append(input[input[pos+2]+game.rel_base]) 36 | 37 | if op in []: 38 | if mode_a == "0": 39 | values.append(input[input[pos+3]]) 40 | elif mode_a == "1": 41 | values.append(input[pos+3]) 42 | elif mode_a == "2": 43 | values.append(input[input[pos+3]+game.rel_base]) 44 | 45 | if op in ["01", "02", "07", "08"]: 46 | if mode_a == "2": 47 | offset = game.rel_base 48 | 49 | if op in ["03"]: 50 | if mode_c == "2": 51 | offset = game.rel_base 52 | 53 | return values, offset 54 | 55 | def run_game(game, input = 0): 56 | while game.prog[game.ip] != 99: 57 | op, modes = split_instruction(game.prog[game.ip]) 58 | values, offset = get_values(game.prog, game.ip, op, modes, game) 59 | 60 | if op == "01": # Addition 61 | game.prog[game.prog[game.ip+3] + offset] = values[0] + values[1] 62 | game.ip += 4 63 | 64 | if op == "02": # Multiplication 65 | game.prog[game.prog[game.ip+3] + offset] = values[0] * values[1] 66 | game.ip += 4 67 | 68 | if op == "03": # Read and Store input 69 | game.prog[game.prog[game.ip+1] + offset] = input 70 | game.ip += 2 71 | 72 | if op == "04": # Print Output 73 | game.output = values[0] 74 | game.ip += 2 75 | return game 76 | 77 | if op == "05": # Jump-if-True 78 | if values[0]: 79 | game.ip = values[1] 80 | else: 81 | game.ip += 3 82 | 83 | if op == "06": # Jump-if-False 84 | if not values[0]: 85 | game.ip = values[1] 86 | else: 87 | game.ip += 3 88 | 89 | if op == "07": # Less than 90 | if values[0] < values[1]: 91 | game.prog[game.prog[game.ip+3] + offset] = 1 92 | else: 93 | game.prog[game.prog[game.ip+3] + offset] = 0 94 | game.ip += 4 95 | 96 | if op == "08": # Equals 97 | if values[0] == values[1]: 98 | game.prog[game.prog[game.ip+3] + offset] = 1 99 | else: 100 | game.prog[game.prog[game.ip+3] + offset] = 0 101 | game.ip += 4 102 | 103 | if op == "09": # Adjust Relative Base 104 | game.rel_base += values[0] 105 | game.ip += 2 106 | 107 | game.halt = True 108 | return game 109 | 110 | def create_program(input): 111 | prog = defaultdict(int) 112 | 113 | for i in range(len(input)): 114 | prog[i] = int(input[i]) 115 | 116 | return prog 117 | 118 | def get_size(field): 119 | len_y, len_x = 0, 0 120 | for position in field.keys(): 121 | len_x = max(len_x, position[0]) 122 | len_y = max(len_y, position[1]) 123 | 124 | return len_x, len_y 125 | 126 | def solve(): 127 | input = read_file("17")[0].split(",") 128 | prog = create_program(input) 129 | game = Game(prog) 130 | 131 | field = defaultdict(str) 132 | x, y = 0, 0 133 | 134 | while not game.halt: 135 | run_game(game) 136 | if game.output == 10: 137 | y += 1 138 | x = 0 139 | else: 140 | field[(x, y)] = chr(game.output) 141 | x += 1 142 | print(chr(game.output), end = "") 143 | 144 | len_x, len_y = get_size(field) 145 | result = 0 146 | 147 | for y in range(1, len_y): 148 | for x in range(1, len_x): 149 | if field[(x-1, y)] == "#" and \ 150 | field[(x, y-1)] == "#" and \ 151 | field[(x+1, y)] == "#" and \ 152 | field[(x, y+1)] == "#": 153 | result += x * y 154 | 155 | return result 156 | 157 | result = solve() 158 | print(f"Solution: {result}") -------------------------------------------------------------------------------- /2019_17_p2.py: -------------------------------------------------------------------------------- 1 | from aoc import read_file, timer 2 | from collections import defaultdict, deque 3 | 4 | class Game: 5 | def __init__(self, prog): 6 | self.prog = prog 7 | self.ip = 0 8 | self.input = deque() 9 | self.output = deque() 10 | self.rel_base = 0 11 | self.halt = False 12 | 13 | def split_instruction(instruction): 14 | instruction = f"{instruction:05}" 15 | return instruction[3:], instruction[0:3] 16 | 17 | def get_values(input, pos, op, modes, game): 18 | mode_a, mode_b, mode_c = modes 19 | values = [] 20 | offset = 0 21 | 22 | if op in ["01", "02", "04", "05", "06", "07", "08", "09"]: 23 | if mode_c == "0": 24 | values.append(input[input[pos+1]]) 25 | elif mode_c == "1": 26 | values.append(input[pos+1]) 27 | elif mode_c == "2": 28 | values.append(input[input[pos+1]+game.rel_base]) 29 | 30 | if op in ["01", "02", "05", "06", "07", "08"]: 31 | if mode_b == "0": 32 | values.append(input[input[pos+2]]) 33 | elif mode_b == "1": 34 | values.append(input[pos+2]) 35 | elif mode_b == "2": 36 | values.append(input[input[pos+2]+game.rel_base]) 37 | 38 | if op in []: 39 | if mode_a == "0": 40 | values.append(input[input[pos+3]]) 41 | elif mode_a == "1": 42 | values.append(input[pos+3]) 43 | elif mode_a == "2": 44 | values.append(input[input[pos+3]+game.rel_base]) 45 | 46 | if op in ["01", "02", "07", "08"]: 47 | if mode_a == "2": 48 | offset = game.rel_base 49 | 50 | if op in ["03"]: 51 | if mode_c == "2": 52 | offset = game.rel_base 53 | 54 | return values, offset 55 | 56 | def read_output(game): 57 | if len(game.output): 58 | return game.output.popleft() 59 | return None 60 | 61 | def run_game(game, input = []): 62 | if len(input): 63 | game.input.extend(input) 64 | 65 | while game.prog[game.ip] != 99: 66 | op, modes = split_instruction(game.prog[game.ip]) 67 | values, offset = get_values(game.prog, game.ip, op, modes, game) 68 | 69 | if op == "01": # Addition 70 | game.prog[game.prog[game.ip+3] + offset] = values[0] + values[1] 71 | game.ip += 4 72 | 73 | if op == "02": # Multiplication 74 | game.prog[game.prog[game.ip+3] + offset] = values[0] * values[1] 75 | game.ip += 4 76 | 77 | if op == "03": # Read and Store input 78 | game.prog[game.prog[game.ip+1] + offset] = game.input.popleft() 79 | game.ip += 2 80 | 81 | if op == "04": # Print Output 82 | game.output.append(values[0]) 83 | game.ip += 2 84 | return game 85 | 86 | if op == "05": # Jump-if-True 87 | if values[0]: 88 | game.ip = values[1] 89 | else: 90 | game.ip += 3 91 | 92 | if op == "06": # Jump-if-False 93 | if not values[0]: 94 | game.ip = values[1] 95 | else: 96 | game.ip += 3 97 | 98 | if op == "07": # Less than 99 | if values[0] < values[1]: 100 | game.prog[game.prog[game.ip+3] + offset] = 1 101 | else: 102 | game.prog[game.prog[game.ip+3] + offset] = 0 103 | game.ip += 4 104 | 105 | if op == "08": # Equals 106 | if values[0] == values[1]: 107 | game.prog[game.prog[game.ip+3] + offset] = 1 108 | else: 109 | game.prog[game.prog[game.ip+3] + offset] = 0 110 | game.ip += 4 111 | 112 | if op == "09": # Adjust Relative Base 113 | game.rel_base += values[0] 114 | game.ip += 2 115 | 116 | game.halt = True 117 | 118 | def create_program(input): 119 | prog = defaultdict(int) 120 | 121 | for i in range(len(input)): 122 | prog[i] = int(input[i]) 123 | 124 | return prog 125 | 126 | def print_message(game): 127 | while not len(game.output) or game.output[-1] != 10: 128 | run_game(game) 129 | while (output := read_output(game)): 130 | print(chr(output), end = "") 131 | 132 | def print_camera(game): 133 | while len(game.output) < 2 or game.output[-2] != 10 or game.output[-1] != 10: 134 | run_game(game) 135 | 136 | while (output := read_output(game)): 137 | print(chr(output), end = "") 138 | 139 | @timer 140 | def solve(): 141 | input = read_file("17")[0].split(",") 142 | input[0] = 2 143 | prog = create_program(input) 144 | game = Game(prog) 145 | 146 | print_camera(game) 147 | 148 | # Solution derived on paper. 149 | # Automated solution will follow, when I find the time. 150 | 151 | instructions = [] 152 | instructions.append([ord(c) for c in "A,B,A,C,A,B,C,B,C,A\n"]) 153 | instructions.append([ord(c) for c in "L,12,R,4,R,4,L,6\n"]) 154 | instructions.append([ord(c) for c in "L,12,R,4,R,4,R,12\n"]) 155 | instructions.append([ord(c) for c in "L,10,L,6,R,4\n"]) 156 | instructions.append([ord(c) for c in "n\n"]) 157 | 158 | print_message(game) 159 | 160 | for inst in instructions: 161 | run_game(game, inst) 162 | print_message(game) 163 | 164 | print_camera(game) 165 | run_game(game) 166 | 167 | return read_output(game) 168 | 169 | result = solve() 170 | print(f"Solution: {result}") 171 | 172 | -------------------------------------------------------------------------------- /2019_18_p1.py: -------------------------------------------------------------------------------- 1 | from aoc import read_file, timer 2 | from collections import defaultdict 3 | from copy import copy 4 | 5 | class Key: 6 | def __init__(self, dungeon, position, type): 7 | self.position = position 8 | self.type = type 9 | self.distance_to_keys = self.get_key_distances(dungeon) 10 | self.blocked_by_doors = self.get_blocking_doors(dungeon) 11 | 12 | def get_key_distances(self, dungeon): 13 | next_search = defaultdict(int) 14 | next_search[self.position] = 1 15 | keys = {} 16 | changes = True 17 | steps = 0 18 | 19 | while changes or not steps: 20 | changes = False 21 | steps += 1 22 | search = copy(next_search) 23 | 24 | for position, state in search.items(): 25 | if state == -1: 26 | del next_search[position] 27 | if state == 1: 28 | next_search[position] = -1 29 | for side in [(-1,0), (0,-1), (1,0), (0,1)]: 30 | side_pos = (position[0] + side[0], position[1] + side[1]) 31 | if dungeon.area[side_pos] != "#" and \ 32 | not search[side_pos]: 33 | del search[side_pos] 34 | changes = True 35 | next_search[side_pos] = 1 36 | if dungeon.area[side_pos].islower(): 37 | keys[dungeon.area[side_pos]] = steps 38 | return keys 39 | 40 | def get_blocking_doors(self, dungeon): 41 | if self.type == "@": 42 | return [] 43 | 44 | next_search = defaultdict(list) 45 | next_search[dungeon.position] = [1] 46 | 47 | while True: 48 | search = copy(next_search) 49 | 50 | for position, state in search.items(): 51 | if state[0] == -1: 52 | del next_search[position] 53 | if state[0] == 1: 54 | next_search[position] = [-1] 55 | for side in [(-1,0), (0,-1), (1,0), (0,1)]: 56 | side_pos = (position[0] + side[0], position[1] + side[1]) 57 | if dungeon.area[side_pos] != "#" and \ 58 | not search[side_pos]: 59 | del search[side_pos] 60 | next_search[side_pos] = copy(state) 61 | if dungeon.area[side_pos] == self.type: 62 | return state[1:] 63 | elif dungeon.area[side_pos].isupper(): 64 | next_search[side_pos].append(dungeon.area[side_pos]) 65 | 66 | class Dungeon: 67 | def __init__(self, layout): 68 | self.area = defaultdict(str) 69 | self.size_x = len(layout[0]) 70 | self.size_y = len(layout) 71 | self.position = (0, 0) 72 | self.key_pos = {} 73 | 74 | for y in range(self.size_y): 75 | for x in range(self.size_x): 76 | self.area[(x, y)] = layout[y][x] 77 | if self.area[(x, y)].islower(): 78 | self.key_pos[self.area[(x, y)]] = (x, y) 79 | elif self.area[(x, y)] == "@": 80 | self.position = (x, y) 81 | 82 | self.reduce_dungeon() 83 | 84 | def is_dead_end(self, pos, keys_allowed = False): 85 | tile = self.area[pos] 86 | if tile == "#" or tile == "@" or (not keys_allowed and tile.islower()): 87 | return False 88 | 89 | count = sum(self.area[(pos[0] + side[0], pos[1] + side[1])] != "#" for side in [(-1,0), (0,-1), (1,0), (0,1)]) 90 | 91 | if count <= 1: 92 | return True 93 | return False 94 | 95 | def reduce_dungeon(self): 96 | reduced = True 97 | while reduced: 98 | reduced = False 99 | for y in range(1, self.size_y): 100 | for x in range(1, self.size_x): 101 | if self.is_dead_end((x, y)): 102 | self.area[(x, y)] = "#" 103 | reduced = True 104 | 105 | def create_keys(dungeon): 106 | keys = {} 107 | for type, position in dungeon.key_pos.items(): 108 | keys[type] = Key(dungeon, position, type) 109 | 110 | keys["@"] = Key(dungeon, dungeon.position, "@") 111 | 112 | return keys 113 | 114 | def get_reachable_keys(keys, keys_taken, doors_opened): 115 | reachable = set() 116 | for key in keys.values(): 117 | if len(set(key.blocked_by_doors) & doors_opened) == len(key.blocked_by_doors) and \ 118 | key.type not in keys_taken: 119 | reachable.add(key) 120 | return reachable 121 | 122 | def fetch_keys(keys, keys_taken, doors_opened, current_key = "@", known_best = 1e8, path = 0, known_situations = {}): 123 | if len(keys_taken) == len(keys): 124 | return path 125 | 126 | best_path = known_best 127 | reachable_keys = get_reachable_keys(keys, keys_taken, doors_opened) 128 | reachable_keys = sorted(reachable_keys, key = lambda x: keys[current_key].distance_to_keys[x.type]) 129 | 130 | for next_key in reachable_keys: 131 | next_path = path + keys[current_key].distance_to_keys[next_key.type] 132 | 133 | current_situation = tuple(sorted(list(keys_taken)) + [next_key.type]) 134 | 135 | if current_situation in known_situations: 136 | if next_path >= known_situations[current_situation]: 137 | continue 138 | 139 | known_situations[current_situation] = next_path 140 | 141 | if next_path >= best_path: 142 | continue 143 | 144 | next_keys_taken = keys_taken | set(next_key.type) 145 | next_doors_opened = doors_opened | set(next_key.type.upper()) 146 | 147 | this_path = fetch_keys(keys, next_keys_taken, next_doors_opened, next_key.type, best_path, next_path, known_situations) 148 | if this_path < best_path: 149 | best_path = this_path 150 | 151 | return best_path 152 | 153 | @timer 154 | def solve(): 155 | input = read_file("18") 156 | dungeon = Dungeon(input) 157 | keys = create_keys(dungeon) 158 | keys_taken = set(("@")) 159 | doors_opened = set() 160 | 161 | return fetch_keys(keys, keys_taken, doors_opened) 162 | 163 | result = solve() 164 | print(f"Solution: {result}") -------------------------------------------------------------------------------- /2019_18_p2.py: -------------------------------------------------------------------------------- 1 | from aoc import read_file, timer 2 | from collections import defaultdict 3 | from copy import copy, deepcopy 4 | 5 | class Key: 6 | def __init__(self, dungeon, position, type): 7 | self.position = position 8 | self.type = type 9 | self.distance_to_keys = self.get_key_distances(dungeon) 10 | self.bot = self.get_bot() 11 | self.blocked_by_doors = self.get_blocking_doors(dungeon) 12 | 13 | def get_key_distances(self, dungeon): 14 | next_search = defaultdict(int) 15 | next_search[self.position] = 1 16 | keys = {} 17 | changes = True 18 | steps = 0 19 | 20 | while changes or not steps: 21 | changes = False 22 | steps += 1 23 | search = copy(next_search) 24 | 25 | for position, state in search.items(): 26 | if state == -1: 27 | del next_search[position] 28 | if state == 1: 29 | next_search[position] = -1 30 | for side in [(-1,0), (0,-1), (1,0), (0,1)]: 31 | side_pos = (position[0] + side[0], position[1] + side[1]) 32 | if dungeon.area[side_pos] != "#" and \ 33 | not search[side_pos]: 34 | del search[side_pos] 35 | changes = True 36 | next_search[side_pos] = 1 37 | if dungeon.area[side_pos].islower() or dungeon.area[side_pos].isnumeric(): 38 | keys[dungeon.area[side_pos]] = steps 39 | return keys 40 | 41 | def get_blocking_doors(self, dungeon): 42 | if self.type.isnumeric(): 43 | return [] 44 | 45 | next_search = defaultdict(list) 46 | next_search[dungeon.bot_pos[self.bot]] = [1] 47 | 48 | while True: 49 | search = copy(next_search) 50 | 51 | for position, state in search.items(): 52 | if state[0] == -1: 53 | del next_search[position] 54 | if state[0] == 1: 55 | next_search[position] = [-1] 56 | for side in [(-1,0), (0,-1), (1,0), (0,1)]: 57 | side_pos = (position[0] + side[0], position[1] + side[1]) 58 | if dungeon.area[side_pos] != "#" and \ 59 | not search[side_pos]: 60 | del search[side_pos] 61 | next_search[side_pos] = copy(state) 62 | if dungeon.area[side_pos] == self.type: 63 | return state[1:] 64 | elif dungeon.area[side_pos].isupper(): 65 | next_search[side_pos].append(dungeon.area[side_pos]) 66 | 67 | def get_bot(self): 68 | for key in self.distance_to_keys.keys(): 69 | if key.isnumeric(): 70 | return int(key) 71 | 72 | 73 | class Dungeon: 74 | def __init__(self, layout): 75 | self.area = defaultdict(str) 76 | self.size_x = len(layout[0]) 77 | self.size_y = len(layout) 78 | self.position = (0, 0) 79 | self.key_pos = {} 80 | self.bot_pos = [] 81 | 82 | for y in range(self.size_y): 83 | for x in range(self.size_x): 84 | self.area[(x, y)] = layout[y][x] 85 | if self.area[(x, y)].islower(): 86 | self.key_pos[self.area[(x, y)]] = (x, y) 87 | elif self.area[(x, y)] == "@": 88 | self.position = (x, y) 89 | 90 | self.reduce_dungeon() 91 | self.patch_dungeon() 92 | 93 | def patch_dungeon(self): 94 | self.area[self.position] = "#" 95 | for side in [(-1,0), (0,-1), (1,0), (0,1)]: 96 | side_pos = (self.position[0] + side[0], self.position[1] + side[1]) 97 | self.area[side_pos] = "#" 98 | for side_id in range(4): 99 | side = [(-1,1), (1,-1), (1,1), (-1,-1)][side_id] 100 | side_pos = (self.position[0] + side[0], self.position[1] + side[1]) 101 | self.area[side_pos] = str(side_id) 102 | self.bot_pos.append(side_pos) 103 | self.key_pos[str(side_id)] = side_pos 104 | 105 | def is_dead_end(self, pos, keys_allowed = False): 106 | tile = self.area[pos] 107 | if tile == "#" or tile == "@" or (not keys_allowed and tile.islower()): 108 | return False 109 | 110 | count = sum(self.area[(pos[0] + side[0], pos[1] + side[1])] != "#" for side in [(-1,0), (0,-1), (1,0), (0,1)]) 111 | 112 | if count <= 1: 113 | return True 114 | return False 115 | 116 | def reduce_dungeon(self): 117 | reduced = True 118 | while reduced: 119 | reduced = False 120 | for y in range(1, self.size_y): 121 | for x in range(1, self.size_x): 122 | if self.is_dead_end((x, y)): 123 | self.area[(x, y)] = "#" 124 | reduced = True 125 | 126 | def create_keys(dungeon): 127 | keys = {} 128 | for type, position in dungeon.key_pos.items(): 129 | keys[type] = Key(dungeon, position, type) 130 | 131 | for bot_id in range(4): 132 | keys[str(bot_id)] = Key(dungeon, dungeon.bot_pos[bot_id], str(bot_id)) 133 | 134 | return keys 135 | 136 | def get_reachable_keys(keys, keys_taken, doors_opened): 137 | reachable = set() 138 | for key in keys.values(): 139 | if len(set(key.blocked_by_doors) & doors_opened) == len(key.blocked_by_doors) and \ 140 | key.type not in keys_taken: 141 | reachable.add(key) 142 | return reachable 143 | 144 | def fetch_keys(key_pos, bot_pos, keys, keys_taken, doors_opened, known_best = 1e8, path = 0, known_situations = {}): 145 | if len(keys_taken) == len(keys): 146 | return path 147 | 148 | best_path = known_best 149 | reachable_keys = get_reachable_keys(keys, keys_taken, doors_opened) 150 | 151 | for next_key in reachable_keys: 152 | for current_key, position in key_pos.items(): 153 | if bot_pos[next_key.bot] == position: 154 | break 155 | 156 | next_path = path + keys[current_key].distance_to_keys[next_key.type] 157 | 158 | current_situation = tuple(sorted(list(keys_taken)) + [bot_pos[bot_id] for bot_id in range(4)]) 159 | 160 | if current_situation in known_situations: 161 | if next_path >= known_situations[current_situation]: 162 | continue 163 | 164 | known_situations[current_situation] = next_path 165 | 166 | if next_path >= best_path: 167 | continue 168 | 169 | next_keys_taken = keys_taken | set(next_key.type) 170 | next_doors_opened = doors_opened | set(next_key.type.upper()) 171 | next_bot_pos = deepcopy(bot_pos) 172 | next_bot_pos[next_key.bot] = copy(key_pos[next_key.type]) 173 | 174 | this_path = fetch_keys(key_pos, next_bot_pos, keys, next_keys_taken, next_doors_opened, best_path, next_path, known_situations) 175 | if this_path < best_path: 176 | best_path = this_path 177 | 178 | return best_path 179 | 180 | @timer 181 | def solve(): 182 | input = read_file("18") 183 | dungeon = Dungeon(input) 184 | keys = create_keys(dungeon) 185 | keys_taken = set(str(bot_id) for bot_id in range(4)) 186 | doors_opened = set() 187 | 188 | return fetch_keys(dungeon.key_pos, dungeon.bot_pos, keys, keys_taken, doors_opened) 189 | 190 | result = solve() 191 | print(f"Solution: {result}") -------------------------------------------------------------------------------- /2019_19_p1.py: -------------------------------------------------------------------------------- 1 | from aoc import read_file, timer 2 | from collections import defaultdict, deque 3 | from copy import copy 4 | 5 | class Game: 6 | def __init__(self, prog): 7 | self.prog = prog 8 | self.ip = 0 9 | self.input = deque() 10 | self.output = deque() 11 | self.rel_base = 0 12 | self.halt = False 13 | 14 | def split_instruction(instruction): 15 | instruction = f"{instruction:05}" 16 | return instruction[3:], instruction[0:3] 17 | 18 | def get_values(input, pos, op, modes, game): 19 | mode_a, mode_b, mode_c = modes 20 | values = [] 21 | offset = 0 22 | 23 | if op in ["01", "02", "04", "05", "06", "07", "08", "09"]: 24 | if mode_c == "0": 25 | values.append(input[input[pos+1]]) 26 | elif mode_c == "1": 27 | values.append(input[pos+1]) 28 | elif mode_c == "2": 29 | values.append(input[input[pos+1]+game.rel_base]) 30 | 31 | if op in ["01", "02", "05", "06", "07", "08"]: 32 | if mode_b == "0": 33 | values.append(input[input[pos+2]]) 34 | elif mode_b == "1": 35 | values.append(input[pos+2]) 36 | elif mode_b == "2": 37 | values.append(input[input[pos+2]+game.rel_base]) 38 | 39 | if op in []: 40 | if mode_a == "0": 41 | values.append(input[input[pos+3]]) 42 | elif mode_a == "1": 43 | values.append(input[pos+3]) 44 | elif mode_a == "2": 45 | values.append(input[input[pos+3]+game.rel_base]) 46 | 47 | if op in ["01", "02", "07", "08"]: 48 | if mode_a == "2": 49 | offset = game.rel_base 50 | 51 | if op in ["03"]: 52 | if mode_c == "2": 53 | offset = game.rel_base 54 | 55 | return values, offset 56 | 57 | def read_output(game): 58 | if len(game.output): 59 | return game.output.popleft() 60 | return None 61 | 62 | def run_game(game, input = []): 63 | if len(input): 64 | game.input.extend(input) 65 | 66 | while game.prog[game.ip] != 99: 67 | op, modes = split_instruction(game.prog[game.ip]) 68 | values, offset = get_values(game.prog, game.ip, op, modes, game) 69 | 70 | if op == "01": # Addition 71 | game.prog[game.prog[game.ip+3] + offset] = values[0] + values[1] 72 | game.ip += 4 73 | 74 | if op == "02": # Multiplication 75 | game.prog[game.prog[game.ip+3] + offset] = values[0] * values[1] 76 | game.ip += 4 77 | 78 | if op == "03": # Read and Store input 79 | game.prog[game.prog[game.ip+1] + offset] = game.input.popleft() 80 | game.ip += 2 81 | 82 | if op == "04": # Print Output 83 | game.output.append(values[0]) 84 | game.ip += 2 85 | return 86 | 87 | if op == "05": # Jump-if-True 88 | if values[0]: 89 | game.ip = values[1] 90 | else: 91 | game.ip += 3 92 | 93 | if op == "06": # Jump-if-False 94 | if not values[0]: 95 | game.ip = values[1] 96 | else: 97 | game.ip += 3 98 | 99 | if op == "07": # Less than 100 | if values[0] < values[1]: 101 | game.prog[game.prog[game.ip+3] + offset] = 1 102 | else: 103 | game.prog[game.prog[game.ip+3] + offset] = 0 104 | game.ip += 4 105 | 106 | if op == "08": # Equals 107 | if values[0] == values[1]: 108 | game.prog[game.prog[game.ip+3] + offset] = 1 109 | else: 110 | game.prog[game.prog[game.ip+3] + offset] = 0 111 | game.ip += 4 112 | 113 | if op == "09": # Adjust Relative Base 114 | game.rel_base += values[0] 115 | game.ip += 2 116 | 117 | game.halt = True 118 | 119 | def create_program(input): 120 | prog = defaultdict(int) 121 | 122 | for i in range(len(input)): 123 | prog[i] = int(input[i]) 124 | 125 | return prog 126 | 127 | @timer 128 | def solve(): 129 | input = read_file("19")[0].split(",") 130 | prog = create_program(input) 131 | game = Game(prog) 132 | 133 | result = 0 134 | 135 | for y in range(50): 136 | for x in range(50): 137 | game = Game(copy(prog)) 138 | run_game(game, [x, y]) 139 | if read_output(game): 140 | result += 1 141 | 142 | return result 143 | 144 | result = solve() 145 | print(f"Solution: {result}") -------------------------------------------------------------------------------- /2019_19_p2.py: -------------------------------------------------------------------------------- 1 | from aoc import read_file, timer 2 | from collections import defaultdict, deque 3 | from copy import copy 4 | 5 | class Game: 6 | def __init__(self, prog): 7 | self.prog = prog 8 | self.ip = 0 9 | self.input = deque() 10 | self.output = deque() 11 | self.rel_base = 0 12 | self.halt = False 13 | 14 | def split_instruction(instruction): 15 | instruction = f"{instruction:05}" 16 | return instruction[3:], instruction[0:3] 17 | 18 | def get_values(input, pos, op, modes, game): 19 | mode_a, mode_b, mode_c = modes 20 | values = [] 21 | offset = 0 22 | 23 | if op in ["01", "02", "04", "05", "06", "07", "08", "09"]: 24 | if mode_c == "0": 25 | values.append(input[input[pos+1]]) 26 | elif mode_c == "1": 27 | values.append(input[pos+1]) 28 | elif mode_c == "2": 29 | values.append(input[input[pos+1]+game.rel_base]) 30 | 31 | if op in ["01", "02", "05", "06", "07", "08"]: 32 | if mode_b == "0": 33 | values.append(input[input[pos+2]]) 34 | elif mode_b == "1": 35 | values.append(input[pos+2]) 36 | elif mode_b == "2": 37 | values.append(input[input[pos+2]+game.rel_base]) 38 | 39 | if op in []: 40 | if mode_a == "0": 41 | values.append(input[input[pos+3]]) 42 | elif mode_a == "1": 43 | values.append(input[pos+3]) 44 | elif mode_a == "2": 45 | values.append(input[input[pos+3]+game.rel_base]) 46 | 47 | if op in ["01", "02", "07", "08"]: 48 | if mode_a == "2": 49 | offset = game.rel_base 50 | 51 | if op in ["03"]: 52 | if mode_c == "2": 53 | offset = game.rel_base 54 | 55 | return values, offset 56 | 57 | def read_output(game): 58 | if len(game.output): 59 | return game.output.popleft() 60 | return None 61 | 62 | def run_game(game, input = []): 63 | if len(input): 64 | game.input.extend(input) 65 | 66 | while game.prog[game.ip] != 99: 67 | op, modes = split_instruction(game.prog[game.ip]) 68 | values, offset = get_values(game.prog, game.ip, op, modes, game) 69 | 70 | if op == "01": # Addition 71 | game.prog[game.prog[game.ip+3] + offset] = values[0] + values[1] 72 | game.ip += 4 73 | 74 | if op == "02": # Multiplication 75 | game.prog[game.prog[game.ip+3] + offset] = values[0] * values[1] 76 | game.ip += 4 77 | 78 | if op == "03": # Read and Store input 79 | game.prog[game.prog[game.ip+1] + offset] = game.input.popleft() 80 | game.ip += 2 81 | 82 | if op == "04": # Print Output 83 | game.output.append(values[0]) 84 | game.ip += 2 85 | return 86 | 87 | if op == "05": # Jump-if-True 88 | if values[0]: 89 | game.ip = values[1] 90 | else: 91 | game.ip += 3 92 | 93 | if op == "06": # Jump-if-False 94 | if not values[0]: 95 | game.ip = values[1] 96 | else: 97 | game.ip += 3 98 | 99 | if op == "07": # Less than 100 | if values[0] < values[1]: 101 | game.prog[game.prog[game.ip+3] + offset] = 1 102 | else: 103 | game.prog[game.prog[game.ip+3] + offset] = 0 104 | game.ip += 4 105 | 106 | if op == "08": # Equals 107 | if values[0] == values[1]: 108 | game.prog[game.prog[game.ip+3] + offset] = 1 109 | else: 110 | game.prog[game.prog[game.ip+3] + offset] = 0 111 | game.ip += 4 112 | 113 | if op == "09": # Adjust Relative Base 114 | game.rel_base += values[0] 115 | game.ip += 2 116 | 117 | game.halt = True 118 | 119 | def create_program(input): 120 | prog = defaultdict(int) 121 | 122 | for i in range(len(input)): 123 | prog[i] = int(input[i]) 124 | 125 | return prog 126 | 127 | def try_y(prog, y, box_size = 100): 128 | output = 0 129 | x = y 130 | 131 | while output == 0: 132 | x += 1 133 | game = Game(copy(prog)) 134 | run_game(game, [x, y]) 135 | output = read_output(game) 136 | 137 | x1 = x 138 | 139 | while output == 1: 140 | x += 1 141 | game = Game(copy(prog)) 142 | run_game(game, [x, y]) 143 | output = read_output(game) 144 | 145 | x2 = x - 1 146 | 147 | if x2 - x1 + 1 < box_size: 148 | return -1, None 149 | 150 | game = Game(copy(prog)) 151 | run_game(game, [x2-(box_size-1), y+box_size-1]) 152 | 153 | if read_output(game) == 1: 154 | game = Game(copy(prog)) 155 | run_game(game, [x2-(box_size-1), y+box_size]) 156 | if read_output(game) == 0: 157 | return 0, (x2-(box_size-1), y) 158 | return 1, None 159 | return -1, None 160 | 161 | @timer 162 | def solve(): 163 | input = read_file("19")[0].split(",") 164 | prog = create_program(input) 165 | game = Game(prog) 166 | 167 | mini, maxi = 50, 1000 168 | check = 1 169 | 170 | while check: 171 | middle = (maxi + mini) // 2 172 | check, corner = try_y(prog, middle) 173 | if check == -1: 174 | mini = middle 175 | elif check == 1: 176 | maxi = middle 177 | 178 | while not check: 179 | middle -= 1 180 | check, corner = try_y(prog, middle) 181 | if not check: 182 | real_corner = corner 183 | 184 | return real_corner[0] * 10000 + real_corner[1] 185 | 186 | result = solve() 187 | print(f"Solution: {result}") -------------------------------------------------------------------------------- /2019_20_p1.py: -------------------------------------------------------------------------------- 1 | from aoc import read_file, timer 2 | from collections import defaultdict 3 | from copy import copy 4 | 5 | class Dungeon: 6 | def __init__(self, layout): 7 | self.area = defaultdict(str) 8 | self.size_x = len(layout[2])+4 9 | self.size_y = len(layout) 10 | self.portals = defaultdict(list) 11 | self.portal_names = defaultdict(str) 12 | self.paths = defaultdict(list) 13 | 14 | for y in range(self.size_y): 15 | for x in range(self.size_x): 16 | if x < len(layout[y]): 17 | self.area[(x, y)] = layout[y][x] 18 | 19 | self.reduce_dungeon() 20 | self.find_portals() 21 | self.find_paths() 22 | 23 | def is_dead_end(self, pos, keys_allowed = False): 24 | tile = self.area[pos] 25 | if tile == "#" or tile == "@" or (not keys_allowed and tile.islower()): 26 | return False 27 | 28 | count = sum(self.area[(pos[0] + side[0], pos[1] + side[1])] != "#" for side in [(-1,0), (0,-1), (1,0), (0,1)]) 29 | 30 | if count <= 1: 31 | return True 32 | return False 33 | 34 | def reduce_dungeon(self): 35 | reduced = True 36 | while reduced: 37 | reduced = False 38 | for y in range(1, self.size_y): 39 | for x in range(1, self.size_x): 40 | if self.is_dead_end((x, y)): 41 | self.area[(x, y)] = "#" 42 | reduced = True 43 | 44 | def find_portals(self): 45 | for y in range(self.size_y): 46 | for x in range(self.size_x): 47 | if self.area[(x, y)].isupper(): 48 | if self.area[(x+1, y)].isupper(): 49 | name = self.area[(x, y)] + self.area[(x+1, y)] 50 | if not name in [p[0] for p in self.portals]: 51 | id = 0 52 | else: 53 | id = 1 54 | if self.area[(x+2, y)] == ".": 55 | self.portals[(name, id)].append((x+2, y)) 56 | self.portal_names[(x+1, y)] = (name, id) 57 | elif self.area[(x-1, y)] == ".": 58 | self.portals[(name, id)].append((x-1, y)) 59 | self.portal_names[(x, y)] = (name, id) 60 | 61 | elif self.area[(x, y+1)].isupper(): 62 | name = self.area[(x, y)] + self.area[(x, y+1)] 63 | if not name in [p[0] for p in self.portals]: 64 | id = 0 65 | else: 66 | id = 1 67 | if self.area[(x, y+2)] == ".": 68 | self.portals[(name, id)].append((x, y+2)) 69 | self.portal_names[(x, y+1)] = (name, id) 70 | elif self.area[(x, y-1)] == ".": 71 | self.portals[(name, id)].append((x, y-1)) 72 | self.portal_names[(x, y)] = (name, id) 73 | 74 | def find_paths(self): 75 | for name, positions in self.portals.items(): 76 | for pos in positions: 77 | next_search = defaultdict(int) 78 | next_search[pos] = 1 79 | 80 | changes = True 81 | steps = 0 82 | 83 | while changes or not steps: 84 | changes = False 85 | steps += 1 86 | search = copy(next_search) 87 | 88 | for position, state in search.items(): 89 | if state == -1: 90 | del next_search[position] 91 | if state == 1: 92 | next_search[position] = -1 93 | for side in [(-1,0), (0,-1), (1,0), (0,1)]: 94 | side_pos = (position[0] + side[0], position[1] + side[1]) 95 | if self.area[side_pos] != "#" and \ 96 | not search[side_pos]: 97 | del search[side_pos] 98 | changes = True 99 | next_search[side_pos] = 1 100 | if self.area[side_pos].isupper(): 101 | next_search[side_pos] = -1 102 | if steps > 1: 103 | target_name = self.portal_names[(side_pos)] 104 | self.paths[name].append((target_name, steps-1)) 105 | 106 | def find_shortest_way(dungeon, path = [("AA", 0)], best_steps = 1e8, steps = 0): 107 | if path[-1] == ("ZZ", 1): 108 | return steps 109 | 110 | for next_portal in dungeon.paths[path[-1]]: 111 | if next_portal[0] in path: 112 | continue 113 | 114 | next_steps = steps + next_portal[1] + 1 115 | if next_steps >= best_steps: 116 | continue 117 | 118 | if next_portal[0][1] == 0: 119 | id = 1 120 | else: 121 | id = 0 122 | 123 | next_path = path + [next_portal] + [(next_portal[0][0], id)] 124 | this_steps = find_shortest_way(dungeon, next_path, best_steps, next_steps) 125 | 126 | if this_steps < best_steps: 127 | best_steps = this_steps 128 | 129 | return best_steps 130 | 131 | @timer 132 | def solve(): 133 | input = read_file("20", strip = False) 134 | dungeon = Dungeon(input) 135 | return find_shortest_way(dungeon) - 1 136 | 137 | result = solve() 138 | print(f"Solution: {result}") -------------------------------------------------------------------------------- /2019_20_p2.py: -------------------------------------------------------------------------------- 1 | from aoc import read_file, timer 2 | from collections import defaultdict 3 | from copy import copy 4 | 5 | class Dungeon: 6 | def __init__(self, layout): 7 | self.area = defaultdict(str) 8 | self.size_x = len(layout[2])+4 9 | self.size_y = len(layout) 10 | self.portals = defaultdict(list) 11 | self.portal_names = defaultdict(str) 12 | self.paths = defaultdict(list) 13 | 14 | for y in range(self.size_y): 15 | for x in range(self.size_x): 16 | if x < len(layout[y]): 17 | self.area[(x, y)] = layout[y][x] 18 | 19 | self.reduce_dungeon() 20 | self.find_portals() 21 | self.find_paths() 22 | 23 | def is_dead_end(self, pos, keys_allowed = False): 24 | tile = self.area[pos] 25 | if tile == "#" or tile == "@" or (not keys_allowed and tile.islower()): 26 | return False 27 | 28 | count = sum(self.area[(pos[0] + side[0], pos[1] + side[1])] != "#" for side in [(-1,0), (0,-1), (1,0), (0,1)]) 29 | 30 | if count <= 1: 31 | return True 32 | return False 33 | 34 | def reduce_dungeon(self): 35 | reduced = True 36 | while reduced: 37 | reduced = False 38 | for y in range(1, self.size_y): 39 | for x in range(1, self.size_x): 40 | if self.is_dead_end((x, y)): 41 | self.area[(x, y)] = "#" 42 | reduced = True 43 | 44 | def find_portals(self): 45 | for y in range(self.size_y): 46 | for x in range(self.size_x): 47 | if self.area[(x, y)].isupper(): 48 | if x > 10 and y > 10 and \ 49 | x < self.size_x - 10 and y < self.size_y - 10: 50 | id = 1 51 | else: 52 | id = -1 53 | 54 | if self.area[(x+1, y)].isupper(): 55 | name = self.area[(x, y)] + self.area[(x+1, y)] 56 | if self.area[(x+2, y)] == ".": 57 | self.portals[(name, id)].append((x+2, y)) 58 | self.portal_names[(x+1, y)] = (name, id) 59 | elif self.area[(x-1, y)] == ".": 60 | self.portals[(name, id)].append((x-1, y)) 61 | self.portal_names[(x, y)] = (name, id) 62 | 63 | elif self.area[(x, y+1)].isupper(): 64 | name = self.area[(x, y)] + self.area[(x, y+1)] 65 | if self.area[(x, y+2)] == ".": 66 | self.portals[(name, id)].append((x, y+2)) 67 | self.portal_names[(x, y+1)] = (name, id) 68 | elif self.area[(x, y-1)] == ".": 69 | self.portals[(name, id)].append((x, y-1)) 70 | self.portal_names[(x, y)] = (name, id) 71 | 72 | def find_paths(self): 73 | for name, positions in self.portals.items(): 74 | for pos in positions: 75 | next_search = defaultdict(int) 76 | next_search[pos] = 1 77 | 78 | changes = True 79 | steps = 0 80 | 81 | while changes or not steps: 82 | changes = False 83 | steps += 1 84 | search = copy(next_search) 85 | 86 | for position, state in search.items(): 87 | if state == -1: 88 | del next_search[position] 89 | if state == 1: 90 | next_search[position] = -1 91 | for side in [(-1,0), (0,-1), (1,0), (0,1)]: 92 | side_pos = (position[0] + side[0], position[1] + side[1]) 93 | if self.area[side_pos] != "#" and \ 94 | not search[side_pos]: 95 | del search[side_pos] 96 | changes = True 97 | next_search[side_pos] = 1 98 | if self.area[side_pos].isupper(): 99 | next_search[side_pos] = -1 100 | if steps > 1: 101 | target_name = self.portal_names[(side_pos)] 102 | self.paths[name].append((target_name, steps-1)) 103 | 104 | def find_shortest_way(dungeon, path = [("AA", -1, 0)], best_steps = 1e8, steps = 0): 105 | depth = path[-1][2] 106 | if depth > 25: 107 | return 1e8 108 | if depth == -1: 109 | return steps 110 | 111 | for next_portal in sorted(dungeon.paths[(path[-1][0], path[-1][1])], key = lambda x: x[1], reverse = True): 112 | situation = (next_portal[0][0], next_portal[0][1], depth) 113 | 114 | if situation in path: 115 | continue 116 | if (situation[0] == "AA" or situation[0] == "ZZ") and situation[2] > 0: 117 | continue 118 | if (situation[0] != "AA" and situation[0] != "ZZ") and situation[1] == -1 and situation[2] == 0: 119 | continue 120 | 121 | next_steps = steps + next_portal[1] + 1 122 | if next_steps >= best_steps: 123 | continue 124 | 125 | if next_portal[0][1] == -1: 126 | id = 1 127 | else: 128 | id = -1 129 | 130 | next_path = path + [situation] + [(next_portal[0][0], id, depth + next_portal[0][1])] 131 | this_steps = find_shortest_way(dungeon, next_path, best_steps, next_steps) 132 | 133 | if this_steps < best_steps: 134 | best_steps = this_steps 135 | 136 | return best_steps 137 | 138 | @timer 139 | def solve(): 140 | input = read_file("20", strip = False) 141 | dungeon = Dungeon(input) 142 | return find_shortest_way(dungeon) - 1 143 | 144 | result = solve() 145 | print(f"Solution: {result}") -------------------------------------------------------------------------------- /2019_21_p1.py: -------------------------------------------------------------------------------- 1 | from aoc import read_file, timer 2 | from collections import defaultdict, deque 3 | 4 | class Game: 5 | def __init__(self, prog): 6 | self.prog = prog 7 | self.ip = 0 8 | self.input = deque() 9 | self.output = deque() 10 | self.rel_base = 0 11 | self.halt = False 12 | 13 | def split_instruction(instruction): 14 | instruction = f"{instruction:05}" 15 | return instruction[3:], instruction[0:3] 16 | 17 | def get_values(input, pos, op, modes, game): 18 | mode_a, mode_b, mode_c = modes 19 | values = [] 20 | offset = 0 21 | 22 | if op in ["01", "02", "04", "05", "06", "07", "08", "09"]: 23 | if mode_c == "0": 24 | values.append(input[input[pos+1]]) 25 | elif mode_c == "1": 26 | values.append(input[pos+1]) 27 | elif mode_c == "2": 28 | values.append(input[input[pos+1]+game.rel_base]) 29 | 30 | if op in ["01", "02", "05", "06", "07", "08"]: 31 | if mode_b == "0": 32 | values.append(input[input[pos+2]]) 33 | elif mode_b == "1": 34 | values.append(input[pos+2]) 35 | elif mode_b == "2": 36 | values.append(input[input[pos+2]+game.rel_base]) 37 | 38 | if op in []: 39 | if mode_a == "0": 40 | values.append(input[input[pos+3]]) 41 | elif mode_a == "1": 42 | values.append(input[pos+3]) 43 | elif mode_a == "2": 44 | values.append(input[input[pos+3]+game.rel_base]) 45 | 46 | if op in ["01", "02", "07", "08"]: 47 | if mode_a == "2": 48 | offset = game.rel_base 49 | 50 | if op in ["03"]: 51 | if mode_c == "2": 52 | offset = game.rel_base 53 | 54 | return values, offset 55 | 56 | def read_output(game): 57 | if len(game.output): 58 | return game.output.popleft() 59 | return None 60 | 61 | def run_game(game, input = []): 62 | if len(input): 63 | game.input.extend(input) 64 | 65 | while game.prog[game.ip] != 99: 66 | op, modes = split_instruction(game.prog[game.ip]) 67 | values, offset = get_values(game.prog, game.ip, op, modes, game) 68 | 69 | if op == "01": # Addition 70 | game.prog[game.prog[game.ip+3] + offset] = values[0] + values[1] 71 | game.ip += 4 72 | 73 | if op == "02": # Multiplication 74 | game.prog[game.prog[game.ip+3] + offset] = values[0] * values[1] 75 | game.ip += 4 76 | 77 | if op == "03": # Read and Store input 78 | game.prog[game.prog[game.ip+1] + offset] = game.input.popleft() 79 | game.ip += 2 80 | 81 | if op == "04": # Print Output 82 | game.output.append(values[0]) 83 | game.ip += 2 84 | return 85 | 86 | if op == "05": # Jump-if-True 87 | if values[0]: 88 | game.ip = values[1] 89 | else: 90 | game.ip += 3 91 | 92 | if op == "06": # Jump-if-False 93 | if not values[0]: 94 | game.ip = values[1] 95 | else: 96 | game.ip += 3 97 | 98 | if op == "07": # Less than 99 | if values[0] < values[1]: 100 | game.prog[game.prog[game.ip+3] + offset] = 1 101 | else: 102 | game.prog[game.prog[game.ip+3] + offset] = 0 103 | game.ip += 4 104 | 105 | if op == "08": # Equals 106 | if values[0] == values[1]: 107 | game.prog[game.prog[game.ip+3] + offset] = 1 108 | else: 109 | game.prog[game.prog[game.ip+3] + offset] = 0 110 | game.ip += 4 111 | 112 | if op == "09": # Adjust Relative Base 113 | game.rel_base += values[0] 114 | game.ip += 2 115 | 116 | game.halt = True 117 | 118 | def create_program(input): 119 | prog = defaultdict(int) 120 | 121 | for i in range(len(input)): 122 | prog[i] = int(input[i]) 123 | 124 | return prog 125 | 126 | @timer 127 | def solve(): 128 | input = read_file("21")[0].split(",") 129 | prog = create_program(input) 130 | game = Game(prog) 131 | 132 | output = 0 133 | 134 | while output != 10: 135 | run_game(game) 136 | if (output := read_output(game)): 137 | print(chr(output), end ="") 138 | 139 | instruction = "NOT C J\n" + \ 140 | "NOT A T\n" + \ 141 | "OR T J\n" + \ 142 | "AND D J\n" + \ 143 | "WALK\n" 144 | 145 | print(instruction) 146 | run_game(game, [ord(char) for char in instruction]) 147 | 148 | while not game.halt: 149 | if (output := read_output(game)): 150 | if output > 255: 151 | return output 152 | else: 153 | print(chr(output), end ="") 154 | run_game(game) 155 | 156 | result = solve() 157 | print(f"Solution: {result}") -------------------------------------------------------------------------------- /2019_21_p2.py: -------------------------------------------------------------------------------- 1 | from aoc import read_file, timer 2 | from collections import defaultdict, deque 3 | 4 | class Game: 5 | def __init__(self, prog): 6 | self.prog = prog 7 | self.ip = 0 8 | self.input = deque() 9 | self.output = deque() 10 | self.rel_base = 0 11 | self.halt = False 12 | 13 | def split_instruction(instruction): 14 | instruction = f"{instruction:05}" 15 | return instruction[3:], instruction[0:3] 16 | 17 | def get_values(input, pos, op, modes, game): 18 | mode_a, mode_b, mode_c = modes 19 | values = [] 20 | offset = 0 21 | 22 | if op in ["01", "02", "04", "05", "06", "07", "08", "09"]: 23 | if mode_c == "0": 24 | values.append(input[input[pos+1]]) 25 | elif mode_c == "1": 26 | values.append(input[pos+1]) 27 | elif mode_c == "2": 28 | values.append(input[input[pos+1]+game.rel_base]) 29 | 30 | if op in ["01", "02", "05", "06", "07", "08"]: 31 | if mode_b == "0": 32 | values.append(input[input[pos+2]]) 33 | elif mode_b == "1": 34 | values.append(input[pos+2]) 35 | elif mode_b == "2": 36 | values.append(input[input[pos+2]+game.rel_base]) 37 | 38 | if op in []: 39 | if mode_a == "0": 40 | values.append(input[input[pos+3]]) 41 | elif mode_a == "1": 42 | values.append(input[pos+3]) 43 | elif mode_a == "2": 44 | values.append(input[input[pos+3]+game.rel_base]) 45 | 46 | if op in ["01", "02", "07", "08"]: 47 | if mode_a == "2": 48 | offset = game.rel_base 49 | 50 | if op in ["03"]: 51 | if mode_c == "2": 52 | offset = game.rel_base 53 | 54 | return values, offset 55 | 56 | def read_output(game): 57 | if len(game.output): 58 | return game.output.popleft() 59 | return None 60 | 61 | def run_game(game, input = []): 62 | if len(input): 63 | game.input.extend(input) 64 | 65 | while game.prog[game.ip] != 99: 66 | op, modes = split_instruction(game.prog[game.ip]) 67 | values, offset = get_values(game.prog, game.ip, op, modes, game) 68 | 69 | if op == "01": # Addition 70 | game.prog[game.prog[game.ip+3] + offset] = values[0] + values[1] 71 | game.ip += 4 72 | 73 | if op == "02": # Multiplication 74 | game.prog[game.prog[game.ip+3] + offset] = values[0] * values[1] 75 | game.ip += 4 76 | 77 | if op == "03": # Read and Store input 78 | game.prog[game.prog[game.ip+1] + offset] = game.input.popleft() 79 | game.ip += 2 80 | 81 | if op == "04": # Print Output 82 | game.output.append(values[0]) 83 | game.ip += 2 84 | return 85 | 86 | if op == "05": # Jump-if-True 87 | if values[0]: 88 | game.ip = values[1] 89 | else: 90 | game.ip += 3 91 | 92 | if op == "06": # Jump-if-False 93 | if not values[0]: 94 | game.ip = values[1] 95 | else: 96 | game.ip += 3 97 | 98 | if op == "07": # Less than 99 | if values[0] < values[1]: 100 | game.prog[game.prog[game.ip+3] + offset] = 1 101 | else: 102 | game.prog[game.prog[game.ip+3] + offset] = 0 103 | game.ip += 4 104 | 105 | if op == "08": # Equals 106 | if values[0] == values[1]: 107 | game.prog[game.prog[game.ip+3] + offset] = 1 108 | else: 109 | game.prog[game.prog[game.ip+3] + offset] = 0 110 | game.ip += 4 111 | 112 | if op == "09": # Adjust Relative Base 113 | game.rel_base += values[0] 114 | game.ip += 2 115 | 116 | game.halt = True 117 | 118 | def create_program(input): 119 | prog = defaultdict(int) 120 | 121 | for i in range(len(input)): 122 | prog[i] = int(input[i]) 123 | 124 | return prog 125 | 126 | @timer 127 | def solve(): 128 | input = read_file("21")[0].split(",") 129 | prog = create_program(input) 130 | game = Game(prog) 131 | 132 | output = 0 133 | 134 | while output != 10: 135 | run_game(game) 136 | if (output := read_output(game)): 137 | print(chr(output), end ="") 138 | 139 | instruction = "NOT C J\n" + \ 140 | "NOT B T\n" + \ 141 | "OR T J\n" + \ 142 | "NOT A T\n" + \ 143 | "OR T J\n" + \ 144 | "AND D J\n" + \ 145 | "NOT E T\n" + \ 146 | "NOT T T\n" + \ 147 | "OR H T\n" + \ 148 | "AND T J\n" + \ 149 | "RUN\n" 150 | 151 | print(instruction) 152 | run_game(game, [ord(char) for char in instruction]) 153 | 154 | while not game.halt: 155 | if (output := read_output(game)): 156 | if output > 255: 157 | return output 158 | else: 159 | print(chr(output), end ="") 160 | run_game(game) 161 | 162 | result = solve() 163 | print(f"Solution: {result}") -------------------------------------------------------------------------------- /2019_22_p1.py: -------------------------------------------------------------------------------- 1 | from aoc import read_file, timer 2 | 3 | def cut(deck, amount): 4 | if amount > 0: 5 | return deck[amount:] + deck[:amount] 6 | elif amount < 0: 7 | return deck[len(deck)+amount:] + deck[:len(deck)+amount] 8 | return deck 9 | 10 | def deal_into_new_stack(deck): 11 | return deck[::-1] 12 | 13 | def deal_with_increment(deck, amount): 14 | new_deck = [0 for _ in range(len(deck))] 15 | for i in range(len(deck)): 16 | new_deck[(i*amount)%len(deck)] = deck[i] 17 | return new_deck 18 | 19 | @timer 20 | def solve(): 21 | input = read_file("22") 22 | instructions = [line.split(" ") for line in input] 23 | 24 | deck = [num for num in range(10007)] 25 | 26 | for instruction in instructions: 27 | if instruction[-2] == "cut": 28 | deck = cut(deck, int(instruction[-1])) 29 | 30 | elif instruction[-1] == "stack": 31 | deck = deal_into_new_stack(deck) 32 | 33 | else: 34 | deck = deal_with_increment(deck, int(instruction[-1])) 35 | 36 | return deck.index(2019) 37 | 38 | result = solve() 39 | print(f"Solution: {result}") -------------------------------------------------------------------------------- /2019_22_p2.py: -------------------------------------------------------------------------------- 1 | from aoc import read_file, timer 2 | from collections import deque 3 | 4 | def apply_operation(operations, addi, multi, size): 5 | operation = operations.popleft() 6 | 7 | if len(operations): 8 | addi, multi = apply_operation(operations, addi, multi, size) 9 | 10 | if operation[-2] == "cut": 11 | addi += int(operation[-1]) * multi 12 | elif operation[-1] == "stack": 13 | multi *= -1 14 | addi += multi 15 | else: 16 | multi *= pow(int(operation[-1]), -1, size) 17 | 18 | return addi, multi 19 | 20 | @timer 21 | def solve(): 22 | input = read_file("22") 23 | operations = deque(reversed([line.split(" ") for line in input])) 24 | 25 | position = 2020 26 | size = 119315717514047 27 | iterations = 101741582076661 28 | 29 | addi, multi = apply_operation(operations, 0, 1, size) 30 | 31 | all_multi = pow(multi, iterations, size) 32 | all_addi = addi * (1 - pow(multi, iterations, size)) * pow(1 - multi, -1, size) 33 | 34 | return (position * all_multi + all_addi) % size 35 | 36 | result = solve() 37 | print(f"Solution: {result}") -------------------------------------------------------------------------------- /2019_23_p1.py: -------------------------------------------------------------------------------- 1 | from aoc import read_file, timer 2 | from collections import defaultdict, deque 3 | 4 | class Game: 5 | def __init__(self, prog): 6 | self.prog = prog 7 | self.ip = 0 8 | self.input = deque() 9 | self.output = deque() 10 | self.rel_base = 0 11 | self.halt = False 12 | 13 | def split_instruction(instruction): 14 | instruction = f"{instruction:05}" 15 | return instruction[3:], instruction[0:3] 16 | 17 | def get_values(input, pos, op, modes, game): 18 | mode_a, mode_b, mode_c = modes 19 | values = [] 20 | offset = 0 21 | 22 | if op in ["01", "02", "04", "05", "06", "07", "08", "09"]: 23 | if mode_c == "0": 24 | values.append(input[input[pos+1]]) 25 | elif mode_c == "1": 26 | values.append(input[pos+1]) 27 | elif mode_c == "2": 28 | values.append(input[input[pos+1]+game.rel_base]) 29 | 30 | if op in ["01", "02", "05", "06", "07", "08"]: 31 | if mode_b == "0": 32 | values.append(input[input[pos+2]]) 33 | elif mode_b == "1": 34 | values.append(input[pos+2]) 35 | elif mode_b == "2": 36 | values.append(input[input[pos+2]+game.rel_base]) 37 | 38 | if op in []: 39 | if mode_a == "0": 40 | values.append(input[input[pos+3]]) 41 | elif mode_a == "1": 42 | values.append(input[pos+3]) 43 | elif mode_a == "2": 44 | values.append(input[input[pos+3]+game.rel_base]) 45 | 46 | if op in ["01", "02", "07", "08"]: 47 | if mode_a == "2": 48 | offset = game.rel_base 49 | 50 | if op in ["03"]: 51 | if mode_c == "2": 52 | offset = game.rel_base 53 | 54 | return values, offset 55 | 56 | def send_input(game, input): 57 | game.input.extend(input) 58 | 59 | def read_output(game): 60 | if len(game.output): 61 | return game.output.popleft() 62 | return None 63 | 64 | def run_game(game): 65 | if game.prog[game.ip] != 99: 66 | op, modes = split_instruction(game.prog[game.ip]) 67 | values, offset = get_values(game.prog, game.ip, op, modes, game) 68 | 69 | if op == "01": # Addition 70 | game.prog[game.prog[game.ip+3] + offset] = values[0] + values[1] 71 | game.ip += 4 72 | 73 | if op == "02": # Multiplication 74 | game.prog[game.prog[game.ip+3] + offset] = values[0] * values[1] 75 | game.ip += 4 76 | 77 | if op == "03": # Read and Store input 78 | if len(game.input): 79 | game.prog[game.prog[game.ip+1] + offset] = game.input.popleft() 80 | else: 81 | game.prog[game.prog[game.ip+1] + offset] = -1 82 | game.ip += 2 83 | 84 | if op == "04": # Print Output 85 | game.output.append(values[0]) 86 | game.ip += 2 87 | return 88 | 89 | if op == "05": # Jump-if-True 90 | if values[0]: 91 | game.ip = values[1] 92 | else: 93 | game.ip += 3 94 | 95 | if op == "06": # Jump-if-False 96 | if not values[0]: 97 | game.ip = values[1] 98 | else: 99 | game.ip += 3 100 | 101 | if op == "07": # Less than 102 | if values[0] < values[1]: 103 | game.prog[game.prog[game.ip+3] + offset] = 1 104 | else: 105 | game.prog[game.prog[game.ip+3] + offset] = 0 106 | game.ip += 4 107 | 108 | if op == "08": # Equals 109 | if values[0] == values[1]: 110 | game.prog[game.prog[game.ip+3] + offset] = 1 111 | else: 112 | game.prog[game.prog[game.ip+3] + offset] = 0 113 | game.ip += 4 114 | 115 | if op == "09": # Adjust Relative Base 116 | game.rel_base += values[0] 117 | game.ip += 2 118 | else: 119 | game.halt = True 120 | 121 | def create_program(input): 122 | prog = defaultdict(int) 123 | 124 | for i in range(len(input)): 125 | prog[i] = int(input[i]) 126 | 127 | return prog 128 | 129 | def create_network(input): 130 | network, network_queue = [], [] 131 | 132 | for network_address in range(50): 133 | prog = create_program(input) 134 | game = Game(prog) 135 | send_input(game, [network_address]) 136 | network.append(game) 137 | network_queue.append([]) 138 | 139 | return network, network_queue 140 | 141 | def find_first_nat_package(network, network_queue): 142 | while True: 143 | for network_address in range(50): 144 | run_game(network[network_address]) 145 | if (output := read_output(network[network_address])): 146 | network_queue[network_address].append(output) 147 | if len(network_queue[network_address]) == 3: 148 | if network_queue[network_address][0] == 255: 149 | return network_queue[network_address] 150 | send_input(network[network_queue[network_address][0]], network_queue[network_address][1:]) 151 | network_queue[network_address] = [] 152 | 153 | @timer 154 | def solve(): 155 | input = read_file("23")[0].split(",") 156 | network, network_queue = create_network(input) 157 | 158 | return find_first_nat_package(network, network_queue)[2] 159 | 160 | result = solve() 161 | print(f"Solution: {result}") -------------------------------------------------------------------------------- /2019_23_p2.py: -------------------------------------------------------------------------------- 1 | from aoc import read_file, timer 2 | from collections import defaultdict, deque 3 | 4 | class Game: 5 | def __init__(self, prog): 6 | self.prog = prog 7 | self.ip = 0 8 | self.input = deque() 9 | self.output = deque() 10 | self.rel_base = 0 11 | self.halt = False 12 | self.is_waiting = False 13 | 14 | def split_instruction(instruction): 15 | instruction = f"{instruction:05}" 16 | return instruction[3:], instruction[0:3] 17 | 18 | def get_values(input, pos, op, modes, game): 19 | mode_a, mode_b, mode_c = modes 20 | values = [] 21 | offset = 0 22 | 23 | if op in ["01", "02", "04", "05", "06", "07", "08", "09"]: 24 | if mode_c == "0": 25 | values.append(input[input[pos+1]]) 26 | elif mode_c == "1": 27 | values.append(input[pos+1]) 28 | elif mode_c == "2": 29 | values.append(input[input[pos+1]+game.rel_base]) 30 | 31 | if op in ["01", "02", "05", "06", "07", "08"]: 32 | if mode_b == "0": 33 | values.append(input[input[pos+2]]) 34 | elif mode_b == "1": 35 | values.append(input[pos+2]) 36 | elif mode_b == "2": 37 | values.append(input[input[pos+2]+game.rel_base]) 38 | 39 | if op in []: 40 | if mode_a == "0": 41 | values.append(input[input[pos+3]]) 42 | elif mode_a == "1": 43 | values.append(input[pos+3]) 44 | elif mode_a == "2": 45 | values.append(input[input[pos+3]+game.rel_base]) 46 | 47 | if op in ["01", "02", "07", "08"]: 48 | if mode_a == "2": 49 | offset = game.rel_base 50 | 51 | if op in ["03"]: 52 | if mode_c == "2": 53 | offset = game.rel_base 54 | 55 | return values, offset 56 | 57 | def send_input(game, input): 58 | game.input.extend(input) 59 | 60 | def read_output(game): 61 | if len(game.output): 62 | return game.output.popleft() 63 | return None 64 | 65 | def run_game(game): 66 | if game.prog[game.ip] != 99: 67 | op, modes = split_instruction(game.prog[game.ip]) 68 | values, offset = get_values(game.prog, game.ip, op, modes, game) 69 | 70 | if op == "01": # Addition 71 | game.prog[game.prog[game.ip+3] + offset] = values[0] + values[1] 72 | game.ip += 4 73 | 74 | if op == "02": # Multiplication 75 | game.prog[game.prog[game.ip+3] + offset] = values[0] * values[1] 76 | game.ip += 4 77 | 78 | if op == "03": # Read and Store input 79 | if len(game.input): 80 | game.prog[game.prog[game.ip+1] + offset] = game.input.popleft() 81 | game.is_waiting = False 82 | else: 83 | game.prog[game.prog[game.ip+1] + offset] = -1 84 | game.is_waiting = True 85 | game.ip += 2 86 | 87 | if op == "04": # Print Output 88 | game.output.append(values[0]) 89 | game.ip += 2 90 | return 91 | 92 | if op == "05": # Jump-if-True 93 | if values[0]: 94 | game.ip = values[1] 95 | else: 96 | game.ip += 3 97 | 98 | if op == "06": # Jump-if-False 99 | if not values[0]: 100 | game.ip = values[1] 101 | else: 102 | game.ip += 3 103 | 104 | if op == "07": # Less than 105 | if values[0] < values[1]: 106 | game.prog[game.prog[game.ip+3] + offset] = 1 107 | else: 108 | game.prog[game.prog[game.ip+3] + offset] = 0 109 | game.ip += 4 110 | 111 | if op == "08": # Equals 112 | if values[0] == values[1]: 113 | game.prog[game.prog[game.ip+3] + offset] = 1 114 | else: 115 | game.prog[game.prog[game.ip+3] + offset] = 0 116 | game.ip += 4 117 | 118 | if op == "09": # Adjust Relative Base 119 | game.rel_base += values[0] 120 | game.ip += 2 121 | else: 122 | game.halt = True 123 | 124 | def create_program(input): 125 | prog = defaultdict(int) 126 | 127 | for i in range(len(input)): 128 | prog[i] = int(input[i]) 129 | 130 | return prog 131 | 132 | def create_network(input): 133 | network, network_queue = [], [] 134 | 135 | for network_address in range(50): 136 | prog = create_program(input) 137 | game = Game(prog) 138 | send_input(game, [network_address]) 139 | network.append(game) 140 | network_queue.append([]) 141 | 142 | return network, network_queue 143 | 144 | def is_idle(network, network_queue): 145 | for network_address in range(50): 146 | if len(network_queue[network_address]) or \ 147 | not network[network_address].is_waiting: 148 | return False 149 | return True 150 | 151 | def find_double_nat_y(network, network_queue): 152 | nat, last_nat = [], None 153 | 154 | while True: 155 | for network_address in range(50): 156 | run_game(network[network_address]) 157 | if (output := read_output(network[network_address])): 158 | network_queue[network_address].append(output) 159 | if len(network_queue[network_address]) == 3: 160 | if network_queue[network_address][0] == 255: 161 | nat = network_queue[network_address][1:] 162 | else: 163 | send_input(network[network_queue[network_address][0]], network_queue[network_address][1:]) 164 | network_queue[network_address] = [] 165 | 166 | if is_idle(network, network_queue) and len(nat): 167 | if nat[1] == last_nat: 168 | return last_nat 169 | send_input(network[0], nat) 170 | last_nat, nat = nat[1], [] 171 | 172 | @timer 173 | def solve(): 174 | input = read_file("23")[0].split(",") 175 | network, network_queue = create_network(input) 176 | return find_double_nat_y(network, network_queue) 177 | 178 | result = solve() 179 | print(f"Solution: {result}") -------------------------------------------------------------------------------- /2019_24_p1.py: -------------------------------------------------------------------------------- 1 | from aoc import read_file, timer 2 | 3 | def num_neighbors(field, pos): 4 | count = 0 5 | for side in [(0, -1), (-1, 0), (0, 1), (1, 0)]: 6 | x, y = pos[1] + side[1], pos[0] + side[0] 7 | if x >= 0 and x <= 4 and \ 8 | y >= 0 and y <= 4 and \ 9 | field[y][x] == "#": 10 | count += 1 11 | return count 12 | 13 | def evolve(field): 14 | new_field = [["." for x in range(5)] for y in range(5)] 15 | 16 | for y in range(5): 17 | for x in range(5): 18 | if field[y][x] == "#": 19 | if num_neighbors(field, (y, x)) == 1: 20 | new_field[y][x] = "#" 21 | elif num_neighbors(field, (y, x)) == 1 or \ 22 | num_neighbors(field, (y, x)) == 2: 23 | new_field[y][x] = "#" 24 | 25 | return new_field 26 | 27 | def bio_diversity(field): 28 | result, multi = 0, 1 29 | 30 | for y in range(5): 31 | for x in range(5): 32 | if field[y][x] == "#": 33 | result += multi 34 | multi *= 2 35 | return result 36 | 37 | @timer 38 | def solve(): 39 | field = read_file("24") 40 | known = set() 41 | 42 | while (bio := bio_diversity(field)) not in known: 43 | known.add(bio) 44 | field = evolve(field) 45 | 46 | return bio 47 | 48 | result = solve() 49 | print(f"Solution: {result}") -------------------------------------------------------------------------------- /2019_24_p2.py: -------------------------------------------------------------------------------- 1 | from aoc import read_file, timer 2 | 3 | def num_below(field, level, pos): 4 | if pos[0] == 1: 5 | return sum(field[level-1][0][x] == "#" for x in range(5)) 6 | 7 | if pos[0] == 3: 8 | return sum(field[level-1][4][x] == "#" for x in range(5)) 9 | 10 | if pos[1] == 1: 11 | return sum(field[level-1][y][0] == "#" for y in range(5)) 12 | 13 | if pos[1] == 3: 14 | return sum(field[level-1][y][4] == "#" for y in range(5)) 15 | 16 | 17 | 18 | def num_neighbors(field, level, pos): 19 | count = 0 20 | 21 | for side in [(0, -1), (-1, 0), (0, 1), (1, 0)]: 22 | new_pos = (pos[0] + side[0], pos[1] + side[1]) 23 | 24 | if new_pos[0] == 2 and new_pos[1] == 2: 25 | count += num_below(field, level, pos) 26 | 27 | elif new_pos[0] == -1: 28 | if field[level+1][1][2] == "#": 29 | count += 1 30 | 31 | elif new_pos[0] == 5: 32 | if field[level+1][3][2] == "#": 33 | count += 1 34 | 35 | elif new_pos[1] == -1: 36 | if field[level+1][2][1] == "#": 37 | count += 1 38 | 39 | elif new_pos[1] == 5: 40 | if field[level+1][2][3] == "#": 41 | count += 1 42 | 43 | elif field[level][new_pos[0]][new_pos[1]] == "#": 44 | count += 1 45 | 46 | return count 47 | 48 | def evolve(field, iterations): 49 | new_field = [[["." for x in range(5)] for y in range(5)] for z in range(iterations*2+3)] 50 | 51 | for level in range(iterations*2+1): 52 | for y in range(5): 53 | for x in range(5): 54 | if x == 2 and y == 2: 55 | continue 56 | 57 | if field[level][y][x] == "#": 58 | if num_neighbors(field, level, (y, x)) == 1: 59 | new_field[level][y][x] = "#" 60 | 61 | else: 62 | if num_neighbors(field, level, (y, x)) == 1 or num_neighbors(field, level, (y, x)) == 2: 63 | new_field[level][y][x] = "#" 64 | 65 | return new_field 66 | 67 | @timer 68 | def solve(): 69 | input = read_file("24") 70 | iterations = 200 71 | field = [[["." for x in range(5)] for y in range(5)] for z in range(iterations*2+3)] 72 | 73 | for y in range(5): 74 | for x in range(5): 75 | field[iterations+1][y][x] = input[y][x] 76 | 77 | for step in range(iterations): 78 | field = evolve(field, iterations) 79 | 80 | return sum(field[level][y][x] == "#" for level in range(iterations*2+3) for y in range(5) for x in range(5)) 81 | 82 | result = solve() 83 | print(f"Solution: {result}") -------------------------------------------------------------------------------- /2019_25_p1.py: -------------------------------------------------------------------------------- 1 | from aoc import read_file, timer 2 | from collections import defaultdict, deque 3 | 4 | class Game: 5 | def __init__(self, prog): 6 | self.prog = prog 7 | self.ip = 0 8 | self.input = deque() 9 | self.output = deque() 10 | self.rel_base = 0 11 | self.halt = False 12 | 13 | def split_instruction(instruction): 14 | instruction = f"{instruction:05}" 15 | return instruction[3:], instruction[0:3] 16 | 17 | def get_values(input, pos, op, modes, game): 18 | mode_a, mode_b, mode_c = modes 19 | values = [] 20 | offset = 0 21 | 22 | if op in ["01", "02", "04", "05", "06", "07", "08", "09"]: 23 | if mode_c == "0": 24 | values.append(input[input[pos+1]]) 25 | elif mode_c == "1": 26 | values.append(input[pos+1]) 27 | elif mode_c == "2": 28 | values.append(input[input[pos+1]+game.rel_base]) 29 | 30 | if op in ["01", "02", "05", "06", "07", "08"]: 31 | if mode_b == "0": 32 | values.append(input[input[pos+2]]) 33 | elif mode_b == "1": 34 | values.append(input[pos+2]) 35 | elif mode_b == "2": 36 | values.append(input[input[pos+2]+game.rel_base]) 37 | 38 | if op in []: 39 | if mode_a == "0": 40 | values.append(input[input[pos+3]]) 41 | elif mode_a == "1": 42 | values.append(input[pos+3]) 43 | elif mode_a == "2": 44 | values.append(input[input[pos+3]+game.rel_base]) 45 | 46 | if op in ["01", "02", "07", "08"]: 47 | if mode_a == "2": 48 | offset = game.rel_base 49 | 50 | if op in ["03"]: 51 | if mode_c == "2": 52 | offset = game.rel_base 53 | 54 | return values, offset 55 | 56 | def send_input(game, input): 57 | game.input.extend(input) 58 | 59 | def read_output(game): 60 | if len(game.output): 61 | return game.output.popleft() 62 | return None 63 | 64 | def run_game(game): 65 | if game.prog[game.ip] != 99: 66 | op, modes = split_instruction(game.prog[game.ip]) 67 | values, offset = get_values(game.prog, game.ip, op, modes, game) 68 | 69 | if op == "01": # Addition 70 | game.prog[game.prog[game.ip+3] + offset] = values[0] + values[1] 71 | game.ip += 4 72 | 73 | if op == "02": # Multiplication 74 | game.prog[game.prog[game.ip+3] + offset] = values[0] * values[1] 75 | game.ip += 4 76 | 77 | if op == "03": # Read and Store input 78 | if len(game.input): 79 | game.prog[game.prog[game.ip+1] + offset] = game.input.popleft() 80 | else: 81 | game.prog[game.prog[game.ip+1] + offset] = -1 82 | game.ip += 2 83 | 84 | if op == "04": # Print Output 85 | game.output.append(values[0]) 86 | game.ip += 2 87 | return 88 | 89 | if op == "05": # Jump-if-True 90 | if values[0]: 91 | game.ip = values[1] 92 | else: 93 | game.ip += 3 94 | 95 | if op == "06": # Jump-if-False 96 | if not values[0]: 97 | game.ip = values[1] 98 | else: 99 | game.ip += 3 100 | 101 | if op == "07": # Less than 102 | if values[0] < values[1]: 103 | game.prog[game.prog[game.ip+3] + offset] = 1 104 | else: 105 | game.prog[game.prog[game.ip+3] + offset] = 0 106 | game.ip += 4 107 | 108 | if op == "08": # Equals 109 | if values[0] == values[1]: 110 | game.prog[game.prog[game.ip+3] + offset] = 1 111 | else: 112 | game.prog[game.prog[game.ip+3] + offset] = 0 113 | game.ip += 4 114 | 115 | if op == "09": # Adjust Relative Base 116 | game.rel_base += values[0] 117 | game.ip += 2 118 | else: 119 | game.halt = True 120 | 121 | def create_program(input): 122 | prog = defaultdict(int) 123 | 124 | for i in range(len(input)): 125 | prog[i] = int(input[i]) 126 | 127 | return prog 128 | 129 | def read_prompt(game, fin = False): 130 | output = None 131 | 132 | while output != ord("?"): 133 | while not (output := read_output(game)): 134 | if game.halt: 135 | return 136 | run_game(game) 137 | 138 | print(chr(output), end = "") 139 | 140 | 141 | @timer 142 | def solve(): 143 | input = read_file("25")[0].split(",") 144 | prog = create_program(input) 145 | game = Game(prog) 146 | 147 | instructions = [] 148 | instructions.append("south\n") 149 | instructions.append("take mouse\n") 150 | instructions.append("north\n") 151 | instructions.append("west\n") 152 | instructions.append("north\n") 153 | instructions.append("north\n") 154 | instructions.append("") 155 | instructions.append("west\n") 156 | instructions.append("take semiconductor\n") 157 | instructions.append("east\n") 158 | instructions.append("") 159 | instructions.append("south\n") 160 | instructions.append("west\n") 161 | instructions.append("south\n") 162 | instructions.append("take hypercube\n") 163 | instructions.append("north\n") 164 | instructions.append("east\n") 165 | instructions.append("south\n") 166 | instructions.append("west\n") 167 | instructions.append("take antenna\n") 168 | instructions.append("west\n") 169 | instructions.append("south\n") 170 | instructions.append("south\n") 171 | instructions.append("south\n") 172 | 173 | for instruction in instructions: 174 | read_prompt(game) 175 | send_input(game, [ord(c) for c in instruction]) 176 | print(f"\n\n{instruction}") 177 | 178 | read_prompt(game, fin = True) 179 | 180 | solve() -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2019 Thomas Kerbl 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Advent of Code 2019 2 | My [Advent of Code](https://adventofcode.com/2019) (Season 2019) solutions written in Python 3.8. I will highlight some of the interesting Python mechanisms I am using on Twitter, so feel free to [follow me](https://twitter.com/Dementophobia). 3 | 4 | | Puzzle | Solution | Tips & Tricks | 5 | | ---------------------------------------------- | ------------------------------------------------------------ | ------------------------------------------------------------ | 6 | | [Day 1](https://adventofcode.com/2019/day/1) | [Part 1](./2019_01_p1.py) and [Part 2](./2019_01_p2.py) | [Assignment Expressions](https://twitter.com/Dementophobia/status/1201027632349040640) | 7 | | [Day 2](https://adventofcode.com/2019/day/2) | [Part 1](./2019_02_p1.py) and [Part 2](./2019_02_p2.py) | [Slicing Notation](https://twitter.com/Dementophobia/status/1201382006774468608) | 8 | | [Day 3](https://adventofcode.com/2019/day/3) | [Part 1](./2019_03_p1.py) and [Part 2](./2019_03_p2.py) | [List Comprehension](https://twitter.com/Dementophobia/status/1201749348083781632) | 9 | | [Day 4](https://adventofcode.com/2019/day/4) | [Part 1](./2019_04_p1.py) and [Part 2](./2019_04_p2.py) | [Short Circuiting](https://twitter.com/Dementophobia/status/1202108904429309952) | 10 | | [Day 5](https://adventofcode.com/2019/day/5) | [Part 1](./2019_05_p1.py) and [Part 2](./2019_05_p2.py) | [Zero Padding with F-Strings](https://twitter.com/Dementophobia/status/1202487898194546689) | 11 | | [Day 6](https://adventofcode.com/2019/day/6) | [Part 1](./2019_06_p1.py) and [Part 2](./2019_06_p2.py) | [Intersection of Sets](https://twitter.com/Dementophobia/status/1202848979328876546) | 12 | | [Day 7](https://adventofcode.com/2019/day/7) | [Part 1](./2019_07_p1.py) and [Part 2](./2019_07_p2.py) | [Permutations from Itertools](https://twitter.com/Dementophobia/status/1203214917697970178) | 13 | | [Day 8](https://adventofcode.com/2019/day/8) | [Part 1](./2019_08_p1.py) and [Part 2](./2019_08_p2.py)
Bonus: [Animated Solution](./extras/README.md#day-8---animation-using-python-and-gimp) | [Avoiding Line Breaks with Print](https://twitter.com/Dementophobia/status/1203560697940119553) | 14 | | [Day 9](https://adventofcode.com/2019/day/9) | [Part 1](./2019_09_p1.py) and [Part 2](./2019_09_p2.py) | [Defaultdict from Collections](https://twitter.com/Dementophobia/status/1203932274280022017) | 15 | | [Day 10](https://adventofcode.com/2019/day/10) | [Part 1](./2019_10_p1.py) and [Part 2](./2019_10_p2.py) | [Sorting with Function as Key](https://twitter.com/Dementophobia/status/1204468347917783042) | 16 | | [Day 11](https://adventofcode.com/2019/day/11) | [Part 1](./2019_11_p1.py) and [Part 2](./2019_11_p2.py)
Bonus: [Animated Solution](./extras/README.md#day-11---another-animation-using-python-and-gimp) | [Using Modulo for Turning](https://twitter.com/Dementophobia/status/1204657448361086976) | 17 | | [Day 12](https://adventofcode.com/2019/day/12) | [Part 1](./2019_12_p1.py) and [Part 2](./2019_12_p2.py) | [Regex based Integer Extractor](https://twitter.com/Dementophobia/status/1205239170219814934) | 18 | | [Day 13](https://adventofcode.com/2019/day/13) | [Part 1](./2019_13_p1.py) and [Part 2](./2019_13_p2.py) | - | 19 | | [Day 14](https://adventofcode.com/2019/day/14) | [Part 1](./2019_14_p1.py) and [Part 2](./2019_14_p2.py) | - | 20 | | [Day 15](https://adventofcode.com/2019/day/15) | [Part 1](./2019_15_p1.py) and [Part 2](./2019_15_p2.py)
Bonus: [Animated Solution](./extras/README.md#day-15---flooding-the-area-with-oxygen) | [Calling Function from List](https://twitter.com/Dementophobia/status/1206182646289780742) | 21 | | [Day 16](https://adventofcode.com/2019/day/16) | [Part 1](./2019_16_p1.py) and [Part 2](./2019_16_p2.py) | [Using Deques for Shifting](https://twitter.com/Dementophobia/status/1206619272946036736) | 22 | | [Day 17](https://adventofcode.com/2019/day/17) | [Part 1](./2019_17_p1.py) and [Part 2](./2019_17_p2.py) | - | 23 | | [Day 18](https://adventofcode.com/2019/day/18) | [Part 1](./2019_18_p1.py) and [Part 2](./2019_18_p2.py) | - | 24 | | [Day 19](https://adventofcode.com/2019/day/19) | [Part 1](./2019_19_p1.py) and [Part 2](./2019_19_p2.py) | - | 25 | | [Day 20](https://adventofcode.com/2019/day/20) | [Part 1](./2019_20_p1.py) and [Part 2](./2019_20_p2.py) | - | 26 | | [Day 21](https://adventofcode.com/2019/day/21) | [Part 1](./2019_21_p1.py) and [Part 2](./2019_21_p2.py) | - | 27 | | [Day 22](https://adventofcode.com/2019/day/22) | [Part 1](./2019_22_p1.py) and [Part 2](./2019_22_p2.py) | [Calculating the Modular Multiplicative Inverse](https://twitter.com/Dementophobia/status/1208778678710222848) | 28 | | [Day 23](https://adventofcode.com/2019/day/23) | [Part 1](./2019_23_p1.py) and [Part 2](./2019_23_p2.py)
Bonus: [Animated Solution](./extras/README.md#day-23---network-analysis) | - | 29 | | [Day 24](https://adventofcode.com/2019/day/24) | [Part 1](./2019_24_p1.py) and [Part 2](./2019_24_p2.py) | [Counting with List Comprehensions](https://twitter.com/Dementophobia/status/1209368903253708800) | 30 | | [Day 25](https://adventofcode.com/2019/day/25) | [Part 1](./2019_25_p1.py) | - | 31 | 32 | -------------------------------------------------------------------------------- /aoc.py: -------------------------------------------------------------------------------- 1 | import time 2 | 3 | def read_file(name, strip = True): 4 | with open("files/input" + name) as f: 5 | content = f.readlines() 6 | if strip: 7 | return [x.strip() for x in content] 8 | return content 9 | 10 | def timer(func): 11 | def wrapper(*args, **kwargs): 12 | start_time = time.time() 13 | result = func(*args, **kwargs) 14 | print(f"\nTime required: {(time.time() - start_time)*1000:.2f} ms\n") 15 | return result 16 | return wrapper -------------------------------------------------------------------------------- /extras/README.md: -------------------------------------------------------------------------------- 1 | # Advent of Code 2019 Extras 2 | This space highlight some of the more creative solutions I designed on top of the straight forward solutions in the [main section](../README.md), including additional information and showcases. 3 | 4 | ## Day 8 - Animation using Python and Gimp 5 | 6 | Part 2 of day 8 required mashing together a bunch of layers to get to the final solution. While this can be done in code alone, I decided to solve the puzzle with an animated GIF. My [python script](../2019_08_animation.py) creates a transparent image for each layer and saves it to the disk (in ./images/, which has to be created manually in advance, if you want to try it yourself). 7 | 8 | Afterwards, all you have to do is import the result in Gimp, tinker with the background and the timing as you please, and save it as animated GIF. 9 | 10 | Here is the result for my input: 11 | 12 |

13 | 14 | 15 | ## Day 11 - Another Animation using Python and Gimp 16 | 17 | I could reuse some of my code from day 8 to create an animation for day 11 as well. Again, I used my [python script](../2019_11_animation.py) to generate the individual images and did the rest with Gimp. 18 | 19 | Watch my little robot paint the hull: 20 | 21 |

22 | 23 | ## Day 15 - Flooding the Area with Oxygen 24 | 25 | Still sticking to my guns with Python and Gimp. Today my [python script](../2019_15_animation.py) floods the base with oxygen: 26 | 27 |

28 | 29 | 30 | 31 | ## Day 23 - Network Analysis 32 | 33 | It is time for one more animation. Watch my [python script](../2019_23_animation.py) analyze the network load distribution in our virtual IntCode network: 34 | 35 |

36 | 37 | 38 | 39 | # About the Author 40 | 41 | If you like my work, follow me on [Twitter](https://twitter.com/Dementophobia), so that you won't miss any new solutions that I publish. You can also drop me a message there, to get in contact with me. -------------------------------------------------------------------------------- /extras/day_11_hull.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Dementophobia/advent-of-code-2019/efdbf28ac986195a1b79ce97a787d9f15d1336e7/extras/day_11_hull.gif -------------------------------------------------------------------------------- /extras/day_15_area.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Dementophobia/advent-of-code-2019/efdbf28ac986195a1b79ce97a787d9f15d1336e7/extras/day_15_area.gif -------------------------------------------------------------------------------- /extras/day_23_network.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Dementophobia/advent-of-code-2019/efdbf28ac986195a1b79ce97a787d9f15d1336e7/extras/day_23_network.gif -------------------------------------------------------------------------------- /extras/day_8_bios.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Dementophobia/advent-of-code-2019/efdbf28ac986195a1b79ce97a787d9f15d1336e7/extras/day_8_bios.gif -------------------------------------------------------------------------------- /files/input01: -------------------------------------------------------------------------------- 1 | 51753 2 | 53456 3 | 128133 4 | 118219 5 | 136490 6 | 113318 7 | 134001 8 | 99775 9 | 84746 10 | 68712 11 | 104274 12 | 72530 13 | 101517 14 | 65533 15 | 98719 16 | 100215 17 | 144296 18 | 114166 19 | 62930 20 | 118494 21 | 144800 22 | 97604 23 | 112836 24 | 73074 25 | 62591 26 | 99278 27 | 94544 28 | 73035 29 | 146631 30 | 148331 31 | 144573 32 | 121956 33 | 94088 34 | 60092 35 | 126397 36 | 117285 37 | 122292 38 | 77413 39 | 145860 40 | 76968 41 | 64790 42 | 58479 43 | 94035 44 | 148441 45 | 78999 46 | 74329 47 | 145182 48 | 129497 49 | 106765 50 | 67046 51 | 58702 52 | 123344 53 | 63866 54 | 121123 55 | 126808 56 | 115190 57 | 86467 58 | 136359 59 | 148718 60 | 88225 61 | 126185 62 | 82745 63 | 142546 64 | 149788 65 | 137524 66 | 114690 67 | 68075 68 | 60244 69 | 127157 70 | 123719 71 | 87843 72 | 107714 73 | 51281 74 | 92123 75 | 146495 76 | 50761 77 | 130708 78 | 53103 79 | 75289 80 | 121675 81 | 61726 82 | 70674 83 | 101755 84 | 97736 85 | 100141 86 | 81085 87 | 55493 88 | 73071 89 | 85321 90 | 119965 91 | 147313 92 | 105201 93 | 107107 94 | 130007 95 | 67834 96 | 137614 97 | 140848 98 | 64038 99 | 106078 100 | 71447 101 | -------------------------------------------------------------------------------- /files/input02: -------------------------------------------------------------------------------- 1 | 1,0,0,3,1,1,2,3,1,3,4,3,1,5,0,3,2,1,6,19,1,9,19,23,2,23,10,27,1,27,5,31,1,31,6,35,1,6,35,39,2,39,13,43,1,9,43,47,2,9,47,51,1,51,6,55,2,55,10,59,1,59,5,63,2,10,63,67,2,9,67,71,1,71,5,75,2,10,75,79,1,79,6,83,2,10,83,87,1,5,87,91,2,9,91,95,1,95,5,99,1,99,2,103,1,103,13,0,99,2,14,0,0 2 | -------------------------------------------------------------------------------- /files/input03: -------------------------------------------------------------------------------- 1 | R991,U77,L916,D26,R424,D739,L558,D439,R636,U616,L364,D653,R546,U909,L66,D472,R341,U906,L37,D360,L369,D451,L649,D521,R2,U491,R409,U801,R23,U323,L209,U171,L849,D891,L854,U224,R476,D519,L937,U345,R722,D785,L312,D949,R124,U20,R677,D236,R820,D320,L549,D631,R42,U621,R760,U958,L925,U84,R914,U656,R598,D610,R397,D753,L109,U988,R435,U828,R219,U583,L317,D520,L940,D850,R594,D801,L422,U292,R883,U204,L76,U860,L753,U483,L183,U179,R441,U163,L859,U437,L485,D239,R454,D940,R689,D704,R110,D12,R370,D413,L192,D979,R990,D651,L308,U177,R787,D717,R245,U689,R11,D509,L680,U228,L347,D179,R508,D40,L502,U689,L643,U45,R884,D653,L23,D918,L825,D312,L691,U292,L285,D183,R997,U427,L89,U252,R475,U217,R16,U749,L578,D931,L273,U509,L741,U97,R407,U275,L605,U136,L558,U318,R478,U505,R446,U295,R562,D646,R988,D254,L68,U645,L953,U916,L442,D713,R978,U540,R447,U594,L804,U215,R95,D995,R818,D237,R212,U664,R455,D684,L338,U308,R463,D985,L988,D281,R758,U510,L232,U509,R289,D90,R65,D46,R886,D741,L327,U755,R236,U870,L764,U60,R391,U91,R367,U587,L651,D434,L47,U954,R707,D336,L242,D387,L410,D19,R203,D703,L228,U292,L19,U916,R411,U421,L726,U543,L240,U755,R157,U836,L397,U71,L125,D934,L723,D145,L317,D229,R863,U941,L926,D55,L2,D452,R895,D670,L216,U504,R66,U696,L581,U75,L235,U88,L609,U415,L850,U21,L109,U416,R408,D367,R823,D199,L718,U136,L860,U780,L308,D312,R230,D671,R477,D672,L94,U307,R301,D143,L300,D792,L593,D399,R840,D225,R680,D484,L646,D917,R132,D213,L779,D143,L176,U673,L772,D93,L10,D624,L244,D993,R346 2 | L997,U989,L596,U821,L419,U118,R258,D239,R902,D810,R553,D271,R213,D787,R723,D57,L874,D556,R53,U317,L196,D813,R500,U151,R180,D293,L415,U493,L99,U482,R517,U649,R102,U860,R905,D499,R133,D741,R394,U737,L903,U800,R755,D376,L11,U751,R539,U33,R539,U30,L534,D631,L714,U190,L446,U409,R977,D731,R282,U244,R29,D212,L523,D570,L89,D327,R178,U970,R435,U250,R213,D604,R64,D348,R315,D994,L508,D261,R62,D50,L347,U183,R410,D627,L128,U855,L803,D695,L879,U857,L629,D145,L341,D733,L566,D626,L302,U236,L55,U428,R183,U254,R226,D228,R616,U137,L593,U204,R620,U624,R605,D705,L263,D568,R931,D464,R989,U621,L277,U274,L137,U768,L261,D360,L45,D110,R35,U212,L271,D318,L444,D427,R225,D380,L907,D193,L118,U741,L101,D298,R604,D598,L98,U458,L733,U511,L82,D173,L644,U803,R926,D610,R24,D170,L198,U766,R656,D474,L393,D934,L789,U92,L889,U460,L232,U193,L877,D380,L455,D526,R899,D696,R452,U95,L828,D720,R370,U664,L792,D204,R84,D749,R808,U132,L152,D375,R19,U164,L615,D121,R644,D289,R381,U126,L304,U508,L112,D268,L572,D838,L998,U127,R500,D344,R694,U451,L846,D565,R158,U47,L430,U214,R571,D983,R690,D227,L107,U109,L286,D66,L544,U205,L453,U716,L36,U672,L517,U878,L487,U936,L628,U253,R424,D409,R422,U636,R412,U553,R59,D332,R7,U495,L305,D939,L428,D821,R749,D195,R531,D898,R337,D303,L398,D625,R57,D503,L699,D553,L478,U716,R897,D3,R420,U903,R994,U864,L745,U205,R229,U126,L227,D454,R670,U605,L356,U499,R510,U238,L542,D440,R156,D512,L237,D341,L439,U642,R873,D650,R871,D616,R322,U696,R248,D746,R990,U829,R812,U294,L462,U740,R780 3 | -------------------------------------------------------------------------------- /files/input04: -------------------------------------------------------------------------------- 1 | 124075-580769 2 | -------------------------------------------------------------------------------- /files/input05: -------------------------------------------------------------------------------- 1 | 3,225,1,225,6,6,1100,1,238,225,104,0,1002,92,42,224,1001,224,-3444,224,4,224,102,8,223,223,101,4,224,224,1,224,223,223,1102,24,81,225,1101,89,36,224,101,-125,224,224,4,224,102,8,223,223,101,5,224,224,1,224,223,223,2,118,191,224,101,-880,224,224,4,224,1002,223,8,223,1001,224,7,224,1,224,223,223,1102,68,94,225,1101,85,91,225,1102,91,82,225,1102,85,77,224,101,-6545,224,224,4,224,1002,223,8,223,101,7,224,224,1,223,224,223,1101,84,20,225,102,41,36,224,101,-3321,224,224,4,224,1002,223,8,223,101,7,224,224,1,223,224,223,1,188,88,224,101,-183,224,224,4,224,1002,223,8,223,1001,224,7,224,1,224,223,223,1001,84,43,224,1001,224,-137,224,4,224,102,8,223,223,101,4,224,224,1,224,223,223,1102,71,92,225,1101,44,50,225,1102,29,47,225,101,7,195,224,101,-36,224,224,4,224,102,8,223,223,101,6,224,224,1,223,224,223,4,223,99,0,0,0,677,0,0,0,0,0,0,0,0,0,0,0,1105,0,99999,1105,227,247,1105,1,99999,1005,227,99999,1005,0,256,1105,1,99999,1106,227,99999,1106,0,265,1105,1,99999,1006,0,99999,1006,227,274,1105,1,99999,1105,1,280,1105,1,99999,1,225,225,225,1101,294,0,0,105,1,0,1105,1,99999,1106,0,300,1105,1,99999,1,225,225,225,1101,314,0,0,106,0,0,1105,1,99999,107,677,677,224,1002,223,2,223,1006,224,329,1001,223,1,223,1108,226,677,224,102,2,223,223,1006,224,344,101,1,223,223,1107,226,226,224,1002,223,2,223,1006,224,359,101,1,223,223,8,677,226,224,1002,223,2,223,1006,224,374,1001,223,1,223,1107,677,226,224,102,2,223,223,1005,224,389,1001,223,1,223,1008,677,677,224,1002,223,2,223,1006,224,404,1001,223,1,223,108,677,677,224,102,2,223,223,1005,224,419,1001,223,1,223,1107,226,677,224,102,2,223,223,1006,224,434,101,1,223,223,1008,226,226,224,1002,223,2,223,1006,224,449,1001,223,1,223,107,226,226,224,102,2,223,223,1006,224,464,1001,223,1,223,1007,677,226,224,1002,223,2,223,1006,224,479,1001,223,1,223,1108,226,226,224,102,2,223,223,1006,224,494,1001,223,1,223,8,226,226,224,1002,223,2,223,1005,224,509,1001,223,1,223,7,226,677,224,102,2,223,223,1005,224,524,101,1,223,223,1008,677,226,224,102,2,223,223,1005,224,539,101,1,223,223,107,226,677,224,1002,223,2,223,1006,224,554,1001,223,1,223,1108,677,226,224,102,2,223,223,1005,224,569,101,1,223,223,108,226,226,224,1002,223,2,223,1005,224,584,1001,223,1,223,7,677,226,224,1002,223,2,223,1005,224,599,1001,223,1,223,108,226,677,224,1002,223,2,223,1006,224,614,101,1,223,223,1007,677,677,224,1002,223,2,223,1006,224,629,101,1,223,223,7,677,677,224,102,2,223,223,1005,224,644,101,1,223,223,1007,226,226,224,1002,223,2,223,1006,224,659,1001,223,1,223,8,226,677,224,102,2,223,223,1005,224,674,1001,223,1,223,4,223,99,226 2 | -------------------------------------------------------------------------------- /files/input07: -------------------------------------------------------------------------------- 1 | 3,8,1001,8,10,8,105,1,0,0,21,34,51,76,101,126,207,288,369,450,99999,3,9,102,4,9,9,1001,9,2,9,4,9,99,3,9,1001,9,2,9,1002,9,3,9,101,3,9,9,4,9,99,3,9,102,5,9,9,1001,9,2,9,102,2,9,9,101,3,9,9,1002,9,2,9,4,9,99,3,9,101,5,9,9,102,5,9,9,1001,9,2,9,102,3,9,9,1001,9,3,9,4,9,99,3,9,101,2,9,9,1002,9,5,9,1001,9,5,9,1002,9,4,9,101,5,9,9,4,9,99,3,9,1002,9,2,9,4,9,3,9,102,2,9,9,4,9,3,9,1001,9,1,9,4,9,3,9,102,2,9,9,4,9,3,9,1001,9,1,9,4,9,3,9,101,1,9,9,4,9,3,9,1001,9,2,9,4,9,3,9,1002,9,2,9,4,9,3,9,1001,9,1,9,4,9,3,9,1001,9,1,9,4,9,99,3,9,102,2,9,9,4,9,3,9,101,2,9,9,4,9,3,9,102,2,9,9,4,9,3,9,1002,9,2,9,4,9,3,9,1001,9,2,9,4,9,3,9,101,1,9,9,4,9,3,9,1001,9,2,9,4,9,3,9,102,2,9,9,4,9,3,9,101,1,9,9,4,9,3,9,102,2,9,9,4,9,99,3,9,101,2,9,9,4,9,3,9,101,2,9,9,4,9,3,9,101,1,9,9,4,9,3,9,1001,9,2,9,4,9,3,9,101,2,9,9,4,9,3,9,101,2,9,9,4,9,3,9,102,2,9,9,4,9,3,9,102,2,9,9,4,9,3,9,1001,9,2,9,4,9,3,9,1001,9,1,9,4,9,99,3,9,1001,9,2,9,4,9,3,9,101,1,9,9,4,9,3,9,102,2,9,9,4,9,3,9,1001,9,1,9,4,9,3,9,101,1,9,9,4,9,3,9,101,2,9,9,4,9,3,9,1001,9,1,9,4,9,3,9,101,2,9,9,4,9,3,9,102,2,9,9,4,9,3,9,102,2,9,9,4,9,99,3,9,1001,9,2,9,4,9,3,9,102,2,9,9,4,9,3,9,1002,9,2,9,4,9,3,9,102,2,9,9,4,9,3,9,102,2,9,9,4,9,3,9,1001,9,1,9,4,9,3,9,101,2,9,9,4,9,3,9,102,2,9,9,4,9,3,9,102,2,9,9,4,9,3,9,102,2,9,9,4,9,99 2 | -------------------------------------------------------------------------------- /files/input09: -------------------------------------------------------------------------------- 1 | 1102,34463338,34463338,63,1007,63,34463338,63,1005,63,53,1101,0,3,1000,109,988,209,12,9,1000,209,6,209,3,203,0,1008,1000,1,63,1005,63,65,1008,1000,2,63,1005,63,904,1008,1000,0,63,1005,63,58,4,25,104,0,99,4,0,104,0,99,4,17,104,0,99,0,0,1101,0,36,1015,1102,1,387,1028,1101,24,0,1016,1101,0,23,1008,1102,1,35,1012,1102,1,554,1023,1101,29,0,1003,1101,27,0,1011,1101,25,0,1000,1101,0,38,1018,1102,20,1,1019,1102,28,1,1005,1102,1,619,1026,1102,1,22,1004,1101,0,0,1020,1101,0,31,1009,1102,1,783,1024,1102,1,33,1001,1102,616,1,1027,1102,1,21,1006,1101,32,0,1013,1102,39,1,1014,1102,1,378,1029,1101,774,0,1025,1102,1,1,1021,1102,30,1,1007,1102,37,1,1002,1102,1,26,1017,1101,0,557,1022,1102,1,34,1010,109,13,2101,0,-5,63,1008,63,23,63,1005,63,203,4,187,1105,1,207,1001,64,1,64,1002,64,2,64,109,-14,2107,28,4,63,1005,63,225,4,213,1106,0,229,1001,64,1,64,1002,64,2,64,109,10,1207,-3,20,63,1005,63,245,1106,0,251,4,235,1001,64,1,64,1002,64,2,64,109,8,1205,3,263,1105,1,269,4,257,1001,64,1,64,1002,64,2,64,109,-9,1207,-7,34,63,1005,63,287,4,275,1105,1,291,1001,64,1,64,1002,64,2,64,109,-4,2102,1,-3,63,1008,63,32,63,1005,63,311,1105,1,317,4,297,1001,64,1,64,1002,64,2,64,109,21,21101,40,0,-6,1008,1019,43,63,1005,63,337,1106,0,343,4,323,1001,64,1,64,1002,64,2,64,109,-26,1202,7,1,63,1008,63,21,63,1005,63,365,4,349,1106,0,369,1001,64,1,64,1002,64,2,64,109,26,2106,0,3,4,375,1001,64,1,64,1105,1,387,1002,64,2,64,109,-9,21108,41,40,3,1005,1019,407,1001,64,1,64,1106,0,409,4,393,1002,64,2,64,109,13,1205,-8,423,4,415,1106,0,427,1001,64,1,64,1002,64,2,64,109,-19,21107,42,41,5,1005,1015,447,1001,64,1,64,1106,0,449,4,433,1002,64,2,64,109,-3,2102,1,-5,63,1008,63,37,63,1005,63,471,4,455,1105,1,475,1001,64,1,64,1002,64,2,64,109,-2,1201,0,0,63,1008,63,28,63,1005,63,497,4,481,1105,1,501,1001,64,1,64,1002,64,2,64,109,8,2107,29,-8,63,1005,63,521,1001,64,1,64,1106,0,523,4,507,1002,64,2,64,109,-3,1208,-3,30,63,1005,63,541,4,529,1106,0,545,1001,64,1,64,1002,64,2,64,109,4,2105,1,9,1105,1,563,4,551,1001,64,1,64,1002,64,2,64,109,9,1206,-3,581,4,569,1001,64,1,64,1106,0,581,1002,64,2,64,109,-8,1201,-9,0,63,1008,63,23,63,1005,63,605,1001,64,1,64,1106,0,607,4,587,1002,64,2,64,109,21,2106,0,-9,1106,0,625,4,613,1001,64,1,64,1002,64,2,64,109,-35,2108,31,8,63,1005,63,647,4,631,1001,64,1,64,1105,1,647,1002,64,2,64,109,2,1202,0,1,63,1008,63,30,63,1005,63,667,1105,1,673,4,653,1001,64,1,64,1002,64,2,64,109,17,21108,43,43,-4,1005,1016,691,4,679,1106,0,695,1001,64,1,64,1002,64,2,64,109,-14,1208,-1,30,63,1005,63,711,1106,0,717,4,701,1001,64,1,64,1002,64,2,64,109,6,21101,44,0,-1,1008,1011,44,63,1005,63,739,4,723,1105,1,743,1001,64,1,64,1002,64,2,64,109,-15,2108,30,8,63,1005,63,759,1106,0,765,4,749,1001,64,1,64,1002,64,2,64,109,27,2105,1,0,4,771,1001,64,1,64,1105,1,783,1002,64,2,64,109,-9,1206,6,795,1105,1,801,4,789,1001,64,1,64,1002,64,2,64,109,4,21102,45,1,-7,1008,1012,45,63,1005,63,823,4,807,1105,1,827,1001,64,1,64,1002,64,2,64,109,-14,21102,46,1,5,1008,1010,43,63,1005,63,851,1001,64,1,64,1105,1,853,4,833,1002,64,2,64,109,-1,2101,0,1,63,1008,63,25,63,1005,63,873,1105,1,879,4,859,1001,64,1,64,1002,64,2,64,109,9,21107,47,48,-3,1005,1010,897,4,885,1105,1,901,1001,64,1,64,4,64,99,21101,0,27,1,21101,915,0,0,1106,0,922,21201,1,57526,1,204,1,99,109,3,1207,-2,3,63,1005,63,964,21201,-2,-1,1,21101,942,0,0,1106,0,922,21201,1,0,-1,21201,-2,-3,1,21101,957,0,0,1106,0,922,22201,1,-1,-2,1105,1,968,21202,-2,1,-2,109,-3,2106,0,0 2 | -------------------------------------------------------------------------------- /files/input10: -------------------------------------------------------------------------------- 1 | #..#....#...#.#..#.......##.#.#### 2 | #......#..#.#..####.....#..#...##. 3 | .##.......#..#.#....#.#..#.#....#. 4 | ###..#.....###.#....##.....#...#.. 5 | ...#.##..#.###.......#....#....### 6 | .####...##...........##..#..#.##.. 7 | ..#...#.#.#.###....#.#...##.....#. 8 | ......#.....#..#...##.#..##.#..### 9 | ...###.#....#..##.#.#.#....#...### 10 | ..#.###.####..###.#.##..#.##.###.. 11 | ...##...#.#..##.#............##.## 12 | ....#.##.##.##..#......##......... 13 | .#..#.#..#.##......##...#.#.#...## 14 | .##.....#.#.##...#.#.#...#..###... 15 | #.#.#..##......#...#...#.......#.. 16 | #.......#..#####.###.#..#..#.#.#.. 17 | .#......##......##...#..#..#..###. 18 | #.#...#..#....##.#....#.##.#....#. 19 | ....#..#....##..#...##..#..#.#.##. 20 | #.#.#.#.##.#.#..###.......#....### 21 | ...#.#..##....###.####.#..#.#..#.. 22 | #....##..#...##.#.#.........##.#.. 23 | .#....#.#...#.#.........#..#...... 24 | ...#..###...#...#.#.#...#.#..##.## 25 | .####.##.#..#.#.#.#...#.##......#. 26 | .##....##..#.#.#.......#.....####. 27 | #.##.##....#...#..#.#..###..#.###. 28 | ...###.#..#.....#.#.#.#....#....#. 29 | ......#...#.........##....#....##. 30 | .....#.....#..#.##.#.###.#..##.... 31 | .#.....#.#.....#####.....##..#.... 32 | .####.##...#.......####..#....##.. 33 | .#.#.......#......#.##..##.#.#..## 34 | ......##.....##...##.##...##...... 35 | -------------------------------------------------------------------------------- /files/input11: -------------------------------------------------------------------------------- 1 | 3,8,1005,8,325,1106,0,11,0,0,0,104,1,104,0,3,8,102,-1,8,10,1001,10,1,10,4,10,1008,8,0,10,4,10,102,1,8,29,1006,0,41,3,8,1002,8,-1,10,101,1,10,10,4,10,1008,8,0,10,4,10,1001,8,0,54,3,8,102,-1,8,10,101,1,10,10,4,10,1008,8,1,10,4,10,102,1,8,76,1,9,11,10,2,5,2,10,2,1107,19,10,3,8,102,-1,8,10,1001,10,1,10,4,10,1008,8,0,10,4,10,101,0,8,110,2,1007,10,10,2,1103,13,10,1006,0,34,3,8,102,-1,8,10,1001,10,1,10,4,10,108,1,8,10,4,10,102,1,8,142,1006,0,32,1,101,0,10,2,9,5,10,1006,0,50,3,8,1002,8,-1,10,1001,10,1,10,4,10,1008,8,1,10,4,10,101,0,8,179,1,1005,11,10,2,1108,11,10,1006,0,10,1,1004,3,10,3,8,1002,8,-1,10,101,1,10,10,4,10,1008,8,1,10,4,10,1002,8,1,216,1,1002,12,10,2,1102,3,10,1,1007,4,10,2,101,7,10,3,8,1002,8,-1,10,1001,10,1,10,4,10,108,0,8,10,4,10,102,1,8,253,2,104,3,10,1006,0,70,3,8,102,-1,8,10,1001,10,1,10,4,10,108,1,8,10,4,10,102,1,8,282,3,8,1002,8,-1,10,101,1,10,10,4,10,1008,8,0,10,4,10,101,0,8,305,101,1,9,9,1007,9,962,10,1005,10,15,99,109,647,104,0,104,1,21102,838211572492,1,1,21102,342,1,0,1105,1,446,21102,825326674840,1,1,21101,0,353,0,1106,0,446,3,10,104,0,104,1,3,10,104,0,104,0,3,10,104,0,104,1,3,10,104,0,104,1,3,10,104,0,104,0,3,10,104,0,104,1,21101,0,29086686211,1,21102,1,400,0,1106,0,446,21102,209420786919,1,1,21101,0,411,0,1105,1,446,3,10,104,0,104,0,3,10,104,0,104,0,21101,0,838337298792,1,21101,434,0,0,1105,1,446,21101,988661154660,0,1,21102,1,445,0,1106,0,446,99,109,2,21201,-1,0,1,21101,40,0,2,21101,0,477,3,21101,0,467,0,1105,1,510,109,-2,2106,0,0,0,1,0,0,1,109,2,3,10,204,-1,1001,472,473,488,4,0,1001,472,1,472,108,4,472,10,1006,10,504,1101,0,0,472,109,-2,2106,0,0,0,109,4,1201,-1,0,509,1207,-3,0,10,1006,10,527,21102,0,1,-3,22102,1,-3,1,22102,1,-2,2,21101,0,1,3,21101,546,0,0,1105,1,551,109,-4,2105,1,0,109,5,1207,-3,1,10,1006,10,574,2207,-4,-2,10,1006,10,574,21201,-4,0,-4,1105,1,642,21201,-4,0,1,21201,-3,-1,2,21202,-2,2,3,21102,1,593,0,1105,1,551,21202,1,1,-4,21102,1,1,-1,2207,-4,-2,10,1006,10,612,21102,0,1,-1,22202,-2,-1,-2,2107,0,-3,10,1006,10,634,21202,-1,1,1,21102,1,634,0,105,1,509,21202,-2,-1,-2,22201,-4,-2,-4,109,-5,2106,0,0 2 | -------------------------------------------------------------------------------- /files/input12: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /files/input13: -------------------------------------------------------------------------------- 1 | 1,380,379,385,1008,2531,381039,381,1005,381,12,99,109,2532,1101,0,0,383,1101,0,0,382,21002,382,1,1,21002,383,1,2,21101,0,37,0,1106,0,578,4,382,4,383,204,1,1001,382,1,382,1007,382,43,381,1005,381,22,1001,383,1,383,1007,383,22,381,1005,381,18,1006,385,69,99,104,-1,104,0,4,386,3,384,1007,384,0,381,1005,381,94,107,0,384,381,1005,381,108,1106,0,161,107,1,392,381,1006,381,161,1101,-1,0,384,1105,1,119,1007,392,41,381,1006,381,161,1102,1,1,384,20101,0,392,1,21102,20,1,2,21101,0,0,3,21101,138,0,0,1106,0,549,1,392,384,392,20102,1,392,1,21102,20,1,2,21102,1,3,3,21101,0,161,0,1105,1,549,1101,0,0,384,20001,388,390,1,21001,389,0,2,21102,180,1,0,1105,1,578,1206,1,213,1208,1,2,381,1006,381,205,20001,388,390,1,20101,0,389,2,21101,205,0,0,1106,0,393,1002,390,-1,390,1102,1,1,384,20101,0,388,1,20001,389,391,2,21101,0,228,0,1106,0,578,1206,1,261,1208,1,2,381,1006,381,253,21001,388,0,1,20001,389,391,2,21102,253,1,0,1106,0,393,1002,391,-1,391,1101,0,1,384,1005,384,161,20001,388,390,1,20001,389,391,2,21101,0,279,0,1105,1,578,1206,1,316,1208,1,2,381,1006,381,304,20001,388,390,1,20001,389,391,2,21101,304,0,0,1106,0,393,1002,390,-1,390,1002,391,-1,391,1101,0,1,384,1005,384,161,21002,388,1,1,21002,389,1,2,21101,0,0,3,21102,1,338,0,1106,0,549,1,388,390,388,1,389,391,389,21002,388,1,1,20101,0,389,2,21101,4,0,3,21102,1,365,0,1106,0,549,1007,389,21,381,1005,381,75,104,-1,104,0,104,0,99,0,1,0,0,0,0,0,0,291,19,17,1,1,21,109,3,22101,0,-2,1,21202,-1,1,2,21102,0,1,3,21102,1,414,0,1105,1,549,22102,1,-2,1,22101,0,-1,2,21102,1,429,0,1106,0,601,1202,1,1,435,1,386,0,386,104,-1,104,0,4,386,1001,387,-1,387,1005,387,451,99,109,-3,2106,0,0,109,8,22202,-7,-6,-3,22201,-3,-5,-3,21202,-4,64,-2,2207,-3,-2,381,1005,381,492,21202,-2,-1,-1,22201,-3,-1,-3,2207,-3,-2,381,1006,381,481,21202,-4,8,-2,2207,-3,-2,381,1005,381,518,21202,-2,-1,-1,22201,-3,-1,-3,2207,-3,-2,381,1006,381,507,2207,-3,-4,381,1005,381,540,21202,-4,-1,-1,22201,-3,-1,-3,2207,-3,-4,381,1006,381,529,22101,0,-3,-7,109,-8,2106,0,0,109,4,1202,-2,43,566,201,-3,566,566,101,639,566,566,1202,-1,1,0,204,-3,204,-2,204,-1,109,-4,2106,0,0,109,3,1202,-1,43,593,201,-2,593,593,101,639,593,593,21002,0,1,-2,109,-3,2106,0,0,109,3,22102,22,-2,1,22201,1,-1,1,21102,479,1,2,21101,0,201,3,21101,946,0,4,21102,630,1,0,1105,1,456,21201,1,1585,-2,109,-3,2106,0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,0,0,0,0,0,2,2,0,2,0,2,2,2,0,2,0,2,2,2,2,0,0,0,2,2,0,2,2,0,0,2,0,2,2,0,2,2,2,2,2,0,1,1,0,2,0,2,2,2,2,2,2,0,2,2,0,2,2,0,0,0,0,0,0,0,0,2,0,0,0,0,0,2,2,0,2,0,2,0,0,0,0,0,0,1,1,0,2,2,0,2,0,0,0,2,2,0,2,0,0,0,2,0,0,0,0,2,2,2,0,2,0,0,0,2,0,2,2,0,0,2,0,2,0,2,2,0,1,1,0,0,2,0,2,0,0,2,2,2,2,2,0,2,0,2,2,0,0,0,2,2,0,0,2,2,0,2,2,2,0,0,2,0,2,0,2,0,0,2,0,1,1,0,2,0,2,0,2,2,2,0,0,0,0,0,0,2,0,2,0,0,2,0,2,0,0,2,0,0,0,0,2,2,0,2,2,0,0,2,0,0,0,0,1,1,0,0,0,2,2,2,2,0,2,2,2,2,0,2,0,0,2,2,0,2,2,2,0,0,0,2,2,0,0,2,2,0,0,0,0,2,2,0,0,2,0,1,1,0,0,0,0,0,0,2,2,2,2,2,2,0,0,2,2,0,0,2,2,2,0,0,2,2,2,0,2,0,2,0,0,2,0,2,2,2,0,2,0,0,1,1,0,2,0,0,0,0,2,2,2,0,0,2,0,0,2,0,2,2,2,2,0,2,0,2,0,0,0,0,2,0,2,2,0,2,2,0,2,2,0,2,0,1,1,0,0,2,2,0,2,2,0,2,0,2,0,2,0,2,0,0,0,0,2,2,2,2,0,2,0,2,2,0,2,0,2,2,0,2,2,0,2,2,0,0,1,1,0,0,2,0,0,2,2,2,0,2,0,0,2,2,0,2,2,0,0,0,2,2,0,2,2,2,0,0,2,0,0,0,0,2,2,2,0,0,0,2,0,1,1,0,0,2,2,0,0,2,0,2,2,2,2,0,2,2,2,2,2,2,2,2,2,0,2,2,0,2,2,0,2,0,2,2,0,2,2,0,2,2,2,0,1,1,0,0,0,2,2,2,0,2,0,0,0,0,2,2,2,2,2,2,2,2,0,0,0,2,2,2,2,2,0,0,2,0,0,0,0,2,2,0,2,2,0,1,1,0,2,0,0,2,2,0,2,0,0,0,2,2,2,2,2,2,0,2,2,0,2,0,2,2,0,2,2,0,2,2,2,2,2,0,0,2,0,0,0,0,1,1,0,2,0,0,2,0,2,0,0,2,0,0,2,2,2,2,2,0,2,0,2,2,0,2,2,0,0,2,2,0,0,0,2,2,0,2,2,0,2,2,0,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,3,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,37,59,35,82,55,63,50,72,81,61,59,5,1,69,3,36,79,19,94,73,56,24,20,10,1,25,20,49,14,41,74,10,1,48,97,35,54,11,81,35,36,54,58,49,82,25,96,37,51,26,65,35,51,78,95,58,66,62,83,44,62,53,19,35,90,77,50,38,53,16,24,10,59,72,21,24,91,15,80,80,83,67,27,51,49,31,38,51,10,47,22,68,71,30,19,57,64,6,63,91,63,34,53,95,87,27,83,15,5,2,22,23,34,80,75,27,15,88,73,28,23,4,85,54,68,43,55,31,81,78,16,88,75,85,8,9,27,82,95,34,86,94,31,33,42,94,26,98,73,73,74,89,43,1,55,63,21,93,97,18,57,41,66,83,32,13,67,23,80,22,95,8,68,26,8,76,22,10,53,56,76,11,82,77,83,31,43,49,45,19,72,13,7,21,40,58,94,67,16,84,38,11,62,22,56,5,2,42,2,38,37,83,3,74,9,4,52,91,38,45,31,60,81,52,19,7,54,49,64,73,26,11,38,84,49,79,48,92,48,28,88,71,8,66,86,44,90,21,73,33,15,5,34,34,30,66,29,13,59,30,7,52,59,77,71,4,42,28,73,50,40,77,33,18,66,5,36,49,98,48,29,32,21,10,18,2,79,44,67,19,26,64,27,92,29,3,19,67,73,44,41,49,45,34,61,65,97,56,4,44,85,38,19,43,61,10,97,44,3,93,86,71,36,52,95,36,13,28,53,2,79,66,92,38,8,92,47,40,78,51,67,22,42,76,49,41,23,47,49,87,81,26,11,20,17,11,93,64,78,63,29,80,54,20,62,45,78,38,6,14,14,62,86,10,17,77,60,20,77,42,6,68,28,62,37,44,17,85,16,33,55,85,11,35,2,8,3,88,4,67,16,97,51,40,72,70,45,28,36,47,48,95,60,77,63,1,31,54,52,18,25,46,39,58,86,26,75,48,85,34,56,93,16,98,36,24,61,63,90,32,93,16,53,48,74,73,95,43,81,55,85,29,32,91,34,4,14,3,24,41,44,64,7,78,19,17,75,71,16,22,75,78,89,93,12,90,54,38,61,3,54,61,69,58,17,27,46,75,19,13,46,53,33,87,25,65,67,22,50,90,53,98,11,54,52,57,4,49,92,73,26,70,43,12,7,70,7,58,13,8,27,12,20,86,45,3,98,56,66,58,47,52,87,79,31,37,48,56,46,26,50,75,1,24,96,67,94,11,56,57,7,58,2,21,57,40,64,73,81,13,58,68,45,32,55,13,91,43,59,62,34,28,44,35,68,35,70,1,78,77,69,3,38,11,63,12,56,13,20,82,58,59,22,69,34,82,80,86,15,30,92,39,49,75,27,83,59,89,35,86,19,26,18,50,9,91,82,4,63,57,22,96,54,72,3,76,8,19,24,81,92,76,86,48,70,72,72,75,97,36,95,44,53,40,81,81,33,7,55,58,23,13,24,16,24,67,88,13,32,98,62,71,49,72,52,34,9,61,78,33,72,38,30,35,17,66,35,81,79,62,45,64,11,67,69,49,33,91,74,24,21,36,84,14,75,87,21,57,88,79,70,74,62,4,45,35,76,1,84,74,59,25,3,88,38,34,97,82,31,17,56,95,40,21,77,9,4,1,40,68,60,26,45,55,17,51,7,34,82,27,82,24,72,84,42,72,23,11,48,42,51,22,49,9,80,31,51,39,15,64,44,40,36,67,97,70,39,48,71,75,12,62,11,22,19,80,78,11,58,98,98,69,3,6,14,29,41,10,76,27,5,58,18,22,73,80,34,53,51,87,5,31,13,82,34,10,59,20,10,39,89,12,59,84,31,66,73,7,19,69,86,85,2,34,20,87,28,98,19,50,74,95,69,87,63,63,67,11,47,56,38,9,28,25,46,69,28,63,95,65,83,41,19,78,50,96,77,52,84,37,71,92,51,92,35,97,46,17,71,43,58,54,26,38,9,90,56,9,55,85,52,63,20,8,63,23,24,63,81,22,86,11,90,74,23,19,52,53,22,52,15,85,13,37,52,69,36,10,68,20,54,77,35,15,17,46,88,38,57,69,15,38,60,70,40,17,12,79,33,17,88,90,72,2,62,23,91,41,18,56,22,38,35,37,11,23,381039 2 | -------------------------------------------------------------------------------- /files/input14: -------------------------------------------------------------------------------- 1 | 1 FJFL, 1 BPVQN => 7 CMNH 2 | 6 FJFL, 2 KZJLT, 3 DZQJ => 2 NSPZ 3 | 11 TPZDN => 2 TNMC 4 | 1 NSPZ, 2 KQVL => 2 HPNWP 5 | 3 XHDVT => 9 LRBN 6 | 3 LRBN => 6 TPZDN 7 | 1 KPFLZ, 1 XVXCZ => 6 WHMLV 8 | 1 BDWQP, 1 JPGK, 1 MTWG => 5 GLHWQ 9 | 2 BGLTP, 1 HPNWP, 2 GLHWQ, 9 CRJZ, 22 QVQJ, 3 PHGWC, 1 BDWQP => 3 LKPNB 10 | 4 BDSB => 2 PNSD 11 | 2 BRJDJ, 13 THQR => 2 BGLTP 12 | 1 WHJKH, 2 JBTJ => 6 THQR 13 | 1 JBTJ => 9 WGVP 14 | 10 CTXHZ, 2 DGMN => 5 TNVC 15 | 7 LCSV, 1 LKPNB, 36 CMNH, 1 JZXPH, 20 DGJPN, 3 WDWB, 69 DXJKC, 3 WHJKH, 18 XSGP, 22 CGZL, 2 BNVB, 57 PNSD => 1 FUEL 16 | 13 CRCG, 8 NMQN => 1 JZXPH 17 | 2 FZVS, 2 ZPFBH => 9 SRPD 18 | 1 QPNTQ, 4 QVQJ, 1 XZKTG => 9 WDWB 19 | 6 SXZW => 5 FJFL 20 | 6 GVGZ => 6 ZPFBH 21 | 1 JPGK, 3 WDFXH, 22 FJFL => 7 BDSB 22 | 3 WHMLV => 4 JPGK 23 | 7 CGZL, 4 LRBN => 8 MTWG 24 | 11 SXZW, 33 ZTBFN => 4 XVXCZ 25 | 1 FZVS, 1 TNMC, 7 JPGK => 9 FLHW 26 | 2 XKFZ => 8 CGZL 27 | 5 WHMLV => 8 MQRS 28 | 1 QVSH, 6 TPZDN, 9 JQHCH => 2 BMNJ 29 | 3 CMNH, 10 XKFZ => 2 KQVL 30 | 119 ORE => 9 PSPQ 31 | 1 WGVP, 18 BRJDJ => 9 PHGWC 32 | 110 ORE => 6 NMQN 33 | 13 NMQN, 24 XVXCZ, 9 XHDVT => 6 KQVS 34 | 6 TNMC => 4 DXJKC 35 | 1 XZKTG => 8 WHJKH 36 | 1 KPFLZ, 1 LRBN, 7 KQVS => 9 JBTJ 37 | 1 XKFZ => 8 JVGD 38 | 152 ORE => 7 SXZW 39 | 1 BDWQP => 5 CTXHZ 40 | 2 JVGD, 8 DGMN, 2 MTWG => 6 QVQJ 41 | 1 KQVL => 2 BNVB 42 | 3 DZQJ, 37 MQRS => 4 CRJZ 43 | 1 KQVL, 5 WDFXH => 7 BDWQP 44 | 3 GVGZ => 3 BPVQN 45 | 4 PSPQ, 6 ZTBFN => 1 KPFLZ 46 | 34 FBTG => 9 XZKTG 47 | 14 TNMC, 4 FZVS, 3 MTWG => 9 KZJLT 48 | 157 ORE => 6 GVGZ 49 | 5 JVGD, 11 JPGK => 5 CRCG 50 | 1 SXZW, 1 NMQN => 3 XHDVT 51 | 1 FBTG => 5 JQHCH 52 | 3 WDFXH, 4 FZVS, 9 CGFML => 6 DZQJ 53 | 5 BDWQP, 3 TNVC, 7 SRPD, 1 WDFXH, 3 JQHCH, 4 QVQJ, 5 CRCG, 4 DGMN => 7 XSGP 54 | 1 KPFLZ, 3 TPZDN, 1 SRPD => 6 FBTG 55 | 1 WHMLV, 3 BDSB, 2 JVGD => 9 LCSV 56 | 13 XZKTG => 4 QVSH 57 | 1 XHDVT => 7 XKFZ 58 | 1 CMNH, 1 KQVS, 2 XVXCZ => 6 CGFML 59 | 6 FLHW => 4 BRJDJ 60 | 2 KQVL, 2 WGVP, 7 BMNJ, 11 KQVS, 1 HPNWP, 6 CRJZ => 4 DGJPN 61 | 2 DZQJ, 1 BDSB => 2 DGMN 62 | 1 XVXCZ, 4 MQRS => 3 WDFXH 63 | 5 FLHW, 10 JPGK, 1 XZKTG => 4 QPNTQ 64 | 2 LRBN => 9 FZVS 65 | 149 ORE => 8 ZTBFN 66 | -------------------------------------------------------------------------------- /files/input15: -------------------------------------------------------------------------------- 1 | 3,1033,1008,1033,1,1032,1005,1032,31,1008,1033,2,1032,1005,1032,58,1008,1033,3,1032,1005,1032,81,1008,1033,4,1032,1005,1032,104,99,101,0,1034,1039,101,0,1036,1041,1001,1035,-1,1040,1008,1038,0,1043,102,-1,1043,1032,1,1037,1032,1042,1105,1,124,101,0,1034,1039,102,1,1036,1041,1001,1035,1,1040,1008,1038,0,1043,1,1037,1038,1042,1106,0,124,1001,1034,-1,1039,1008,1036,0,1041,102,1,1035,1040,1001,1038,0,1043,1001,1037,0,1042,1106,0,124,1001,1034,1,1039,1008,1036,0,1041,1001,1035,0,1040,1001,1038,0,1043,1002,1037,1,1042,1006,1039,217,1006,1040,217,1008,1039,40,1032,1005,1032,217,1008,1040,40,1032,1005,1032,217,1008,1039,7,1032,1006,1032,165,1008,1040,5,1032,1006,1032,165,1102,1,2,1044,1105,1,224,2,1041,1043,1032,1006,1032,179,1101,0,1,1044,1105,1,224,1,1041,1043,1032,1006,1032,217,1,1042,1043,1032,1001,1032,-1,1032,1002,1032,39,1032,1,1032,1039,1032,101,-1,1032,1032,101,252,1032,211,1007,0,27,1044,1106,0,224,1102,1,0,1044,1106,0,224,1006,1044,247,101,0,1039,1034,101,0,1040,1035,102,1,1041,1036,1001,1043,0,1038,102,1,1042,1037,4,1044,1106,0,0,13,3,18,86,2,10,5,16,95,16,54,4,23,63,70,10,21,20,26,99,85,9,96,3,83,5,9,91,14,1,4,78,11,15,53,10,35,13,7,17,30,90,23,65,65,67,16,4,65,39,11,57,13,36,22,95,53,63,22,47,12,47,2,12,3,71,92,17,55,16,51,79,6,3,92,15,17,15,18,63,8,12,3,49,6,69,32,1,25,83,17,12,1,76,23,95,17,13,92,13,56,16,69,94,11,20,31,83,30,21,88,22,61,45,6,70,12,3,30,23,86,6,93,4,24,9,73,72,7,72,83,9,30,6,24,86,99,11,11,96,16,68,10,35,19,23,6,79,51,8,3,8,75,2,32,26,73,23,80,30,86,25,64,46,24,81,20,18,85,7,94,28,37,93,18,12,77,99,14,22,19,50,2,18,45,63,8,2,89,79,79,7,33,77,18,20,22,12,58,61,20,4,58,20,51,79,14,32,19,87,21,19,76,8,81,7,13,72,75,22,28,22,14,92,30,18,90,10,6,97,25,34,9,20,26,52,45,6,4,97,4,46,26,86,61,20,25,28,26,22,54,69,16,51,3,58,5,23,75,92,18,98,12,11,55,38,22,87,14,20,17,52,73,9,91,30,14,26,12,56,81,54,9,72,18,12,47,93,22,54,21,59,73,7,78,12,87,26,5,39,45,4,55,16,21,86,62,20,98,61,14,20,70,14,25,92,32,44,2,3,15,32,23,23,97,76,78,15,23,95,21,11,69,34,12,89,3,95,24,15,59,38,39,72,14,15,55,48,18,2,43,26,13,58,68,11,22,89,33,79,22,43,40,14,26,5,50,11,28,9,36,33,2,22,43,21,90,15,92,14,14,49,9,80,14,85,99,70,8,16,14,15,70,1,39,32,45,5,57,12,12,4,99,75,28,14,2,28,71,5,69,61,4,28,98,97,87,10,80,2,65,93,6,21,81,7,95,22,35,18,38,23,11,53,14,5,2,84,3,70,33,19,8,52,10,99,14,58,36,1,3,30,53,4,7,47,10,93,2,32,17,40,68,43,20,41,4,16,21,29,23,82,2,18,37,37,15,19,26,41,28,9,95,17,17,52,25,13,49,28,47,22,5,52,14,21,72,83,7,17,86,20,3,18,58,14,19,25,56,65,65,26,53,8,20,75,31,21,40,17,6,33,20,95,47,24,75,26,17,96,24,48,65,97,4,52,20,78,47,14,23,77,32,8,18,98,43,7,61,25,84,40,6,36,24,87,24,71,77,13,20,49,16,60,35,9,64,48,21,2,74,25,1,2,57,11,58,7,45,35,26,13,74,92,2,9,82,9,20,23,15,33,94,7,10,48,78,16,24,94,33,11,21,5,89,47,15,52,12,51,51,81,9,18,39,14,2,97,79,33,23,12,99,3,16,11,79,83,45,18,23,78,86,69,10,25,98,62,62,18,7,44,47,1,3,92,8,22,81,9,3,29,8,81,21,13,95,6,5,99,5,29,16,3,53,72,26,14,44,97,7,43,12,42,65,17,8,12,88,55,18,20,34,13,39,10,72,58,15,11,69,17,94,20,22,52,28,13,30,65,8,2,63,18,4,36,17,8,71,16,71,15,64,14,31,51,75,1,12,92,14,35,23,40,45,1,5,87,28,18,83,43,9,90,2,3,50,18,61,68,5,89,16,44,7,34,82,74,15,83,15,70,13,80,20,43,8,35,14,58,50,75,20,50,9,68,46,52,2,73,11,60,32,61,25,40,9,31,21,73,0,0,21,21,1,10,1,0,0,0,0,0,0 2 | -------------------------------------------------------------------------------- /files/input16: -------------------------------------------------------------------------------- 1 | 59727310424796235189476878806940387435291429226818921130171187957262146115559932358924341808253400617220924411865224341744614706346865536561788244183609411225788501102400269978290670307147139438239865673058478091682748114942700860895620690690625512670966265975462089087644554004423208369517716075591723905075838513598360188150158989179151879406086757964381549720210763972463291801513250953430219653258827586382953297392567981587028568433943223260723561880121205475323894070000380258122357270847092900809245133752093782889315244091880516672127950518799757198383131025701009960944008679555864631340867924665650332161673274408001712152664733237178121872 2 | -------------------------------------------------------------------------------- /files/input17: -------------------------------------------------------------------------------- 1 | 1,330,331,332,109,2780,1102,1,1182,16,1102,1417,1,24,101,0,0,570,1006,570,36,101,0,571,0,1001,570,-1,570,1001,24,1,24,1105,1,18,1008,571,0,571,1001,16,1,16,1008,16,1417,570,1006,570,14,21101,58,0,0,1105,1,786,1006,332,62,99,21102,333,1,1,21101,73,0,0,1106,0,579,1101,0,0,572,1101,0,0,573,3,574,101,1,573,573,1007,574,65,570,1005,570,151,107,67,574,570,1005,570,151,1001,574,-64,574,1002,574,-1,574,1001,572,1,572,1007,572,11,570,1006,570,165,101,1182,572,127,102,1,574,0,3,574,101,1,573,573,1008,574,10,570,1005,570,189,1008,574,44,570,1006,570,158,1106,0,81,21102,340,1,1,1106,0,177,21102,1,477,1,1106,0,177,21102,514,1,1,21101,0,176,0,1106,0,579,99,21101,184,0,0,1106,0,579,4,574,104,10,99,1007,573,22,570,1006,570,165,102,1,572,1182,21101,375,0,1,21101,211,0,0,1105,1,579,21101,1182,11,1,21102,222,1,0,1105,1,979,21101,0,388,1,21102,233,1,0,1106,0,579,21101,1182,22,1,21102,244,1,0,1105,1,979,21101,0,401,1,21102,1,255,0,1106,0,579,21101,1182,33,1,21101,0,266,0,1105,1,979,21101,0,414,1,21102,1,277,0,1105,1,579,3,575,1008,575,89,570,1008,575,121,575,1,575,570,575,3,574,1008,574,10,570,1006,570,291,104,10,21101,0,1182,1,21101,313,0,0,1105,1,622,1005,575,327,1101,1,0,575,21101,327,0,0,1106,0,786,4,438,99,0,1,1,6,77,97,105,110,58,10,33,10,69,120,112,101,99,116,101,100,32,102,117,110,99,116,105,111,110,32,110,97,109,101,32,98,117,116,32,103,111,116,58,32,0,12,70,117,110,99,116,105,111,110,32,65,58,10,12,70,117,110,99,116,105,111,110,32,66,58,10,12,70,117,110,99,116,105,111,110,32,67,58,10,23,67,111,110,116,105,110,117,111,117,115,32,118,105,100,101,111,32,102,101,101,100,63,10,0,37,10,69,120,112,101,99,116,101,100,32,82,44,32,76,44,32,111,114,32,100,105,115,116,97,110,99,101,32,98,117,116,32,103,111,116,58,32,36,10,69,120,112,101,99,116,101,100,32,99,111,109,109,97,32,111,114,32,110,101,119,108,105,110,101,32,98,117,116,32,103,111,116,58,32,43,10,68,101,102,105,110,105,116,105,111,110,115,32,109,97,121,32,98,101,32,97,116,32,109,111,115,116,32,50,48,32,99,104,97,114,97,99,116,101,114,115,33,10,94,62,118,60,0,1,0,-1,-1,0,1,0,0,0,0,0,0,1,20,18,0,109,4,2102,1,-3,587,20102,1,0,-1,22101,1,-3,-3,21101,0,0,-2,2208,-2,-1,570,1005,570,617,2201,-3,-2,609,4,0,21201,-2,1,-2,1106,0,597,109,-4,2105,1,0,109,5,1202,-4,1,629,21002,0,1,-2,22101,1,-4,-4,21102,0,1,-3,2208,-3,-2,570,1005,570,781,2201,-4,-3,653,20102,1,0,-1,1208,-1,-4,570,1005,570,709,1208,-1,-5,570,1005,570,734,1207,-1,0,570,1005,570,759,1206,-1,774,1001,578,562,684,1,0,576,576,1001,578,566,692,1,0,577,577,21101,0,702,0,1105,1,786,21201,-1,-1,-1,1105,1,676,1001,578,1,578,1008,578,4,570,1006,570,724,1001,578,-4,578,21102,1,731,0,1106,0,786,1106,0,774,1001,578,-1,578,1008,578,-1,570,1006,570,749,1001,578,4,578,21101,0,756,0,1106,0,786,1106,0,774,21202,-1,-11,1,22101,1182,1,1,21101,0,774,0,1106,0,622,21201,-3,1,-3,1105,1,640,109,-5,2105,1,0,109,7,1005,575,802,21002,576,1,-6,20101,0,577,-5,1106,0,814,21102,1,0,-1,21101,0,0,-5,21101,0,0,-6,20208,-6,576,-2,208,-5,577,570,22002,570,-2,-2,21202,-5,47,-3,22201,-6,-3,-3,22101,1417,-3,-3,2102,1,-3,843,1005,0,863,21202,-2,42,-4,22101,46,-4,-4,1206,-2,924,21101,1,0,-1,1105,1,924,1205,-2,873,21102,35,1,-4,1106,0,924,1201,-3,0,878,1008,0,1,570,1006,570,916,1001,374,1,374,1201,-3,0,895,1102,2,1,0,2102,1,-3,902,1001,438,0,438,2202,-6,-5,570,1,570,374,570,1,570,438,438,1001,578,558,922,20102,1,0,-4,1006,575,959,204,-4,22101,1,-6,-6,1208,-6,47,570,1006,570,814,104,10,22101,1,-5,-5,1208,-5,29,570,1006,570,810,104,10,1206,-1,974,99,1206,-1,974,1101,0,1,575,21102,973,1,0,1105,1,786,99,109,-7,2105,1,0,109,6,21101,0,0,-4,21102,1,0,-3,203,-2,22101,1,-3,-3,21208,-2,82,-1,1205,-1,1030,21208,-2,76,-1,1205,-1,1037,21207,-2,48,-1,1205,-1,1124,22107,57,-2,-1,1205,-1,1124,21201,-2,-48,-2,1106,0,1041,21101,0,-4,-2,1105,1,1041,21101,-5,0,-2,21201,-4,1,-4,21207,-4,11,-1,1206,-1,1138,2201,-5,-4,1059,2102,1,-2,0,203,-2,22101,1,-3,-3,21207,-2,48,-1,1205,-1,1107,22107,57,-2,-1,1205,-1,1107,21201,-2,-48,-2,2201,-5,-4,1090,20102,10,0,-1,22201,-2,-1,-2,2201,-5,-4,1103,2101,0,-2,0,1106,0,1060,21208,-2,10,-1,1205,-1,1162,21208,-2,44,-1,1206,-1,1131,1105,1,989,21101,439,0,1,1105,1,1150,21101,477,0,1,1106,0,1150,21101,0,514,1,21101,1149,0,0,1106,0,579,99,21101,1157,0,0,1106,0,579,204,-2,104,10,99,21207,-3,22,-1,1206,-1,1138,1201,-5,0,1176,1202,-4,1,0,109,-6,2106,0,0,36,5,42,1,3,1,42,1,3,1,42,1,3,1,6,5,23,13,6,1,3,1,23,1,7,1,10,1,3,1,23,1,7,1,10,1,3,1,23,1,7,1,10,13,13,5,5,1,14,1,7,1,13,1,1,1,1,1,5,1,14,1,7,1,13,1,1,1,1,1,1,11,8,1,7,1,13,1,1,1,1,1,1,1,3,1,5,1,8,1,7,1,13,1,1,1,1,7,5,1,8,1,7,1,13,1,1,1,3,1,9,1,8,1,3,5,13,1,1,7,7,1,8,1,3,1,17,1,5,1,1,1,7,1,8,13,9,1,1,5,1,1,7,1,12,1,7,1,9,1,1,1,5,1,7,1,12,13,5,1,1,1,5,13,16,1,9,1,1,1,13,1,3,1,12,5,5,5,1,1,13,1,3,1,12,1,9,1,5,1,13,1,3,1,12,1,9,1,5,1,13,5,12,1,9,1,5,1,30,1,5,7,3,1,30,1,9,1,1,1,3,1,30,11,1,1,3,1,42,1,3,1,42,5,18 2 | -------------------------------------------------------------------------------- /files/input18: -------------------------------------------------------------------------------- 1 | ################################################################################# 2 | #...#.............#...#.W...............#.#...#.....#.........#.#.......#.......# 3 | #.#.#.#.#########.#.#.#.###############.#.#.#.#.#.#.#.#.#####.#.#.#####.#.###.#.# 4 | #.#...#.#.......#.#.#.#.#.......#.......#...#.#.#.#.#.#g#...#.#.....#.#..d..#.#.# 5 | #.#####.#.#####.#.#D#.#.#.###.###.#######.###.#.#.#.#.#.#.#.#.#####.#.#######.#.# 6 | #v..#.#.#.#.#...#.#.#...#.#...#...#.....#...#...#.#.#.#.#.#.#.....#...#...#...#.# 7 | ###.#.#.#.#.#.#####.#####.###.#.###.###.###.#####.#.#.#.#.#U#####.#####.#.#.###.# 8 | #...#...#.#.#.#...#...#.....#.#.#.....#.#...#...#.#.#.#.#.#...#...#.....#...#.#.# 9 | #.#######.#.#.#.#.###.#.###.#C#.#######.#.###.#.#.#.#.###.###.#.###.#########.#.# 10 | #...#...#.#.#...#...#.#.#...#.#..t......#.#.#.#...#.#...#.#x..#.#...#.........#.# 11 | #.#.#.#.#.#.#######.#.#.#.###.#########.#.#.#.#########.#.#.###.#.###.#######.#.# 12 | #.#.#.#...#.......#.#.#.#...#.#.....#...#...#.........#...#.#..a..#...#..w....#.# 13 | ###.#.#####.###.###.#.#.###.###.###.#.#####.#########.#####.#.#########.###.###.# 14 | #...#...#...#...#...#.#.#...#...#...#...#e#.....#...#...#...#.#..o#.....#.#.#...# 15 | #.#.###.#.###.###.###.#.#.###.###.#####.#.#####.#.#.###.#.#####.#.#.#####.#.#.### 16 | #.#.#.#...#...#.F.#...#.#.....#.#.......#.#.....#.#.#...#.....X.#.#...#.....#.#.# 17 | #.#.#.#####.###.###.#######.###.#########.#.#####.###.###########.###.###.###.#.# 18 | #.#.....#.....#.#...#.G...#...#...#.....#.#.......#...#.........#...#...#...#...# 19 | #.#.#####.#####.#.###.###.###.#.#.#.###.#.#######.#.###.#####.#####.#.#.#######T# 20 | #.#.#.....#.....#.#..u#...#.#.#.#.#.#.#.#.#.L.....#.....#.#...#.....#.#...#.....# 21 | #.#.#.#####.###.#.#.###.###.#.#.###.#.#.#.#.#############.#.###.#########.#.##### 22 | #.#.#.....#.#...#.#...#.#.#...#.#.....#.#...#.............#.#.#.....#j..#.......# 23 | #.#######.#.#.###A#####.#.#.###.#.#####.#.###.###########.#.#Q#.###.#.#.#######.# 24 | #.......#.#.#...#.......#.#.#.......#...#...#.....#.......#.#.#.O.#...#.....#...# 25 | #.#.#.###.#.#############.#.#########.#.###.#.###.#########.#.#############J#.### 26 | #.#.#z#...#...............#.#...#...#.#.#.#.#.#...#...#.....#.....#k..N...#.#...# 27 | #.#.###.###############.###.#.#.#.#.#.#.#.#.###.###.#.#.#.#######.#.#####.#.###.# 28 | #.#...#...#.....#.......#...#.#...#...#.#.#.#...#...#...#.#....q..#...#.#.#.#...# 29 | #####.###.#.###.#.#######.###.###########.#.#.###.###.#####.#######.#.#.#.#.#.### 30 | #.......#.#.#.#.#.........#.............#.#.#...#.#...#...#.#.......#.#n..#.#.#c# 31 | #.#.#####.#.#.#.###############.#######.#.#.#.#.#.#.###.#.#.#########.#.###.#.#.# 32 | #.#.#...#...#.#.....#.........#.#...#...#.#.#.#.#.#...#.#.#.......K...#.....#...# 33 | #.###.#.#####.#####.#####.###.#.#.#.#.#.#.#.###.#.#.###.#.#####################.# 34 | #.#...#...#.......#.......#...#...#.#.#.#.#.#...#.#.#...#.................#.....# 35 | #.#.###.###Y#.#############.#######.#.#.#.#.#.###.###.#######.#########.###.##### 36 | #.#.#.#.....#.#...........#.#.....#.#.#.#.#.#.#...#...#.....#.#...#...#.#...#...# 37 | #.#.#.#######.#.###.#####.#.#.#.#.###.#.#.#.#.#.#.#.###.###.#.#.#.#.#.###.###.#.# 38 | #...#.......#...#.#...#...#.#.#.#...#.#.#...#.#.#.#.#.....#.#.#.#...#...#.....#i# 39 | #M###.#####.#####.###.#####.###.###.#.#.#.###.#.###.#######.#.#.#######.#######.# 40 | #....b#.............#...........#.....#.......#.............#.........#.........# 41 | #######################################.@.####################################### 42 | #.#.......#...#.......#.......#.....#.....#...#...............#.....B.....#.....# 43 | #.#.#.###.#.###.#.###.#.#####.#.###.#.#.#.#.#.#.#####.#####.###.#.#########.###.# 44 | #...#.#.....#...#.#.#.#.#...#.#.#...#.#.#...#.#.#.#...#.....#...#.#.....#...#.#.# 45 | #H###.#.#####.###.#.#.#.###.#.#.#.###.#.#.###.#.#.#.#.#######.###.#.###.#.###.#.# 46 | #.#...#...#...#.#.#.#.#.#...#...#.....#.#...#...#.#.#.#...#...#...#.#.#.#.#...#.# 47 | #.#.#####.#.###.#.#.#.#.#.#############.###.#####.#.#.#.#.#.###.###.#.#.#.#.#.#.# 48 | #.#.....#.#...#.#.#...#.#.....#.....#...#...#.....#.#.#.#.#.#.#...#...#...#.#.#.# 49 | #.#####.#.###.#.#.###.#.#.#.###.###.#.#.#.#######.#.###.#.#.#.###.###.#####.#.#.# 50 | #.....#.#.#.#.#.#...#.#.#.#...#...#.#.#.#.........#.....#.#.....#.#...#.....#.#f# 51 | #######.#.#.#.#.###.###.#####.#.###.#.###########.#######.#.#####.#.#####.#.#.#.# 52 | #.......#...#.....#.....#...#...#...#..l#.......#.#.......#.#.....#.#...#.#.#.#.# 53 | #.#######.###.#####.#####.#.#####.#.###.#.#.#####.#.#####.#.#.#####.#.#.###.###.# 54 | #...#.I.#.#...#...#.......#.......#.#...#.#.......#...#..y#.#...Z.#.#.#...#.#...# 55 | ###.#.###.#.###.#.#############.#####.#.#.###########.#####.#####.#.#V###.#.#.#.# 56 | #...#.....#.#...#...#...........#.....#.#...E.......#.....#...#.#...#.#.....#.#.# 57 | #.#######.#.#.#####.#####.#######.#################.#####.###.#.#####.#.#####.### 58 | #...P...#.#.#.#...#.....#.#.....#...#...#.........#...#.#.....#..m..#.#.#...#...# 59 | #.#####.###.#.#.#.#####.###.###.#.#.#.#.#.#.#########.#.#######.###.#.#R#.#.###.# 60 | #.#.....#...#...#.#.......#.#.#.#.#...#.#.#...#.....#.....#.....#...#.#.#.#...#.# 61 | #.#.#####.#######.#######.#.#.#.#######.#.###.#.###.#####.#.#####.###.#.#.###.#.# 62 | #.#.....#.....#.#...#.#.....#...#.......#...#.#.#.#.....#.#.#.#...#...#.#.#.#...# 63 | #######.#####.#.###.#.#######.###.#########.#.#.#.#####.#.#.#.#.###.###.#.#.###.# 64 | #.........#.#...#...#.....#.#...#.......#...#.#...#.....#...#.#.#...#...#.#.....# 65 | #.#######.#.###.#.#.#####.#.###.#.#####.#.###.###.#.#####.###.#.###.#.###.###.### 66 | #...#.........#.#.#...#...#.#...#...#.#.#.#.#...#.#.#.....#...#.#...#...#...#..p# 67 | ###.#.#########.#.#####.###.#.#####.#.#.#.#.###.#.#.#.#####.###.#.#####.###.###.# 68 | #...#.#.........#.......#.#...#.......#.#.#...#.#.#.#.#.#...#.#.#.#...#.#.#...#.# 69 | #.###.#.#################.#.#########.#.#.###.#.#.#.#.#.#.###.#.#.###.#.#.###.#.# 70 | #...#.#.#.......#...#.....#.#.......#.#.#.#...#...#.#.#.#...#...#...#.....#.#.#.# 71 | #.#.###.#.###.#.#.#.#####.#.###.###.#.#.#.#.#######.#.#.###.#.###.#.#####.#.#.### 72 | #.#...#.#.#...#.#.#...#...#...#...#.#.#.#...#.....#.#...#...#.#...#...#.....#...# 73 | #####.#.###.###.#.###.#.#.###.###.#.###.#.###.###.#.###.#.###.#######.#.#######.# 74 | #..r#.#...#.#.....#...#s#...#.....#...#.#.#...#.#.#.#...#.#...#.......#.#...S...# 75 | #.#.#.###.#.#######.###.#############.#.###.###.#.#.#.###.#.###.#######.#.#####.# 76 | #.#.....#.#.#...#.#...#.........#...#.#.#...#.......#...#.#.....#.#.....#.#.#...# 77 | #.#######.#.#.#.#.###.#.###.###.#.#.#.#.#.#############.#.#######.#.#####.#.#.### 78 | #.#.....#.#...#.#.....#...#.#...#.#.#...#.....#...#...#.#.....#.....#..h..#.#.#.# 79 | #.#.###.#.#####.#.#########.#.###.#.#####.###.#.#.#.#.#.#####.#######.#####.#.#.# 80 | #.....#.........#...........#.....#.....#...#...#...#.......#.........#.........# 81 | ################################################################################# 82 | -------------------------------------------------------------------------------- /files/input19: -------------------------------------------------------------------------------- 1 | 109,424,203,1,21101,11,0,0,1106,0,282,21102,18,1,0,1106,0,259,2101,0,1,221,203,1,21101,31,0,0,1106,0,282,21102,1,38,0,1106,0,259,21002,23,1,2,22102,1,1,3,21102,1,1,1,21101,57,0,0,1106,0,303,2101,0,1,222,21002,221,1,3,21001,221,0,2,21102,259,1,1,21102,80,1,0,1106,0,225,21102,1,79,2,21101,0,91,0,1106,0,303,2102,1,1,223,21001,222,0,4,21102,259,1,3,21101,225,0,2,21102,1,225,1,21101,0,118,0,1105,1,225,21002,222,1,3,21101,118,0,2,21101,0,133,0,1106,0,303,21202,1,-1,1,22001,223,1,1,21102,1,148,0,1105,1,259,1202,1,1,223,20102,1,221,4,20101,0,222,3,21102,1,22,2,1001,132,-2,224,1002,224,2,224,1001,224,3,224,1002,132,-1,132,1,224,132,224,21001,224,1,1,21102,1,195,0,105,1,109,20207,1,223,2,21002,23,1,1,21101,-1,0,3,21102,214,1,0,1106,0,303,22101,1,1,1,204,1,99,0,0,0,0,109,5,2101,0,-4,249,22101,0,-3,1,22102,1,-2,2,21201,-1,0,3,21101,0,250,0,1105,1,225,22101,0,1,-4,109,-5,2105,1,0,109,3,22107,0,-2,-1,21202,-1,2,-1,21201,-1,-1,-1,22202,-1,-2,-2,109,-3,2106,0,0,109,3,21207,-2,0,-1,1206,-1,294,104,0,99,22102,1,-2,-2,109,-3,2106,0,0,109,5,22207,-3,-4,-1,1206,-1,346,22201,-4,-3,-4,21202,-3,-1,-1,22201,-4,-1,2,21202,2,-1,-1,22201,-4,-1,1,22102,1,-2,3,21102,343,1,0,1106,0,303,1105,1,415,22207,-2,-3,-1,1206,-1,387,22201,-3,-2,-3,21202,-2,-1,-1,22201,-3,-1,3,21202,3,-1,-1,22201,-3,-1,2,21201,-4,0,1,21102,384,1,0,1105,1,303,1106,0,415,21202,-4,-1,-4,22201,-4,-3,-4,22202,-3,-2,-2,22202,-2,-4,-4,22202,-3,-2,-3,21202,-4,-1,-2,22201,-3,-2,1,22101,0,1,-4,109,-5,2106,0,0 2 | -------------------------------------------------------------------------------- /files/input21: -------------------------------------------------------------------------------- 1 | 109,2050,21101,0,966,1,21102,13,1,0,1105,1,1378,21101,0,20,0,1106,0,1337,21102,27,1,0,1106,0,1279,1208,1,65,748,1005,748,73,1208,1,79,748,1005,748,110,1208,1,78,748,1005,748,132,1208,1,87,748,1005,748,169,1208,1,82,748,1005,748,239,21102,1,1041,1,21102,1,73,0,1106,0,1421,21102,1,78,1,21102,1,1041,2,21101,0,88,0,1105,1,1301,21101,68,0,1,21102,1041,1,2,21102,103,1,0,1105,1,1301,1101,1,0,750,1106,0,298,21101,82,0,1,21101,0,1041,2,21102,1,125,0,1106,0,1301,1102,2,1,750,1105,1,298,21102,1,79,1,21101,1041,0,2,21101,147,0,0,1106,0,1301,21102,84,1,1,21101,1041,0,2,21101,162,0,0,1105,1,1301,1101,3,0,750,1105,1,298,21102,1,65,1,21101,0,1041,2,21102,184,1,0,1106,0,1301,21102,1,76,1,21102,1,1041,2,21102,1,199,0,1106,0,1301,21102,75,1,1,21102,1041,1,2,21101,214,0,0,1106,0,1301,21101,221,0,0,1105,1,1337,21102,10,1,1,21102,1,1041,2,21102,236,1,0,1105,1,1301,1106,0,553,21102,1,85,1,21102,1041,1,2,21101,0,254,0,1106,0,1301,21101,78,0,1,21102,1,1041,2,21101,269,0,0,1105,1,1301,21102,1,276,0,1106,0,1337,21102,10,1,1,21102,1,1041,2,21101,0,291,0,1105,1,1301,1102,1,1,755,1105,1,553,21102,1,32,1,21102,1,1041,2,21101,313,0,0,1105,1,1301,21102,1,320,0,1106,0,1337,21101,327,0,0,1105,1,1279,2101,0,1,749,21102,1,65,2,21102,73,1,3,21101,0,346,0,1105,1,1889,1206,1,367,1007,749,69,748,1005,748,360,1102,1,1,756,1001,749,-64,751,1106,0,406,1008,749,74,748,1006,748,381,1101,-1,0,751,1105,1,406,1008,749,84,748,1006,748,395,1101,0,-2,751,1105,1,406,21101,0,1100,1,21101,406,0,0,1105,1,1421,21102,32,1,1,21102,1100,1,2,21102,421,1,0,1105,1,1301,21101,428,0,0,1106,0,1337,21101,435,0,0,1105,1,1279,2102,1,1,749,1008,749,74,748,1006,748,453,1101,0,-1,752,1106,0,478,1008,749,84,748,1006,748,467,1102,-2,1,752,1106,0,478,21101,1168,0,1,21102,1,478,0,1106,0,1421,21102,1,485,0,1106,0,1337,21101,10,0,1,21102,1,1168,2,21101,0,500,0,1105,1,1301,1007,920,15,748,1005,748,518,21101,1209,0,1,21101,518,0,0,1105,1,1421,1002,920,3,529,1001,529,921,529,102,1,750,0,1001,529,1,537,1001,751,0,0,1001,537,1,545,1002,752,1,0,1001,920,1,920,1105,1,13,1005,755,577,1006,756,570,21101,1100,0,1,21102,570,1,0,1105,1,1421,21102,1,987,1,1105,1,581,21102,1001,1,1,21101,588,0,0,1105,1,1378,1102,758,1,594,102,1,0,753,1006,753,654,21002,753,1,1,21102,1,610,0,1106,0,667,21102,0,1,1,21102,621,1,0,1106,0,1463,1205,1,647,21101,1015,0,1,21102,635,1,0,1106,0,1378,21102,1,1,1,21101,0,646,0,1105,1,1463,99,1001,594,1,594,1106,0,592,1006,755,664,1101,0,0,755,1105,1,647,4,754,99,109,2,1102,726,1,757,22101,0,-1,1,21102,9,1,2,21101,697,0,3,21101,0,692,0,1105,1,1913,109,-2,2105,1,0,109,2,1001,757,0,706,2101,0,-1,0,1001,757,1,757,109,-2,2105,1,0,1,1,1,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0,255,63,223,191,95,127,159,0,228,49,34,55,222,59,252,85,109,103,221,76,141,197,124,142,115,217,206,69,187,232,114,60,122,53,87,169,42,166,241,177,167,203,186,136,220,181,234,54,68,184,219,102,43,168,47,79,179,157,251,93,123,245,253,202,178,50,57,171,238,196,116,46,152,172,201,200,61,111,120,86,58,158,199,101,107,218,92,138,173,212,156,139,243,125,205,182,231,239,163,188,236,227,230,51,183,247,143,229,84,244,175,248,154,78,121,100,185,119,98,170,213,38,207,237,106,155,226,216,153,94,242,71,70,204,99,56,214,39,189,137,62,162,190,118,35,113,77,246,174,249,215,254,235,233,108,110,117,198,250,126,140,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,20,73,110,112,117,116,32,105,110,115,116,114,117,99,116,105,111,110,115,58,10,13,10,87,97,108,107,105,110,103,46,46,46,10,10,13,10,82,117,110,110,105,110,103,46,46,46,10,10,25,10,68,105,100,110,39,116,32,109,97,107,101,32,105,116,32,97,99,114,111,115,115,58,10,10,58,73,110,118,97,108,105,100,32,111,112,101,114,97,116,105,111,110,59,32,101,120,112,101,99,116,101,100,32,115,111,109,101,116,104,105,110,103,32,108,105,107,101,32,65,78,68,44,32,79,82,44,32,111,114,32,78,79,84,67,73,110,118,97,108,105,100,32,102,105,114,115,116,32,97,114,103,117,109,101,110,116,59,32,101,120,112,101,99,116,101,100,32,115,111,109,101,116,104,105,110,103,32,108,105,107,101,32,65,44,32,66,44,32,67,44,32,68,44,32,74,44,32,111,114,32,84,40,73,110,118,97,108,105,100,32,115,101,99,111,110,100,32,97,114,103,117,109,101,110,116,59,32,101,120,112,101,99,116,101,100,32,74,32,111,114,32,84,52,79,117,116,32,111,102,32,109,101,109,111,114,121,59,32,97,116,32,109,111,115,116,32,49,53,32,105,110,115,116,114,117,99,116,105,111,110,115,32,99,97,110,32,98,101,32,115,116,111,114,101,100,0,109,1,1005,1262,1270,3,1262,21001,1262,0,0,109,-1,2106,0,0,109,1,21102,1,1288,0,1106,0,1263,20102,1,1262,0,1102,0,1,1262,109,-1,2106,0,0,109,5,21102,1310,1,0,1106,0,1279,21201,1,0,-2,22208,-2,-4,-1,1205,-1,1332,22101,0,-3,1,21102,1,1332,0,1105,1,1421,109,-5,2106,0,0,109,2,21102,1,1346,0,1105,1,1263,21208,1,32,-1,1205,-1,1363,21208,1,9,-1,1205,-1,1363,1106,0,1373,21102,1,1370,0,1106,0,1279,1105,1,1339,109,-2,2105,1,0,109,5,2102,1,-4,1385,21001,0,0,-2,22101,1,-4,-4,21102,0,1,-3,22208,-3,-2,-1,1205,-1,1416,2201,-4,-3,1408,4,0,21201,-3,1,-3,1106,0,1396,109,-5,2106,0,0,109,2,104,10,22101,0,-1,1,21102,1,1436,0,1105,1,1378,104,10,99,109,-2,2106,0,0,109,3,20002,594,753,-1,22202,-1,-2,-1,201,-1,754,754,109,-3,2106,0,0,109,10,21101,5,0,-5,21102,1,1,-4,21101,0,0,-3,1206,-9,1555,21102,1,3,-6,21102,1,5,-7,22208,-7,-5,-8,1206,-8,1507,22208,-6,-4,-8,1206,-8,1507,104,64,1106,0,1529,1205,-6,1527,1201,-7,716,1515,21002,0,-11,-8,21201,-8,46,-8,204,-8,1106,0,1529,104,46,21201,-7,1,-7,21207,-7,22,-8,1205,-8,1488,104,10,21201,-6,-1,-6,21207,-6,0,-8,1206,-8,1484,104,10,21207,-4,1,-8,1206,-8,1569,21102,1,0,-9,1105,1,1689,21208,-5,21,-8,1206,-8,1583,21102,1,1,-9,1106,0,1689,1201,-5,716,1589,20101,0,0,-2,21208,-4,1,-1,22202,-2,-1,-1,1205,-2,1613,22102,1,-5,1,21102,1,1613,0,1106,0,1444,1206,-1,1634,21201,-5,0,1,21102,1,1627,0,1106,0,1694,1206,1,1634,21101,0,2,-3,22107,1,-4,-8,22201,-1,-8,-8,1206,-8,1649,21201,-5,1,-5,1206,-3,1663,21201,-3,-1,-3,21201,-4,1,-4,1106,0,1667,21201,-4,-1,-4,21208,-4,0,-1,1201,-5,716,1676,22002,0,-1,-1,1206,-1,1686,21101,1,0,-4,1105,1,1477,109,-10,2106,0,0,109,11,21101,0,0,-6,21101,0,0,-8,21102,0,1,-7,20208,-6,920,-9,1205,-9,1880,21202,-6,3,-9,1201,-9,921,1725,20101,0,0,-5,1001,1725,1,1732,21001,0,0,-4,21201,-4,0,1,21101,0,1,2,21101,0,9,3,21101,1754,0,0,1106,0,1889,1206,1,1772,2201,-10,-4,1766,1001,1766,716,1766,21002,0,1,-3,1106,0,1790,21208,-4,-1,-9,1206,-9,1786,22102,1,-8,-3,1105,1,1790,21202,-7,1,-3,1001,1732,1,1796,20101,0,0,-2,21208,-2,-1,-9,1206,-9,1812,22101,0,-8,-1,1106,0,1816,21201,-7,0,-1,21208,-5,1,-9,1205,-9,1837,21208,-5,2,-9,1205,-9,1844,21208,-3,0,-1,1106,0,1855,22202,-3,-1,-1,1106,0,1855,22201,-3,-1,-1,22107,0,-1,-1,1106,0,1855,21208,-2,-1,-9,1206,-9,1869,21202,-1,1,-8,1105,1,1873,21201,-1,0,-7,21201,-6,1,-6,1106,0,1708,22102,1,-8,-10,109,-11,2105,1,0,109,7,22207,-6,-5,-3,22207,-4,-6,-2,22201,-3,-2,-1,21208,-1,0,-6,109,-7,2106,0,0,0,109,5,1201,-2,0,1912,21207,-4,0,-1,1206,-1,1930,21101,0,0,-4,22102,1,-4,1,22101,0,-3,2,21101,0,1,3,21102,1949,1,0,1105,1,1954,109,-5,2106,0,0,109,6,21207,-4,1,-1,1206,-1,1977,22207,-5,-3,-1,1206,-1,1977,22101,0,-5,-5,1106,0,2045,22101,0,-5,1,21201,-4,-1,2,21202,-3,2,3,21102,1,1996,0,1105,1,1954,22102,1,1,-5,21102,1,1,-2,22207,-5,-3,-1,1206,-1,2015,21101,0,0,-2,22202,-3,-2,-3,22107,0,-4,-1,1206,-1,2037,22102,1,-2,1,21101,2037,0,0,106,0,1912,21202,-3,-1,-3,22201,-5,-3,-5,109,-6,2106,0,0 2 | -------------------------------------------------------------------------------- /files/input22: -------------------------------------------------------------------------------- 1 | deal into new stack 2 | deal with increment 21 3 | cut -1639 4 | deal with increment 32 5 | cut -873 6 | deal with increment 8 7 | deal into new stack 8 | cut -7730 9 | deal with increment 8 10 | cut -8408 11 | deal with increment 42 12 | cut -4951 13 | deal into new stack 14 | deal with increment 24 15 | cut -6185 16 | deal with increment 69 17 | cut -930 18 | deal into new stack 19 | cut 8675 20 | deal with increment 47 21 | cut -4543 22 | deal with increment 62 23 | deal into new stack 24 | deal with increment 23 25 | cut 7128 26 | deal with increment 29 27 | deal into new stack 28 | deal with increment 65 29 | cut 8232 30 | deal with increment 34 31 | deal into new stack 32 | deal with increment 7 33 | deal into new stack 34 | cut -5590 35 | deal with increment 34 36 | cut -3523 37 | deal with increment 24 38 | cut 8446 39 | deal with increment 42 40 | cut 6714 41 | deal into new stack 42 | deal with increment 60 43 | cut 1977 44 | deal with increment 51 45 | cut 2719 46 | deal with increment 45 47 | cut 9563 48 | deal with increment 33 49 | cut 9036 50 | deal with increment 70 51 | cut 3372 52 | deal with increment 60 53 | cut 9686 54 | deal with increment 7 55 | cut 9344 56 | deal with increment 13 57 | cut 797 58 | deal with increment 12 59 | cut -6989 60 | deal with increment 43 61 | deal into new stack 62 | cut 1031 63 | deal with increment 14 64 | cut -1145 65 | deal with increment 26 66 | cut -9008 67 | deal with increment 14 68 | cut 432 69 | deal with increment 46 70 | cut -65 71 | deal with increment 50 72 | cut -704 73 | deal with increment 4 74 | cut 7372 75 | deal with increment 66 76 | cut 690 77 | deal with increment 60 78 | cut -7137 79 | deal with increment 66 80 | cut 9776 81 | deal with increment 30 82 | cut 3532 83 | deal with increment 62 84 | cut 4768 85 | deal with increment 13 86 | deal into new stack 87 | cut -9014 88 | deal with increment 68 89 | cut -9601 90 | deal with increment 6 91 | cut -7535 92 | deal with increment 74 93 | cut 9479 94 | deal with increment 6 95 | cut -1879 96 | deal with increment 33 97 | cut 3675 98 | deal with increment 19 99 | cut -937 100 | deal with increment 42 101 | -------------------------------------------------------------------------------- /files/input23: -------------------------------------------------------------------------------- 1 | 3,62,1001,62,11,10,109,2241,105,1,0,1526,798,2012,1254,1054,1460,953,889,1975,1732,672,1190,2078,1157,2181,604,701,1295,1225,1326,1802,1493,1833,2113,1691,2144,1425,829,1942,1359,2045,1122,767,1567,1394,922,860,1660,990,732,1629,635,1023,1598,1091,2210,1878,1765,1909,571,0,0,0,0,0,0,0,0,0,0,0,0,3,64,1008,64,-1,62,1006,62,88,1006,61,170,1105,1,73,3,65,21002,64,1,1,20102,1,66,2,21101,105,0,0,1105,1,436,1201,1,-1,64,1007,64,0,62,1005,62,73,7,64,67,62,1006,62,73,1002,64,2,133,1,133,68,133,102,1,0,62,1001,133,1,140,8,0,65,63,2,63,62,62,1005,62,73,1002,64,2,161,1,161,68,161,1102,1,1,0,1001,161,1,169,1001,65,0,0,1102,1,1,61,1102,0,1,63,7,63,67,62,1006,62,203,1002,63,2,194,1,68,194,194,1006,0,73,1001,63,1,63,1106,0,178,21101,210,0,0,106,0,69,2101,0,1,70,1102,1,0,63,7,63,71,62,1006,62,250,1002,63,2,234,1,72,234,234,4,0,101,1,234,240,4,0,4,70,1001,63,1,63,1105,1,218,1106,0,73,109,4,21101,0,0,-3,21102,1,0,-2,20207,-2,67,-1,1206,-1,293,1202,-2,2,283,101,1,283,283,1,68,283,283,22001,0,-3,-3,21201,-2,1,-2,1105,1,263,22102,1,-3,-3,109,-4,2106,0,0,109,4,21101,0,1,-3,21102,0,1,-2,20207,-2,67,-1,1206,-1,342,1202,-2,2,332,101,1,332,332,1,68,332,332,22002,0,-3,-3,21201,-2,1,-2,1106,0,312,21202,-3,1,-3,109,-4,2105,1,0,109,1,101,1,68,359,20101,0,0,1,101,3,68,366,21002,0,1,2,21102,1,376,0,1106,0,436,22101,0,1,0,109,-1,2105,1,0,1,2,4,8,16,32,64,128,256,512,1024,2048,4096,8192,16384,32768,65536,131072,262144,524288,1048576,2097152,4194304,8388608,16777216,33554432,67108864,134217728,268435456,536870912,1073741824,2147483648,4294967296,8589934592,17179869184,34359738368,68719476736,137438953472,274877906944,549755813888,1099511627776,2199023255552,4398046511104,8796093022208,17592186044416,35184372088832,70368744177664,140737488355328,281474976710656,562949953421312,1125899906842624,109,8,21202,-6,10,-5,22207,-7,-5,-5,1205,-5,521,21101,0,0,-4,21101,0,0,-3,21102,1,51,-2,21201,-2,-1,-2,1201,-2,385,471,20101,0,0,-1,21202,-3,2,-3,22207,-7,-1,-5,1205,-5,496,21201,-3,1,-3,22102,-1,-1,-5,22201,-7,-5,-7,22207,-3,-6,-5,1205,-5,515,22102,-1,-6,-5,22201,-3,-5,-3,22201,-1,-4,-4,1205,-2,461,1105,1,547,21101,0,-1,-4,21202,-6,-1,-6,21207,-7,0,-5,1205,-5,547,22201,-7,-6,-7,21201,-4,1,-4,1105,1,529,22102,1,-4,-7,109,-8,2106,0,0,109,1,101,1,68,563,21001,0,0,0,109,-1,2105,1,0,1102,87671,1,66,1102,1,2,67,1102,598,1,68,1101,302,0,69,1101,1,0,71,1101,0,602,72,1105,1,73,0,0,0,0,19,59159,1101,59779,0,66,1101,0,1,67,1102,1,631,68,1101,0,556,69,1102,1,1,71,1101,633,0,72,1105,1,73,1,25,30,192358,1102,41491,1,66,1101,0,4,67,1101,0,662,68,1101,253,0,69,1102,1,1,71,1101,0,670,72,1105,1,73,0,0,0,0,0,0,0,0,30,96179,1101,0,77699,66,1102,1,1,67,1101,0,699,68,1101,556,0,69,1102,1,0,71,1102,701,1,72,1105,1,73,1,1177,1101,32299,0,66,1101,0,1,67,1102,1,728,68,1102,1,556,69,1101,1,0,71,1101,730,0,72,1106,0,73,1,1151,25,264644,1102,1,77591,66,1101,1,0,67,1101,759,0,68,1101,0,556,69,1101,0,3,71,1101,0,761,72,1105,1,73,1,2,25,132322,3,115706,3,289265,1101,46451,0,66,1102,1,1,67,1101,0,794,68,1101,0,556,69,1102,1,1,71,1102,1,796,72,1105,1,73,1,7537,26,236679,1101,37951,0,66,1101,0,1,67,1101,0,825,68,1102,556,1,69,1102,1,1,71,1101,827,0,72,1106,0,73,1,997,25,66161,1102,1,17491,66,1102,1,1,67,1101,856,0,68,1102,1,556,69,1102,1,1,71,1101,0,858,72,1105,1,73,1,-67132,24,75773,1101,78989,0,66,1101,0,1,67,1101,0,887,68,1102,1,556,69,1101,0,0,71,1102,889,1,72,1105,1,73,1,1547,1101,25969,0,66,1102,1,1,67,1102,916,1,68,1102,1,556,69,1101,2,0,71,1102,918,1,72,1105,1,73,1,10,47,112276,3,231412,1101,6469,0,66,1102,1,1,67,1101,0,949,68,1102,556,1,69,1101,1,0,71,1101,951,0,72,1105,1,73,1,-19261,24,454638,1102,101873,1,66,1102,1,1,67,1102,980,1,68,1101,556,0,69,1101,4,0,71,1102,1,982,72,1105,1,73,1,1,26,157786,8,164378,25,198483,11,95071,1102,1,48751,66,1102,2,1,67,1101,0,1017,68,1101,0,302,69,1102,1,1,71,1102,1021,1,72,1105,1,73,0,0,0,0,4,268724,1102,1,60383,66,1102,1,1,67,1101,1050,0,68,1102,1,556,69,1102,1,1,71,1102,1052,1,72,1106,0,73,1,121,8,246567,1102,1,67181,66,1101,4,0,67,1102,1081,1,68,1101,253,0,69,1101,1,0,71,1101,1089,0,72,1106,0,73,0,0,0,0,0,0,0,0,5,104479,1101,0,99277,66,1102,1,1,67,1101,0,1118,68,1101,0,556,69,1101,0,1,71,1102,1,1120,72,1106,0,73,1,-75,11,285213,1102,1,76753,66,1102,3,1,67,1101,1149,0,68,1101,0,302,69,1101,1,0,71,1101,0,1155,72,1105,1,73,0,0,0,0,0,0,4,201543,1101,0,79,66,1102,1,1,67,1101,1184,0,68,1102,1,556,69,1101,0,2,71,1101,0,1186,72,1105,1,73,1,125,49,87671,47,28069,1102,95071,1,66,1102,3,1,67,1101,1217,0,68,1102,1,302,69,1102,1,1,71,1101,1223,0,72,1105,1,73,0,0,0,0,0,0,12,6982,1101,0,78889,66,1101,1,0,67,1101,0,1252,68,1101,0,556,69,1102,1,0,71,1102,1,1254,72,1105,1,73,1,1927,1101,0,57853,66,1102,1,6,67,1102,1281,1,68,1102,1,302,69,1102,1,1,71,1102,1293,1,72,1106,0,73,0,0,0,0,0,0,0,0,0,0,0,0,5,208958,1101,16363,0,66,1101,0,1,67,1102,1,1322,68,1102,1,556,69,1102,1,1,71,1101,1324,0,72,1105,1,73,1,50656,24,303092,1102,59159,1,66,1102,1,2,67,1102,1,1353,68,1102,1,302,69,1102,1,1,71,1101,1357,0,72,1105,1,73,0,0,0,0,2,81758,1102,43853,1,66,1101,3,0,67,1102,1386,1,68,1102,302,1,69,1102,1,1,71,1102,1,1392,72,1106,0,73,0,0,0,0,0,0,4,134362,1102,67061,1,66,1102,1,1,67,1102,1,1421,68,1102,1,556,69,1102,1,1,71,1102,1423,1,72,1105,1,73,1,11,8,328756,1102,1,78893,66,1101,0,3,67,1102,1,1452,68,1101,302,0,69,1102,1,1,71,1102,1,1458,72,1106,0,73,0,0,0,0,0,0,41,124473,1102,1,104479,66,1101,2,0,67,1101,0,1487,68,1101,351,0,69,1101,1,0,71,1102,1491,1,72,1105,1,73,0,0,0,0,255,99571,1101,87587,0,66,1102,1,1,67,1102,1,1520,68,1101,0,556,69,1102,1,2,71,1102,1522,1,72,1106,0,73,1,509,29,87706,11,190142,1102,1,99571,66,1102,1,1,67,1102,1,1553,68,1101,0,556,69,1102,1,6,71,1102,1555,1,72,1106,0,73,1,21486,38,48751,12,3491,12,10473,31,76753,31,153506,31,230259,1102,1,85159,66,1101,1,0,67,1102,1594,1,68,1102,556,1,69,1102,1,1,71,1102,1,1596,72,1106,0,73,1,439,24,378865,1102,9187,1,66,1102,1,1,67,1101,1625,0,68,1101,556,0,69,1101,0,1,71,1101,0,1627,72,1106,0,73,1,67,8,82189,1101,49363,0,66,1102,1,1,67,1102,1656,1,68,1102,556,1,69,1101,0,1,71,1101,0,1658,72,1105,1,73,1,14,26,78893,1101,17291,0,66,1102,1,1,67,1102,1687,1,68,1102,1,556,69,1101,1,0,71,1101,0,1689,72,1105,1,73,1,-2,48,141374,1102,75773,1,66,1102,1,6,67,1102,1718,1,68,1102,1,253,69,1102,1,1,71,1102,1,1730,72,1106,0,73,0,0,0,0,0,0,0,0,0,0,0,0,49,175342,1102,13159,1,66,1102,2,1,67,1102,1759,1,68,1101,302,0,69,1101,0,1,71,1101,0,1763,72,1106,0,73,0,0,0,0,38,97502,1102,28069,1,66,1102,4,1,67,1101,0,1792,68,1101,0,302,69,1101,0,1,71,1102,1,1800,72,1105,1,73,0,0,0,0,0,0,0,0,3,57853,1101,40853,0,66,1102,1,1,67,1102,1,1829,68,1101,0,556,69,1102,1,1,71,1101,0,1831,72,1106,0,73,1,327322,24,227319,1102,1,53089,66,1101,1,0,67,1102,1860,1,68,1101,556,0,69,1101,0,8,71,1101,1862,0,72,1106,0,73,1,5,19,118318,2,40879,29,43853,28,65963,9,13159,47,56138,47,84207,3,173559,1102,1,44777,66,1102,1,1,67,1101,0,1905,68,1101,556,0,69,1102,1,1,71,1101,0,1907,72,1105,1,73,1,-71105,24,151546,1101,0,70687,66,1102,2,1,67,1102,1,1936,68,1102,302,1,69,1102,1,1,71,1102,1,1940,72,1106,0,73,0,0,0,0,41,82982,1102,1,65963,66,1102,1,2,67,1102,1,1969,68,1101,302,0,69,1102,1,1,71,1102,1,1973,72,1105,1,73,0,0,0,0,9,26318,1101,82189,0,66,1102,1,4,67,1101,0,2002,68,1101,0,302,69,1102,1,1,71,1101,0,2010,72,1106,0,73,0,0,0,0,0,0,0,0,41,41491,1101,0,40879,66,1101,0,2,67,1101,2039,0,68,1102,1,302,69,1102,1,1,71,1101,0,2043,72,1106,0,73,0,0,0,0,29,131559,1102,1,96179,66,1102,2,1,67,1102,1,2072,68,1101,0,302,69,1102,1,1,71,1102,1,2076,72,1106,0,73,0,0,0,0,28,131926,1101,3491,0,66,1102,3,1,67,1101,0,2105,68,1102,302,1,69,1102,1,1,71,1102,1,2111,72,1106,0,73,0,0,0,0,0,0,4,67181,1101,65551,0,66,1101,0,1,67,1102,1,2140,68,1102,1,556,69,1101,0,1,71,1102,1,2142,72,1105,1,73,1,296273,48,70687,1101,66161,0,66,1102,4,1,67,1101,2171,0,68,1102,302,1,69,1101,0,1,71,1101,2179,0,72,1106,0,73,0,0,0,0,0,0,0,0,41,165964,1101,0,81181,66,1101,0,1,67,1102,1,2208,68,1102,556,1,69,1102,0,1,71,1101,2210,0,72,1106,0,73,1,1141,1101,0,74093,66,1101,0,1,67,1102,2237,1,68,1102,1,556,69,1101,1,0,71,1102,1,2239,72,1106,0,73,1,160,3,347118 2 | -------------------------------------------------------------------------------- /files/input24: -------------------------------------------------------------------------------- 1 | .#.## 2 | ..##. 3 | ##... 4 | #...# 5 | ..### 6 | --------------------------------------------------------------------------------