def day13b(): """Day 13b: Shuttle Search.""" items = helpers.get_input_strings("day13") def get_valid_busses(t, busmap): """Return a list of busses that are valid for a given time.""" valid = [] for b in sorted(busmap, reverse=True): n = busmap[b] if b and (t + n) % b == 0: valid.append(b) return valid busmap = {} i = 0 for x in items[1].split(","): if x != "x": busmap[int(x)] = i i += 1 loop = 0 step = 1 t = 0 while True: loop += 1 t += step v = get_valid_busses(t, busmap) print(f"{t}: {v}") if v: step = math.prod(v) if len(v) == len(busmap): break print(f"Loops: {loop}")
def day13a(): """Day 13a: Shuttle Search.""" items = helpers.get_input_strings("day13") est = int(items[0]) busmap = {} i = 0 for x in items[1].split(","): if x != "x": busmap[int(x)] = i i += 1 print(est, busmap) times = {} for b in busmap: n = round(est / b) t = b * n if t not in times: times[t] = [] times[t].append(b) t = b * (n + 1) if t not in times: times[t] = [] times[t].append(b) for t in sorted(times): if t >= est: b = times[t][0] w = t - est a = b * w print( f"Bus #{b} departs at {t}, which is {w} minutes wait: {b} * {w} = {a}." ) print(f"Answer: {a}") break
def day18b(): """Day 18a.""" items = helpers.get_input_strings("day18") total = 0 for expression in items: total += helpers.evaluate_expression_advanced(expression) print(f"Total: {total}")
def day5a(output=True): """Day 5: Binary Boarding.""" rowcount = 127 colcount = 7 seat_ids = [] items = helpers.get_input_strings("day5") verbose = False for i in items: rowstring = i[:7] colstring = i[-3:] row = helpers.check_seat_row(rowstring, 0, rowcount, verbose=verbose) if verbose: print(f"Row: {row}\n") col = helpers.check_seat_col(colstring, 0, colcount, verbose=verbose) if verbose: print(f"Column: {col}\n") seat_id = (row * 8) + col seat_ids.append(seat_id) if verbose: print(f"{i}: row {row}, col {col}, seat ID {seat_id}") if output: print(f"\nMax Seat ID: {max(seat_ids)}") return seat_ids
def day11b(): """Day 11b Seating System.""" rows = helpers.get_input_strings("day11") length = len(rows) width = len(rows[0]) print(f"Length: {length}, Width: {width}") helpers.print_rows(rows) limit = 5 recurse = True done = False i = 0 while not done: print(f"\nIteration {i}:\n") new_rows = helpers.perform_seating(rows, length, width, limit, recurse) helpers.print_rows(new_rows) if new_rows == rows: done = True rows = new_rows i += 1 occupied = 0 for row in rows: for c in row: if c == "#": occupied += 1 print(f"Iterations: {i}") print(f"Occupied: {occupied}")
def day7b(): """Day 7a.""" check = "shiny gold" items = helpers.get_input_strings("day7") bags = helpers.get_bags(items) # print(json.dumps(bags, indent=2, sort_keys=True)) total = helpers.count_bags(check, bags) print(f"\nTotal: {total}")
def day12a(): """Day 12a: Rain Risk.""" items = helpers.get_input_strings("day12") loc = (0, 0, "E") for item in items: loc = helpers.parse_action_a(loc, item) x, y, d = loc final = abs(x) + abs(y) print(f"Answer: {final}")
def day12b(): """Day 12b: Rain Risk.""" items = helpers.get_input_strings("day12") loc = (10, 1, 0, 0) for item in items: loc = helpers.parse_action_b(loc, item) x, y, a, b = loc print(f"\nWaypoint: {x}, {y}; Ship: {a}, {b}") answer = abs(a) + abs(b) print(f"\nAnswer: {answer}")
def day21a(): """Day 21a.""" items = helpers.get_input_strings("day21") allergens = {} ingredients = {} for i in items: f, a = i.strip(")").split(" (contains ") foods = [] algns = [] for food in f.strip().split(" "): foods.append(food) for algn in a.split(","): algns.append(algn.strip()) print(foods) print(algns) print("") for allergen in algns: if allergen not in allergens: allergens[allergen] = foods else: allergens[allergen] = list( set(allergens[allergen]).intersection(set(foods))) for food in foods: if food not in ingredients: ingredients[food] = 0 ingredients[food] += 1 print(json.dumps(allergens, indent=2, sort_keys=True)) found = {} while len(found) < len(allergens): for allergen in allergens: i = allergens[allergen] if len(i) == 1: f = i[0] found[f] = allergen for a in allergens: if f in allergens[a]: allergens[a].remove(f) print(json.dumps(found, indent=2, sort_keys=True)) total = 0 for food in ingredients: if food not in found: total += ingredients[food] print(f"Total: {total}") print(",".join(sorted(found, key=lambda x: found[x])))
def day2b(): """Day 2: Password Philosophy.""" items = helpers.get_input_strings("day2") valid = [] for item in items: result = re.findall(r"^([0-9]+)-([0-9]+) (.): (.*)$", item) first, second, character, password = result[0] a = password[int(first) - 1] b = password[int(second) - 1] if (character in [a, b]) and a != b: valid.append(password) print(f"\nValid Passwords: {len(valid)}")
def day7a(): """Day 7a.""" check = "shiny gold" items = helpers.get_input_strings("day7") bags = helpers.get_bags(items) # print(json.dumps(bags, indent=2, sort_keys=True)) valid = [] print("\nValid colors:") for color in bags: if helpers.check_valid_bag(check, color, bags): valid.append(color) print(f" {color}") print(f"\nTotal: {len(valid)}")
def day3b(): """Day 3: Toboggan Trajectory.""" items = helpers.get_input_strings("day3") counts = [] counts.append(helpers.check_slope(1, 1, items)) counts.append(helpers.check_slope(3, 1, items)) counts.append(helpers.check_slope(5, 1, items)) counts.append(helpers.check_slope(7, 1, items)) counts.append(helpers.check_slope(1, 2, items)) result = 1 for count in counts: result *= count print(f"\nResult: {result}")
def day2a(): """Day 2: Password Philosophy.""" items = helpers.get_input_strings("day2") valid = [] for item in items: result = re.findall(r"^([0-9]+)-([0-9]+) (.): (.*)$", item) mincount, maxcount, character, password = result[0] count = 0 for c in password: if c == character: count += 1 if count >= int(mincount) and count <= int(maxcount): valid.append(password) print(f"\nValid Passwords: {len(valid)}")
def day23a(): """Second attempt at day23.""" items = helpers.get_input_strings("day23") cups = items[0] print(f"Cups: {cups}") index = 0 move = 0 while move < 100: move += 1 position = (move - 1) % 9 # get the current cup based on the index current = cups[index] # if we're near the end of the string, rotate it a bit if index > 5: cups = rotate_string(cups, 4) index = cups.index(current) pickup = cups[index + 1:index + 4] newcups = cups[0:index + 1] + cups[index + 4:] destination = get_destination(current, newcups) print(f"\n-- move {move} --") print(f"cups: {gen_cups_display(cups, current, position)}") print(f"pick up: {', '.join(pickup)}") print(f"destination: {destination}") dindex = newcups.index(destination) a = newcups[0:dindex + 1] b = newcups[dindex + 1:] cups = a + pickup + b index = cups.index(current) + 1 if index == 9: index = 0 current = cups[index] print("\n-- final --") print(f"cups: {gen_cups_display(cups, current, position + 1 % 9)}") n = cups.index("1") if n: labels = rotate_string(cups, 9 - n) print(f"\nAnswer: {labels[1:]}")
def day24a(): """Day 24a: Lobby Layout.""" items = helpers.get_input_strings("day24") tiles = {} for i in items: # get steps steps = [] while i: f = i[0] if f in ["e", "w"]: steps.append(f) i = i[1:] else: f = i[0:2] steps.append(f) i = i[2:] print(steps) # run through steps t = Floortile((0, 0), tiles) for d in steps: x, y = t.v if d == "ne": v = (x + 2, y + 2) elif d == "e": v = (x + 4, y) elif d == "se": v = (x + 2, y - 2) elif d == "sw": v = (x - 2, y - 2) elif d == "w": v = (x - 4, y) elif d == "nw": v = (x - 2, y + 2) # visit tile t = Floortile(v, tiles) # print(f"-> {d} {v}") t.flip() print(len(tiles)) black = 0 for v in tiles: t = tiles[v] if t.state: black += 1 print(f"Total Black: {black}")
def day17a(): """Day 17a.""" items = helpers.get_input_strings("day17") cubes = helpers.get_3d_cubes(items) helpers.print_3d_grid(cubes) n = 0 while n < 6: cubes = helpers.run_3d_conway_cubes(cubes) # print_grid(cubes) n += 1 count = 0 for i in cubes: if cubes[i] == "#": count += 1 print(f"Count: {count}")
def day23(): """Day 23a.""" items = helpers.get_input_strings("day23test") cups = [int(x) for x in items[0]] print(f"Cups: {cups}") current = None cups_len = len(cups) for move in range(100): position = move % 9 print(f"\n-- move {move + 1} --") # 1. Find current cup current_ix = (cups.index(current) + 1) % cups_len if current else 0 current = cups[current_ix] print(f"cups: {gen_cups_display(cups, current, position)}") # 2. Pick up cups picked_up = [] for j in range(3): picked_up.append(cups[(current_ix + j + 1) % cups_len]) for p in picked_up: cups.remove(p) # 3. Find destination cup destination = current - 1 or cups_len while destination in picked_up: destination = destination - 1 or cups_len destination_ix = cups.index(destination) print(f"pick up: {', '.join(str(x) for x in picked_up)}") print(f"destination: {destination}") # 4. Rearrange the cups cups = cups[:destination_ix + 1] + picked_up + cups[destination_ix + 1:] ix_1 = cups.index(1) result = cups[ix_1 + 1:] + cups[:ix_1] print(''.join(str(i) for i in result))
def day6a(): """Day 6a.""" items = helpers.get_input_strings("day6") counts = [] group = None for i in items: if not i: counts.append(len(group)) group = {} if not group: group = {} for c in list(i): if c in group: group[c] += 1 else: group[c] = 1 counts.append(len(group)) total = 0 for t in counts: total += t print(f"\nTotal: {total}")
def day8b(): """Day 8a.""" items = helpers.get_input_strings("day8") i = 0 while i < len(items): code = items[i] inst, num = code.split(" ") test = False if inst == "jmp": new = "nop" newitems = list(items) newitems[i] = f"{new} {num}" test = True elif inst == "nop": new = "jmp" newitems = list(items) newitems[i] = f"{new} {num}" test = True if test: print(f"Testing row {i}: {inst} -> {new}") accumulator = helpers.test_boot_code(newitems) print(f"Accumulator: {accumulator}") i += 1
def day4a(): """Day 4.""" items = helpers.get_input_strings("day4") start, stop = items[0].split("-") print(start, stop) count = 0 for i in range(int(start), int(stop) + 1): string = str(i) valid = False for c in [str(x) for x in range(0, 10)]: if c * 2 in string and c * 3 not in string: valid = True if not valid: continue # check for sorted if list(string) != sorted(string): continue print(i) count += 1 print(f"Count: {count}")
def day3a(): """Day 3: Toboggan Trajectory.""" items = helpers.get_input_strings("day3") print(f"Total Items: {len(items)}") trees = helpers.check_slope(3, 1, items) print(f"\nTrees: {trees}")
def day17b(): """Day 17b.""" items = helpers.get_input_strings("day17test")
def day15b(): """Day 15b.""" items = helpers.get_input_strings("day15")[0].split(",") print(items) print(helpers.speak_numbers(items, 30000000))
def day14b(): """Day 14b.""" lines = helpers.get_input_strings("day14") mask = [] mem = {} print(f"Initialize memory: {mem}") def apply_mask(location): """Apply the mask to a binary.""" binary = '{0:036b}'.format(location) print(f"address: {binary} (decimal {location})") binary_list = [] for i in list(binary): binary_list.append(int(i)) n = 0 for x in mask: if x == 1: binary_list[n] = 1 if x == "X": binary_list[n] = "X" n += 1 result = ''.join([str(x) for x in binary_list]) print(f"mask: {get_mask_string(mask)}") print(f"result: {result}") return result def get_permutations(n): """Return all the itertaions of 0 and 1 for n items.""" bits = ["0", "1"] if n == 1: return bits permutations = [] for x in get_permutations(n - 1): for y in bits: permutations.append(x + y) return permutations def get_locations(result): """Return a list of locations based on the floating bits in a result.""" locations = [] floats = [] fmtstring = "" n = 0 f = 0 while n < len(result): x = result[n] if x == "X": floats.append(n) fmtstring += "%s" f += 1 else: fmtstring += str(x) n += 1 locations = [] for p in get_permutations(len(floats)): binary = fmtstring % tuple(list(p)) locations.append(int(binary, 2)) return locations def get_mask_string(mask): """Return the mask as a string.""" return "".join([str(x) for x in mask]) def save_value(integer, result): """Apply the mask.""" print(result, integer) locations = get_locations(result) for loc in locations: mem[loc] = integer def get_mask(mask_string): """Set the mask.""" mask = [] maskmap = {} i = 0 for c in list(mask_string): if c == "X": mask.append("X") else: mask.append(int(c)) maskmap[int(c)] = i i += 1 return mask for line in lines: print() print(line) if re.match(r"mask = .*", line): mask_string = line.replace("mask = ", "") mask = get_mask(mask_string) print(f"Initialize mask: {mask}") elif re.match(r"mem\[.*\] = .*", line): loc, integer = line.replace("mem[", "").replace("]", "").replace(" =", "").split(" ") result = apply_mask(int(loc)) save_value(int(integer), result) print(f"Sum: {sum(mem.values())}")
def day14a(): """Day 14a.""" lines = helpers.get_input_strings("day14") mask = [] mem = {} print(f"Initialize memory: {mem}") def apply_mask(binary): """Apply the mask to a binary.""" binary_list = [] for i in list(binary): binary_list.append(int(i)) n = 0 for x in mask: if x != "X": binary_list[n] = x n += 1 binary = ''.join([str(x) for x in binary_list]) return binary def get_mask_string(mask): """Return the mask as a string.""" return "".join([str(x) for x in mask]) def save_value(integer, loc): """Apply the mask.""" binary = '{0:036b}'.format(integer) print(f"value: {binary} (decimal {integer})") print(f"mask: {get_mask_string(mask)}") result = apply_mask(binary) value = int(result, 2) print(f"result: {result} (decimal {value})") mem[loc] = value def get_mask(mask_string): """Set the mask.""" mask = [] maskmap = {} i = 0 for c in list(mask_string): if c == "X": mask.append("X") else: mask.append(int(c)) maskmap[int(c)] = i i += 1 return mask for line in lines: print() print(line) if re.match(r"mask = .*", line): mask_string = line.replace("mask = ", "") mask = get_mask(mask_string) print(f"Initialize mask: {mask}") elif re.match(r"mem\[.*\] = .*", line): loc, integer = line.replace("mem[", "").replace("]", "").replace(" =", "").split(" ") save_value(int(integer), int(loc)) print(f"Sum: {sum(mem.values())}")
def day23b(): """Day 23b.""" items = helpers.get_input_strings("day23test")
def day24b(): """Day 24b: Lobby Layout.""" items = helpers.get_input_strings("day24test") tiles = {} for i in items: # get steps steps = [] while i: f = i[0] if f in ["e", "w"]: steps.append(f) i = i[1:] else: f = i[0:2] steps.append(f) i = i[2:] # print(steps) # run through steps t = Floortile((0, 0), tiles) for d in steps: x, y = t.v if d == "ne": v = (x + 2, y + 2) elif d == "e": v = (x + 4, y) elif d == "se": v = (x + 2, y - 2) elif d == "sw": v = (x - 2, y - 2) elif d == "w": v = (x - 4, y) elif d == "nw": v = (x - 2, y + 2) # visit tile t = Floortile(v, tiles) # print(f"-> {d} {v}") t.flip() print(f"\nTiles: {len(tiles)}") black = 0 for v in tiles: t = tiles[v] if t.state: black += 1 print(f"Black Tiles: {black}") day = 0 while day < 3: day += 1 # expand tiles for v in dict(tiles): t = tiles[v] if t.state: t.check_neighbors() # get tiles to flip flip = [] for v in dict(tiles): t = tiles[v] if t.state: if t.check_neighbors() == 2: flip.append(t) else: c = t.check_neighbors() if c == 0 or c > 2: flip.append(t) # flip tiles for t in flip: t.flip() # count black tiles black = 0 for v in dict(tiles): t = tiles[v] if t.state: black += 1 print(f"\nDay {day}: {black}") print(f"\nTiles: {len(tiles)}")
def day8a(): """Day 8a.""" items = helpers.get_input_strings("day8") accumulator = helpers.test_boot_code(items) print(f"\nAccumulator: {accumulator}")