resulting_molecules = set() for mol_from, mol_to in replacements: for index in [m.start() for m in re.finditer(mol_from, molecule)]: new_molecule = molecule[:index] + molecule[index:].replace( mol_from, mol_to, 1) resulting_molecules.add(new_molecule) return resulting_molecules example_molecule = "HOH" example_replacements = (("H", "HO"), ("H", "OH"), ("O", "HH"), ("e", "H"), ("e", "O")) print(find_all_resulting_molecules(example_molecule, example_replacements)) u.answer_part_1(len(find_all_resulting_molecules(molecule, replacements))) # # _\/_ # /\ # /\ # / \ # /~~\o # PART ------ /o \ ------ TWO # /~~*~~~\ # o/ o \ # /~~~~~~~~\~` # /__*_______\ # || # \====/ # \__/
# class CaloriesVector(NamedTuple): # a: int # b: str # c: dict # def __mul__(self, other): # pass # from operator import attrgetter # persons.sort() # sorted(persons, key=attrgetter('info.age')) # plus performant que la version lambda # sorted(persons, key=attrgetter('info.age', 'info.taille')) # ha ! va écrire une lambda équivalente # sorted(persons, key=lambda x: x.info.age) size = 100 # 156 849 iterations for size 100 generator = ((x, y, z, size - x - y - z) for x in range(1, size) for y in range(1, size - x) for z in range(1, size - x - y)) maxScore = 0 maxScores500Calories = 0 for row in generator: score = math.prod( [max(0, dot(constraint, row)) for constraint in constraints]) calories = dot(row, caloriesVector) if score > maxScore: maxScore = score if calories == 500 and score > maxScores500Calories: maxScores500Calories = score # print(f'\033[91m'+'a'*row[0]+'\033[92m'+'b'*row[1]+'\033[94m'+'c'*row[2]+'\033[93m'+'d'*row[3]+f'\033[0m {score}') u.answer_part_1(maxScore) u.answer_part_2(maxScores500Calories)
SUBJECT = 7 # part 1 -'*'-.,__,.-'*'-.,__,.-'*'-.,__,.-'*'-.,__,.-'*'-.,__,.-'*'-.,__,.-'*'-.,_ def find_loop_size(public_key: int): value = 1 for loop_size in itertools.count(start=1): value = (value * SUBJECT) % MODULO if value == public_key: return loop_size def find_encryption_key(public_key: int, loop_size_of_other_device: int): return pow(public_key, loop_size_of_other_device, MODULO) u.assert_equals(find_loop_size(5764801), 8) u.assert_equals(find_loop_size(17807724), 11) u.assert_equals(find_encryption_key(5764801, 11), 14897079) card_loop_size = find_loop_size(card_key) u.pink(f"card loop: {card_loop_size}") encryption_key = find_encryption_key(door_key, card_loop_size) u.answer_part_1(encryption_key) # 1018011 too low # part 2 -'*'-.,__,.-'*'-.,__,.-'*'-.,__,.-'*'-.,__,.-'*'-.,__,.-'*'-.,__,.-'*'-.,_
return False return True criteria = { "children": 3, "cats": 7, "samoyeds": 2, "pomeranians": 3, "akitas": 0, "vizslas": 0, "goldfish": 5, "trees": 3, "cars": 2, "perfumes": 1, } parser = r"""Sue\s(\d+)\: # Sue number \s(\w+)\:\s(\d+), # info 1 \s(\w+)\:\s(\d+), # info 2 \s(\w+)\:\s(\d+) # info 3 """ pattern = re.compile(parser, re.X | re.M) for group in pattern.findall(inputStr): sueNumber, carac1, nb1, carac2, nb2, carac3, nb3 = group sue = {carac1: int(nb1), carac2: int(nb2), carac3: int(nb3)} if does_sue_match_criteria_part_1(sue, criteria): u.answer_part_1(sueNumber) if does_sue_match_criteria_part_2(sue, criteria): u.answer_part_2(sueNumber)
after_east_moves.append(new_row) after_south_moves = [[] for _ in range(len(current_step))] for col in range(len(current_step[0])): col_string = "".join(row[col] for row in after_east_moves) col_string = col_string.replace("v.", ".v") column = list(col_string) if after_east_moves[-1][col] == "v" and after_east_moves[0][col] == ".": column[0] = "v" column[-1] = "." changed = True for row, element in enumerate(column): after_south_moves[row].append(element) if not changed: changed = current_step != after_south_moves return after_south_moves, changed def part_1(raw_input): state = [list(row) for row in raw_input.splitlines()] changed = True done_steps = 0 while changed: state, changed = get_next_step(state) done_steps += 1 return done_steps u.assert_equals(part_1(example), 58) u.answer_part_1(part_1(raw_input)) # part 2 -'*'-.,__,.-'*'-.,__,.-'*'-.,__,.-'*'-.,__,.-'*'-.,__,.-'*'-.,__,.-'*'-.,_
elif step == "se": q += 1 s -= 1 elif step == "sw": q -= 1 r += 1 elif step == "nw": q -= 1 s += 1 return int((abs(q) + abs(r) + abs(s)) / 2) for path, distance in examples.items(): u.assert_equals(get_distance_from_path(path), distance) u.answer_part_1(get_distance_from_path(raw_input)) # part 2 -'*'-.,__,.-'*'-.,__,.-'*'-.,__,.-'*'-.,__,.-'*'-.,__,.-'*'-.,__,.-'*'-.,_ def get_further_during_path(path): q, r, s = 0, 0, 0 further = 0 for step in path.split(","): if step == "n": s += 1 r -= 1 elif step == "s": r += 1 s -= 1 elif step == "ne":
dbcfg fgd bdegcaf fgec aegbdf ecdfab fbedc dacgb gdcebf gf | cefg dcbef fcge gbcadfe bdfegc cbegaf gecbf dfcage bdacg ed bedf ced adcbefg gebcd | ed bcgafe cdgba cbgef egadfb cdbfeg cegd fecab cgb gbdefca cg fgcdab egfdb bfceg | gbdfcae bgc cg cgb gcafb gcf dcaebfg ecagb gf abcdeg gaef cafbge fdbac fegbdc | fgae cfgab fg bagce""" # part 1 -'*'-.,__,.-'*'-.,__,.-'*'-.,__,.-'*'-.,__,.-'*'-.,__,.-'*'-.,__,.-'*'-.,_ def count_easy_letters_in_output(raw_input): outputs = [row.split(" | ")[1] for row in raw_input.splitlines()] outputs = tuple(itertools.chain(*(r.split() for r in outputs))) return len(tuple(filter(lambda x: len(x) in (2, 4, 3, 7), outputs))) u.assert_equals(count_easy_letters_in_output(example_input), 26) u.answer_part_1(count_easy_letters_in_output(raw_input)) # part 2 -'*'-.,__,.-'*'-.,__,.-'*'-.,__,.-'*'-.,__,.-'*'-.,__,.-'*'-.,__,.-'*'-.,_ def output_sequence_from_entry(entry): all_sequences = tuple("".join(sorted(x)) for x in entry.split(" | ")[0].split(" ")) outputs = tuple("".join(sorted(x)) for x in entry.split(" | ")[1].split(" ")) one = next(x for x in all_sequences if len(x) == 2) four = next(x for x in all_sequences if len(x) == 4) seven = next(x for x in all_sequences if len(x) == 3) eight = next(x for x in all_sequences if len(x) == 7)
mask = line[7:] elif line.startswith("mem"): address, value = tuple( map(int, re.findall(MEMORY_INSTRUCTION, line)[0])) bits = bits_from_integer(value) for i, mask_val in enumerate(reversed(mask)): if mask_val != "X": bits[i] = mask_val memory[address] = bits_to_integer(bits) return sum(memory.values()) u.assert_equals(parse_input_to_program(example_program), 165) u.assert_equals(parse_input_to_program(raw_input), 13496669152158) u.answer_part_1(parse_input_to_program(raw_input)) # 13496669152158 # part 2 -'*'-.,__,.-'*'-.,__,.-'*'-.,__,.-'*'-.,__,.-'*'-.,__,.-'*'-.,__,.-'*'-.,_ def parse_input_to_program_v2(raw_input): memory = defaultdict(lambda: 0) for line in raw_input.splitlines(): if line.startswith("mask"): mask = line[7:] elif line.startswith("mem"): address, target_value = tuple( map(int, re.findall(MEMORY_INSTRUCTION, line)[0])) bits = bits_from_integer(address)
def find_corner_tiles(raw_tileset): contacts = build_contact_graph(raw_tileset) # in contacts graph: # - insider tiles have 4 neighbors # - border tiles have 3 neighbors # - corner tiles have 2 neighbors return [ node for node in contacts.nodes() if len(list(nx.neighbors(contacts, node))) == 2 ] u.assert_equals(prod(find_corner_tiles(example_input)), 20899048083289) u.answer_part_1(prod(find_corner_tiles(raw_input))) # part 2 -'*'-.,__,.-'*'-.,__,.-'*'-.,__,.-'*'-.,__,.-'*'-.,__,.-'*'-.,__,.-'*'-.,_ TOP = 0 RIGHT = 1 BOTTOM = 2 LEFT = 3 DIRECTIONS = ("Top", "Right", "Bottom", "Left") SEA_MONSTER = """ _ * __ __ ^^> \ / \ / \ /
next_sources = evolve_grid(grid, *source) sources.extend(next_sources) remove_floating_water(grid) def count_wet_squares(grid: dict): min_x, max_x, min_y, max_y = find_min_max_clay_coordinates(grid) return sum(1 for x in range(min_x, max_x + 1) for y in range(min_y, max_y + 1) if grid[x, y] in ("~", "|")) def count_resting_water_squares(grid: dict): min_x, max_x, min_y, max_y = find_min_max_clay_coordinates(grid) return sum(1 for x in range(min_x, max_x + 1) for y in range(min_y, max_y + 1) if grid[x, y] == "~") example_grid = parse_input(example_input) evolve_grid_until_everything_is_filled(example_grid) u.assert_equals(count_wet_squares(example_grid), 57) grid = parse_input(raw_input) evolve_grid_until_everything_is_filled(grid) draw_grid(grid) u.answer_part_1(count_wet_squares(grid)) # 37277 is too low # 38364 good answer, I was missing the "every x coordinate is valid" u.assert_equals(count_resting_water_squares(example_grid), 29) u.answer_part_2(count_resting_water_squares(grid))
if neighbor in path and self.is_small(neighbor): continue self.visit(neighbor, path.copy()) pf = PathFinder(example_10paths) u.assert_equals(pf.find_all_paths(), 10) pf = PathFinder(example_19paths) u.assert_equals(pf.find_all_paths(), 19) pf = PathFinder(example_226paths) u.assert_equals(pf.find_all_paths(), 226) pf = PathFinder(raw_input) u.answer_part_1(pf.find_all_paths()) # part 2 -'*'-.,__,.-'*'-.,__,.-'*'-.,__,.-'*'-.,__,.-'*'-.,__,.-'*'-.,__,.-'*'-.,_ class ImprovedPathFinder(PathFinder): def visit(self, node, path, one_small_cave_visited_twice=False): path.append(node) if node == "end": self.finished_path(path) return for neighbor in nx.neighbors(self.graph, node): if neighbor == "start": continue if ( one_small_cave_visited_twice
generate_regex_for_rule(subrule, rules) for subrule in rule.split(" | ")) + ")") def check_validity_for_messages(raw_input: str): raw_rules, raw_messages = raw_input.split("\n\n") ruleset = generate_dict_from_raw_rules(raw_rules) regex_zero = re.compile( "^" + generate_regex_for_rule(ruleset["0"], ruleset) + "$", re.MULTILINE, ) return len(regex_zero.findall(raw_messages)) u.assert_equals(check_validity_for_messages(example_input), 2) u.answer_part_1(check_validity_for_messages(raw_input)) # part 2 -'*'-.,__,.-'*'-.,__,.-'*'-.,__,.-'*'-.,__,.-'*'-.,__,.-'*'-.,__,.-'*'-.,_ IMBRICATION_LEVEL = 5 raw_rules, _ = raw_input.split("\n\n") ruleset = generate_dict_from_raw_rules(raw_rules) def generate_regex_for_rule_part_2(rule: str, rules: dict, idx=0): if len(rule) == 3 and rule.count('"') == 2: return rule[1] if idx == "8" and rule == "42": # 8: 42 | 42 8 => 42 | 42 42 | 42 42 42… so.. hop! ⤵︎ return generate_regex_for_rule_part_2("42", rules) + "+"
] def part_1(raw_input): algorithm, lines = parse_input(raw_input) if algorithm[0] == "1": default_on_odd_turns = "1" else: default_on_odd_turns = "0" lines = calculate_next_grid(lines, algorithm, default="0") lines = calculate_next_grid(lines, algorithm, default=default_on_odd_turns) return sum(row.count("1") for row in lines) u.assert_equals(part_1(example), 35) u.answer_part_1(part_1(raw_input)) # 5464! YAY # part 2 -'*'-.,__,.-'*'-.,__,.-'*'-.,__,.-'*'-.,__,.-'*'-.,__,.-'*'-.,__,.-'*'-.,_ def part_2(raw_input): algorithm, lines = parse_input(raw_input) if algorithm[0] == "1": default_on_odd_turns = "1" else: default_on_odd_turns = "0" for turn in range(50): print("█" * turn, turn, end="\r") default = default_on_odd_turns if turn % 2 == 1 else "0" lines = calculate_next_grid(lines, algorithm, default=default) print("\ndone!")
memorization.update( {number: [rank] for rank, number in enumerate(starting_numbers, 1)}) last_spoken_number = starting_numbers[-1] for rank in range(len(starting_numbers) + 1, n + 1): if rank % 1000 == 0: print(rank, end="\r") if len(memorization[last_spoken_number]) >= 2: last_spoken_number = rank - 1 - memorization[last_spoken_number][-2] else: last_spoken_number = 0 if rank == n: return last_spoken_number # maybe for memory optimization we could shorten the list here, # to keep only the 2 last indexes. But it worked for both parts # without the optimization, so… memorization[last_spoken_number].append(rank) u.assert_equals(find_nth_number_in_drinking_game((0, 3, 6), 10), 0) for starting_numbers, expected in examples.items(): u.assert_equals(find_nth_number_in_drinking_game(starting_numbers, 2020), expected) u.answer_part_1(find_nth_number_in_drinking_game(my_input, 2020)) # part 2 -'*'-.,__,.-'*'-.,__,.-'*'-.,__,.-'*'-.,__,.-'*'-.,__,.-'*'-.,__,.-'*'-.,_ u.answer_part_2(find_nth_number_in_drinking_game(my_input, 30000000))
print("duh?") tiling[row, col] *= -1 return tiling def count_black_tiles(grid: dict): return list(grid.values()).count(-1) example_tiling = extract_black_tiles(example) u.assert_equals(count_black_tiles(example_tiling), 10) tiling = extract_black_tiles(raw_input) u.assert_equals(count_black_tiles(tiling), 317) u.answer_part_1(count_black_tiles(tiling)) # part 2 -'*'-.,__,.-'*'-.,__,.-'*'-.,__,.-'*'-.,__,.-'*'-.,__,.-'*'-.,__,.-'*'-.,_ def count_black_neighbors(grid: defaultdict, coordinates: tuple): return [ grid[coordinates] for coordinates in get_neighbors_coordinates(coordinates) ].count(-1) def get_neighbors_coordinates(coordinates: tuple): row, col = coordinates neighbors_offsets = ((0, 2), (0, -2), (1, 1), (1, -1), (-1, -1), (-1, 1)) for row_offset, col_offset in neighbors_offsets: yield row + row_offset, col + col_offset
state_graphs.add_edge( current_state, new_state, weight=nx.shortest_path_length( distances, position, target, weight="weight" ) * COSTS[letter], ) # print('────────────────────────────────────────────') # previous = None # for intermediary in nx.shortest_path( # state_graphs, initial_state, TARGET, weight="weight" # ): # debug_state(intermediary) # if previous: # print(state_graphs.edges[previous, intermediary]) # previous = intermediary return nx.shortest_path_length(state_graphs, initial_state, TARGET, weight="weight") u.assert_equals(part_1(example_state), 44169) # state_with_a_D_who_can_go_home = ('A', 'B', None, 'C', 'A', 'D', 'C', 'B', 'D', 'D', 'A', None, 'C', 'B', 'D', None, 'B', 'A', 'C', None, None, None, None) # part_1(state_with_a_D_who_can_go_home) my_initial_state = ( (None,) * 7 + tuple("CDDB") + tuple("DCBA") + tuple("ABAD") + tuple("BACC") ) u.answer_part_1(part_1(my_initial_state)) # part 2 -'*'-.,__,.-'*'-.,__,.-'*'-.,__,.-'*'-.,__,.-'*'-.,__,.-'*'-.,__,.-'*'-.,_
u.assert_equals(get_place_coordinates("BFFFBBFRRR"), (70, 7)) u.assert_equals(get_place_coordinates("FFFBBBFRRR"), (14, 7)) u.assert_equals(get_place_coordinates("BBFFBBFRLL"), (102, 4)) u.assert_equals(get_place_id(70, 7), 567) u.assert_equals(get_place_id(14, 7), 119) u.assert_equals(get_place_id(102, 4), 820) place_ids = [ get_place_id(*get_place_coordinates(boarding_pass)) for boarding_pass in raw_input.splitlines() ] u.answer_part_1(max(place_ids)) # part 2 -'*'-.,__,.-'*'-.,__,.-'*'-.,__,.-'*'-.,__,.-'*'-.,__,.-'*'-.,__,.-'*'-.,_ sorted_place_ids = sorted(place_ids) for i in range(1, len(sorted_place_ids) - 1): seat_id = sorted_place_ids[i] next_seat_id = sorted_place_ids[i + 1] if seat_id + 1 != next_seat_id: u.answer_part_2(seat_id + 1) break # another method using a comprehension, but i'm not sure it's clearer for seat_id, next_seat_id in ((sorted_place_ids[i:i + 2]) for i in range(len(sorted_place_ids) - 1)):
def get_power_consumption(raw_input): rows = raw_input.splitlines() first_row = rows[0] width = len(first_row) length = len(rows) gamma_string = "".join( "0" if [r[bit] for r in rows].count("0") > length / 2 else "1" for bit in range(width)) epsilon_string = "".join("0" if c == "1" else "1" for c in gamma_string) return int(gamma_string, 2) * int(epsilon_string, 2) u.assert_equals(get_power_consumption(raw_example), 198) u.answer_part_1(get_power_consumption(raw_input)) # part 2 -'*'-.,__,.-'*'-.,__,.-'*'-.,__,.-'*'-.,__,.-'*'-.,__,.-'*'-.,__,.-'*'-.,_ def get_life_support_rating(raw_input): rows = raw_input.splitlines() first_row = rows[0] width = len(first_row) length = len(rows) oxygen = rows.copy() co2 = rows.copy() for bit in range(width): o2_sum = sum(int(r[bit]) for r in oxygen) o2_criteria = str(int(o2_sum >= len(oxygen) / 2)) oxygen = [r for r in oxygen if r[bit] == o2_criteria]
x, y, z = coordinates return -grid[x, y, z] + sum(grid[xn, yn, zn] for xn in range(x - 1, x + 2) for yn in range(y - 1, y + 2) for zn in range(z - 1, z + 2)) def boot_grid_for_6_cycles(raw_input): grid = build_grid_from_input(raw_input) for i in range(6): grid = build_new_grid(grid) return sum(grid.values()) u.assert_equals(boot_grid_for_6_cycles(example_input), 112) u.answer_part_1(boot_grid_for_6_cycles(raw_input)) # part 2 -'*'-.,__,.-'*'-.,__,.-'*'-.,__,.-'*'-.,__,.-'*'-.,__,.-'*'-.,__,.-'*'-.,_ # Basically the same as part 1, with 4 dimensions: # I copy-pasted and added "hyper" in function names. def build_hyper_grid_from_input(input): rows = input.strip().splitlines() grid = defaultdict( int) # grid[something] will be 0 if <something> is not defined for y, row in enumerate(rows): for x, char in enumerate(row): if char == "#": grid[x, y, 0, 0] = 1
elif length <= 1: list = list else: list = list[length - 1::-1] + list[length:] list = rotate(list, skip + length) total_rotation += skip + length return rotate(list, len(list) - (total_rotation % len(list))) l = list(range(5)) u.assert_equals(apply_lengths(l, (3, 4, 1, 5)), [3, 4, 2, 1, 0]) l = list(range(256)) lengths = [int(x) for x in raw_input.split(",")] l = apply_lengths(l, lengths) u.answer_part_1(l[0] * l[1]) # 54990 too high # part 2 -'*'-.,__,.-'*'-.,__,.-'*'-.,__,.-'*'-.,__,.-'*'-.,__,.-'*'-.,__,.-'*'-.,_ def part_2(raw_input): lengths = [ord(char) for char in raw_input] + [17, 31, 73, 47, 23] sparse_hash = apply_lengths(list(range(256)), lengths * 64) dense_hash = [ reduce(xor, sparse_hash[sl * 16:sl * 16 + 16]) for sl in range(16) ] return "".join(hex(number)[2:].rjust(2, "0") for number in dense_hash) tests = {
height = len(grid) if axis == "y": # horizontal fold if value != (height - 1) / 2: return new_grid = [[(grid[y][x] or grid[height - 1 - y][x]) for x in range(width)] for y in range(int((height - 1) / 2))] elif axis == "x": # vertical fold if value != ((width - 1) / 2): return new_grid = [[(row[x] or row[width - 1 - x]) for x in range(int((width - 1) / 2))] for row in grid] return new_grid grid, folds = construct_grid(example) new_grid = fold_grid(grid, folds[0]) new_grid = fold_grid(new_grid, folds[1]) grid, folds = construct_grid(raw_input) new_grid = fold_grid(grid, folds.pop(0)) u.answer_part_1(sum(sum(1 if val else 0 for val in row) for row in new_grid)) # part 2 -'*'-.,__,.-'*'-.,__,.-'*'-.,__,.-'*'-.,__,.-'*'-.,__,.-'*'-.,__,.-'*'-.,_ for fold in folds: new_grid = fold_grid(new_grid, fold) u.answer_part_2("RCPLAKHL") debug_grid(new_grid)
new_scores = sum(score[pos] for pos in elves_position) score.extend(map(int, list(str(new_scores)))) elves_position = [(pos + score[pos] + 1) % len(score) for pos in elves_position] # debug_position(score, elves_position) if len(score) >= n + 10: break return "".join(map(str, (score[x] for x in range(n, n + 10)))) u.assert_equals(look_for_ten_recipes_after_nth(9), "5158916779") u.assert_equals(look_for_ten_recipes_after_nth(5), "0124515891") u.assert_equals(look_for_ten_recipes_after_nth(2018), "5941429882") u.assert_equals(look_for_ten_recipes_after_nth(18), "9251071085") u.answer_part_1(look_for_ten_recipes_after_nth(int(puzzle_input))) # part 2 -'*'-.,__,.-'*'-.,__,.-'*'-.,__,.-'*'-.,__,.-'*'-.,__,.-'*'-.,__,.-'*'-.,_ def look_for_pattern_in_recipes(pattern: str): score = "37" elves_position = [0, 1] init = time() for i in count(): if i % 10000 == 0: print(f"round {i} - len = {len(score)} - time = {time() - init}", end="\r") new_scores = str(sum(int(score[pos]) for pos in elves_position)) score += new_scores elves_position = [(pos + int(score[pos]) + 1) % len(score)
iyr:2013 ecl:amb cid:350 eyr:2023 pid:028048884 hcl:#cfa07d byr:1929 hcl:#ae17e1 iyr:2013 eyr:2024 ecl:brn pid:760753108 byr:1931 hgt:179cm hcl:#cfa07d eyr:2025 pid:166559648 iyr:2011 ecl:brn hgt:59in """ u.assert_equals(count_valid_passports_in_batch(example_batch), 2) u.answer_part_1(count_valid_passports_in_batch(raw_input)) # part 2 -'*'-.,__,.-'*'-.,__,.-'*'-.,__,.-'*'-.,__,.-'*'-.,__,.-'*'-.,__,.-'*'-.,_ # criteria which are easily regexable: EASY_CRITERIA = tuple( map( lambda p: re.compile(p, re.M), ( # hcl (Hair Color) - a # followed by exactly six characters 0-9 or a-f. # do the elves really define their hair color using hexcodes?? r"hcl:#[0-9a-f]{6}\s", # ecl (Eye Color) - exactly one of: amb blu brn gry grn hzl oth. r"ecl:(amb|blu|brn|gry|grn|hzl|oth)\s", # THIS ---------------^ # pid (Passport ID) - a nine-digit number, including leading zeroes.
for row in raw_input.splitlines(): value = int(row[-1:]) dir = row[0] if dir == "f": x += value elif dir == "u": depth -= value if depth < 0: print("uh oh, flying submarine??") elif dir == "d": depth += value return x * depth u.assert_equals(find_where_its_going(raw_example), 150) u.answer_part_1(find_where_its_going(raw_input)) # part 2 -'*'-.,__,.-'*'-.,__,.-'*'-.,__,.-'*'-.,__,.-'*'-.,__,.-'*'-.,__,.-'*'-.,_ def calculate_with_aim(raw_input): x = 0 depth = 0 aim = 0 for row in raw_input.splitlines(): value = int(row[-1:]) dir = row[0] if dir == "f": x += value depth += value * aim elif dir == "u":
from itertools import product from monad import monad import utils as u biggest_number = 0 for a in range(1, 10): print(f'{("▓" * a).ljust(10, "░")} biggestnumber = {biggest_number}', end="\r") for b, c, d, e, f, g, h, i, j, k, l, m, n in product(range(1, 10), repeat=13): _, _, _, z = monad(a, b, c, d, e, f, g, h, i, j, k, l, m, n) if z == 0: number = int("".join((a, b, c, d, e, f, g, h, i, j, k, l, m, n))) if number > biggest_number: biggest_number = number print( f'{("▓" * a).ljust(10, "░")} biggestnumber = {biggest_number}', end="\r", ) print("") u.answer_part_1(biggest_number)
def compute_scanning_error_rate(raw_notes, valid_values): rows = raw_notes.splitlines() nearby_tickets_row = rows.index("nearby tickets:") invalid_values = [] for raw_ticket in rows[nearby_tickets_row + 1:]: invalid_values.extend(value for value in map(int, raw_ticket.split(",")) if value not in valid_values) return sum(invalid_values) valid_values = extract_valid_values_from_raw_input(example_input) u.assert_equals(compute_scanning_error_rate(example_input, valid_values), 71) my_valid_values = extract_valid_values_from_raw_input(raw_input) u.answer_part_1(compute_scanning_error_rate(raw_input, my_valid_values)) # 16908 too low: i will try use a list instead of a set # part 2 -'*'-.,__,.-'*'-.,__,.-'*'-.,__,.-'*'-.,__,.-'*'-.,__,.-'*'-.,__,.-'*'-.,_ def extract_valid_tickets(raw_notes, valid_values): rows = raw_notes.splitlines() nearby_tickets_row = rows.index("nearby tickets:") for raw_ticket in rows[nearby_tickets_row + 1:]: int_ticket = tuple(map(int, raw_ticket.split(","))) if all(value in valid_values for value in int_ticket): yield (int_ticket) def extract_my_ticket_from_raw_input(raw_input):
u.assert_equals(sumOfAllNumbers("[1,2,3]"), 6) u.assert_equals(sumOfAllNumbers('{"a":2,"b":4}'), 6) # [[[3]]] and {"a":{"b":4},"c":-1} both have a sum of 3. u.assert_equals(sumOfAllNumbers("[[[3]]]"), 3) u.assert_equals(sumOfAllNumbers('{"a":{"b":4},"c":-1}'), 3) # {"a":[-1,1]} and [-1,{"a":1}] both have a sum of 0. u.assert_equals(sumOfAllNumbers('{"a":[-1,1]}'), 0) u.assert_equals(sumOfAllNumbers('[-1,{"a":1}]'), 0) # [] and {} both have a sum of 0. u.assert_equals(sumOfAllNumbers("[]"), 0) u.assert_equals(sumOfAllNumbers(r"{}"), 0) u.answer_part_1(sumOfAllNumbers(inputStr)) u.assert_equals(4, sumOfAllNumbers(removeRedObjects('[1,{"c":"red","b":2},3]'))) u.assert_equals( sumOfAllNumbers(removeRedObjects('{"d":"red","e":[1,2,3,4],"f":5}')), 0) inputStrWithoutRed = removeRedObjects(inputStr) u.answer_part_2(sumOfAllNumbers(inputStrWithoutRed)) # part2 85717 too high # part2 68466 yay! # Ignore any object (and all of its children) which has any property with the value "red". # Do this only for objects ({...}), not arrays ([...]). # [1,2,3] still has a sum of 6. # [1,{"c":"red","b":2},3] now has a sum of 4, because the middle object is ignored.
r"([a-z]+) (inc|dec) (-?\d+) if ([a-z]+) ([<>=!]+) (-?\d+)") registries = defaultdict(lambda: 0) for row in raw_input.splitlines(): m = reg.match(row) groups = m.groups() if interpret_condition(groups[3:], registries): registry, action, value = groups[:3] if action == "dec": registries[registry] -= int(value) elif action == "inc": registries[registry] += int(value) return max(registries.values()) u.assert_equals(interpret_instructions(example), 1) u.answer_part_1(interpret_instructions(raw_input)) # part 2 -'*'-.,__,.-'*'-.,__,.-'*'-.,__,.-'*'-.,__,.-'*'-.,__,.-'*'-.,__,.-'*'-.,_ def interpret_instructions_part_2(raw_input): reg = re.compile( r"([a-z]+) (inc|dec) (-?\d+) if ([a-z]+) ([<>=!]+) (-?\d+)") registries = defaultdict(lambda: 0) max_ever = 0 for row in raw_input.splitlines(): m = reg.match(row) groups = m.groups() if interpret_condition(groups[3:], registries): registry, action, value = groups[:3] if action == "dec":
example_cups = deque(map(int, list(example_labeling))) example_cups = crab_moves_cups(example_cups) u.assert_equals("".join(map(str, example_cups)), "837419265") my_cups = deque(map(int, list(my_labeling))) cups_after_100_moves = crab_moves_cups(my_cups, 100) index_of_one = cups_after_100_moves.index(1) cups_after_100_moves.rotate(-index_of_one) # put 1 at the beginning of the deque cups_after_100_moves.popleft() # remove the one answer_part_1 = "".join(map(str, cups_after_100_moves)) u.assert_equals(answer_part_1, "25368479") u.answer_part_1(answer_part_1) # # part 2 -'*'-.,__,.-'*'-.,__,.-'*'-.,__,.-'*'-.,__,.-'*'-.,__,.-'*'-.,__,.-'*'-.,_ def build_chained_list(seed: str, length: int): """instead of storing every cup in order, store every cup with the label of the next cup in the circle""" d = dict() seed = list(map(int, list(seed))) current = seed[0] for i, value in enumerate(seed[:-1]): d[value] = seed[i + 1] if length > len(seed): # last cup of the seed is next to the first "extension" cup d[seed[-1]] = len(seed) + 1
# print(f"------ ROUND {i} -----------") army.targeting_phase() something_happened = army.attack_phase() counted_groups = dict(army.counting_groups()) if not something_happened: print("nothing happens") break # print(counted_groups) if 0 in counted_groups.values(): break return max(counted_groups.values()) u.assert_equals(fight(example), 5216) u.answer_part_1(fight(raw_input)) # 30454 too high # 25241 too high # 25241 again # 23385 ! # part 2 -'*'-.,__,.-'*'-.,__,.-'*'-.,__,.-'*'-.,__,.-'*'-.,__,.-'*'-.,__,.-'*'-.,_ def boosted_fight(input_str, boost): army = Army(f"xxxx") side = "Immune System" for row in filter(None, input_str.splitlines()): if row == "Immune System:": side = "Immune System" elif row == "Infection:":