def score_incomplete_lines(code: List[str]) -> int: incomplete_lines = get_incomplete_lines(code) scores = [] for incomplete_line in incomplete_lines: completed_line = complete_line(incomplete_line) scores.append(line_score(completed_line, incomplete_line)) return sorted(scores)[len(scores) // 2] ### TEST test_code = '''[({(<(())[]>[[{[]{<()<>> [(()[<>])]({[<{<<[]>>( {([(<{}[<>[]}>{[]{[(<()> (((({<>}<{<{<>}{[]{[]{} [[<[([]))<([[{}[[()]]] [{[{({}]{}}([{[{{{}}([] {<[[]]>}<{[{[{[]{()[[[] [<(<(<(<{}))><([]([]() <{([([[(<>()){}]>(<<{{ <{([{{}}[<[[[<>{}]]]>[]]'''.split('\n') assert score_corrupted_lines(test_code) == 26397 assert complete_line('[({(<(())[]>[[{[]{<()<>>') == '[({(<(())[]>[[{[]{<()<>>}}]])})]' assert score_incomplete_lines(test_code) == 288957 ### THE REAL THING code = read_input_lines(10) print(f'Part 1: {score_corrupted_lines(code)}') print(f'Part 2: {score_incomplete_lines(code)}')
shiny gold bags contain 1 dark olive bag, 2 vibrant plum bags. dark olive bags contain 3 faded blue bags, 4 dotted black bags. vibrant plum bags contain 5 faded blue bags, 6 dotted black bags. faded blue bags contain no other bags. dotted black bags contain no other bags.'''.split('\n') regs = parse_regulations(sample_regulations) sample_gold_containers = bags_that_can_contain(regs, 'shiny gold') assert len(sample_gold_containers) == 4 assert ('bright white' in sample_gold_containers and 'muted yellow' in sample_gold_containers and 'dark orange' in sample_gold_containers and 'light red' in sample_gold_containers) assert count_required_bags(regs, 'shiny gold') == 32 sample_regulations = '''shiny gold bags contain 2 dark red bags. dark red bags contain 2 dark orange bags. dark orange bags contain 2 dark yellow bags. dark yellow bags contain 2 dark green bags. dark green bags contain 2 dark blue bags. dark blue bags contain 2 dark violet bags. dark violet bags contain no other bags.'''.split('\n') regs = parse_regulations(sample_regulations) assert count_required_bags(regs, 'shiny gold') == 126 ### THE REAL THING ####################################################################### regulations = helper.read_input_lines(7) regs = parse_regulations(regulations) gold_containers = bags_that_can_contain(regs, 'shiny gold') print('Part 1:', len(gold_containers)) print('Part 2:', count_required_bags(regs, 'shiny gold'))
if len(aunt_things_not_on_tape) > 0: continue match = True for thing in ticker_tape: if thing in aunt_things and match_func(aunt_things, ticker_tape, thing): match = False break if match: candidate_aunts.append(aunt_num) return candidate_aunts aunts_sue = parse_aunts(helper.read_input_lines(16)) ticker_tape = dict(children=3, cats=7, samoyeds=2, pomeranians=3, akitas=0, vizslas=0, goldfish=5, trees=3, cars=2, perfumes=1) print('Part 1:', find_aunt(ticker_tape, aunts_sue)) print('Part 1:', find_aunt(ticker_tape, aunts_sue, matches_range))
self.memory[this_address] = value ### TESTS ############################### sample_program = '''mask = XXXXXXXXXXXXXXXXXXXXXXXXXXXXX1XXXX0X mem[8] = 11 mem[7] = 101 mem[8] = 0'''.split('\n') initializer = Initializer() initializer.run_program(sample_program) assert sum(initializer.memory.values()) == 165 sample_program = '''mask = 000000000000000000000000000000X1001X mem[42] = 100 mask = 00000000000000000000000000000000X0XX mem[26] = 1'''.split('\n') initializer = InitializerV2() initializer.run_program(sample_program) assert sum(initializer.memory.values()) == 208 ### THE REAL THING ###################### program = helper.read_input_lines(14) initializer = Initializer() initializer.run_program(program) print('Part 1:', sum(initializer.memory.values())) initializer = InitializerV2() initializer.run_program(program) print('Part 2:', sum(initializer.memory.values()))
def infer_loop_size(public_key): loop_size = 1 value = 1 while True: value *= 7 value = value % divisor if value == public_key: return loop_size if loop_size % 10_000 == 0: print(loop_size, value) loop_size += 1 assert transform(7, 8) == 5764801 assert transform(7, 11) == 17807724 assert infer_loop_size(5764801) == 8 assert infer_loop_size(17807724) == 11 assert transform(17807724, 8) == transform(5764801, 11) assert transform(17807724, 8) == 14897079 public_keys = [int(k) for k in helper.read_input_lines(25)] loop_size = infer_loop_size(public_keys[0]) print('Part 1:', transform(public_keys[1], loop_size))
def get_ext_dist(cities, p2p_distances, ext='min'): if ext == 'min': ext_dist = sum(p2p_distances[k] for k in p2p_distances) else: ext_dist = -1 for candidate_city_list in permutations(cities, len(cities)): candidate_dist = 0 for c1, c2 in zip(candidate_city_list[:-1], candidate_city_list[1:]): city_pair = tuple(sorted([c1, c2])) candidate_dist += p2p_distances[city_pair] if (ext == 'min' and candidate_dist < ext_dist) or ( ext == 'max' and candidate_dist > ext_dist): ext_dist = candidate_dist return ext_dist example_distances = '''London to Dublin = 464 London to Belfast = 518 Dublin to Belfast = 141'''.split('\n') cities, p2p_distances = parse_distances(example_distances) assert get_ext_dist(cities, p2p_distances) == 605 distances = helper.read_input_lines(9) cities, p2p_distances = parse_distances(distances) print('Part 1:', get_ext_dist(cities, p2p_distances)) print('Part 2:', get_ext_dist(cities, p2p_distances, 'max'))
sample_output = '''35 20 15 25 47 40 62 55 65 95 102 117 150 182 127 219 299 277 309 576'''.split('\n') sample_output = parse_output(sample_output) assert find_first_invalid_number(sample_output, 5) == 127 assert find_contiguous_group_that_sums_to(127, sample_output) == 62 output = parse_output(helper.read_input_lines(9)) first_invalid_number = find_first_invalid_number(output) print('First invalid number:', first_invalid_number) print('Weakness is:', find_contiguous_group_that_sums_to(first_invalid_number, output))
n_chars += len(a) return n_chars def characters_newly_encoded(lines): n_chars = 0 for line in lines: a = '"' + line.replace('\\', r'\\').replace(r'"', r'\"') + '"' n_chars += len(a) return n_chars example_file = r'''"" "abc" "aaa\"aaa" "\x27"'''.split('\n') assert characters_in_code(example_file) == 23 assert characters_in_memory(example_file) == 11 real_file = helper.read_input_lines(8) print('Part 1:', characters_in_code(real_file) - characters_in_memory(real_file)) print('Part 2:', characters_newly_encoded(real_file) - characters_in_code(real_file))
'acedgfb cdfbe gcdfa fbcad dab cefabd cdfgeb eafb cagedb ab | cdfeb fcadb cdfeb cdbaf' ] small_test_signal_patterns, small_test_output_values = parse_input( small_test_input) small_test_pattern = deduce_pattern(small_test_signal_patterns[0]) small_test_output = decode_output(small_test_output_values[0], small_test_pattern) assert small_test_output == 5353 test_input = '''be cfbegad cbdgef fgaecd cgeb fdcge agebfd fecdb fabcd edb | fdgacbe cefdb cefbgd gcbe edbfga begcd cbg gc gcadebf fbgde acbgfd abcde gfcbed gfec | fcgedb cgb dgebacf gc fgaebd cg bdaec gdafb agbcfd gdcbef bgcad gfac gcb cdgabef | cg cg fdcagb cbg fbegcd cbd adcefb dageb afcb bc aefdc ecdab fgdeca fcdbega | efabcd cedba gadfec cb aecbfdg fbg gf bafeg dbefa fcge gcbea fcaegb dgceab fcbdga | gecf egdcabf bgf bfgea fgeab ca afcebg bdacfeg cfaedg gcfdb baec bfadeg bafgc acf | gebdcfa ecba ca fadegcb 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'''.split( '\n') test_signal_patterns, test_output_values = parse_input(test_input) assert count_unique_digits(test_output_values) == 26 assert sum_output(test_signal_patterns, test_output_values) == 61229 ### THE REAL THING input_lines = read_input_lines(8) signal_patterns, output_values = parse_input(input_lines) print(f'Part 1: {count_unique_digits(output_values)}') print(f'Part 2: {sum_output(signal_patterns, output_values)}')
assert bin2dec('10110') == 22 test_report = '''00100 11110 10110 10111 10101 01111 00111 11100 10000 11001 00010 01010'''.split('\n') assert calculate_rate(test_report, 'gamma') == 22 assert calculate_rate(test_report, 'epsilon') == 9 print(get_oxygen_generator_rating(test_report)) print(get_co2_scrubber_rating(test_report)) assert get_oxygen_generator_rating(test_report) == 23 assert get_co2_scrubber_rating(test_report) == 10 ##### THE REAL THING report = read_input_lines(3) power_consumption = get_power_consumption(report) print(f'Part 1: {power_consumption}') life_support_rating = get_life_support_rating(report) print(f'Part 2: {life_support_rating}')
lights_on += sum(1 for light in row if light == ON) return lights_on def update_many(light_map, n_steps, stuck_corners=False): updated_map = light_map for _ in range(n_steps): updated_map = update_light_map(updated_map, stuck_corners) return updated_map def get_corner_coords(light_map): return [(0, 0), (len(light_map) - 1, 0), (len(light_map) - 1, len(light_map[0]) - 1), (0, len(light_map[0]) - 1)] def turn_on_corners(light_map): corners = get_corner_coords(light_map) for row_num, col_num in corners: light_map[row_num][col_num] = ON light_map = parse_map(helper.read_input_lines(18)) updated_map = update_many(light_map, 100) print('Part 1:', count_lights_on(updated_map)) turn_on_corners(light_map) updated_map = update_many(light_map, 100, True) print('Part 2:', count_lights_on(updated_map))
49 45 19 38 39 11 1 32 25 35 8 17 7 9 4 2 34 10 3'''.split('\n') sample_adapters = parse_adapter_list(sample_adapters) sample_adapter_chain = chain_adapters(sample_adapters) sample_diffs = adapter_chain_differences(sample_adapter_chain) assert part1_answer(sample_diffs) == 220 assert count_configs2(sample_adapters) == 19208 adapters = parse_adapter_list(helper.read_input_lines(10)) adapter_chain = chain_adapters(adapters) diffs = adapter_chain_differences(adapter_chain) print("Part 1:", part1_answer(diffs)) print("Part 2:", count_configs2(adapters))
if recipe_score > best['score'] and (calorie_count is None or count_calories(recipe) == calorie_count): best['score'] = recipe_score best['recipe'] = recipe.copy() best = {'recipe': None, 'score': -1} recursive_for(total_tsp, ingredients, best, calorie_count) return best['score'], best['recipe'] example_ingredients = '''Butterscotch: capacity -1, durability -2, flavor 6, texture 3, calories 8 Cinnamon: capacity 2, durability 3, flavor -2, texture -1, calories 3'''.split( '\n') ingredients = [Ingredient(properties) for properties in example_ingredients] recipe = {ingredients[0]: 44, ingredients[1]: 56} assert cookie_score(recipe) == 62842880 recipe = {ingredients[0]: 40, ingredients[1]: 60} assert cookie_score(recipe) == 57600000 assert count_calories(recipe) == 500 assert optimize_recipe(example_ingredients)[0] == 62842880 assert optimize_recipe(example_ingredients, 500)[0] == 57600000 ingredient_list = helper.read_input_lines(15) best_score, best_recipe = optimize_recipe(ingredient_list) print('Part 1:', best_score, best_recipe) best_score, best_recipe = optimize_recipe(ingredient_list, 500) print('Part 2:', best_score, best_recipe)
if are_charts_equal(new_chart, chart): break else: chart = copy_seating_chart(new_chart) n_iter += 1 return chart sample_seating_chart = '''L.LL.LL.LL LLLLLLL.LL L.L.L..L.. LLLL.LL.LL L.LL.LL.LL L.LLLLL.LL ..L.L..... LLLLLLLLLL L.LLLLLL.L L.LLLLL.LL'''.split('\n') sample_end_state = run(sample_seating_chart, verbose=True) assert count_filled_seats(sample_end_state) == 37 sample_end_state_los = run(sample_seating_chart, None, 5, verbose=False) assert count_filled_seats(sample_end_state_los) == 26 chart = helper.read_input_lines(11) end_state = run(chart) print("Part 1:", count_filled_seats(end_state)) end_state_los = run(chart, max_steps=None, get_up_thresh=5) print('Part 2:', count_filled_seats(end_state_los))
start_char = 0 while start_char < len(molecule): for atom_len in [1, 2]: atom = molecule[start_char:(start_char + atom_len)] if atom in replacements: for replacement in replacements[atom]: new_molecules.append(molecule[:start_char] + replacement + molecule[(start_char + atom_len):]) start_char += 1 return len(set(new_molecules)) replacements_and_molecule = read_input_lines(19) replacements = parse_replacements(replacements_and_molecule[:-1]) molecule = replacements_and_molecule[-1] test_replacements = '''H => HO H => OH O => HH'''.split('\n') test_molecule_1 = 'HOH' test_molecule_2 = 'HOHOHO' test_replacements = parse_replacements(test_replacements) assert calibrate(test_molecule_1, test_replacements) == 4 assert calibrate(test_molecule_2, test_replacements) == 7 print(calibrate(molecule, replacements))
def new_scoring(reindeer, n_steps): scores = {r.name: 0 for r in reindeer} for _ in range(n_steps): race_all(reindeer, 1) max_dist = max(reindeer, key=lambda x: x.distance).distance leading_reindeer = [r for r in reindeer if r.distance == max_dist] for lr in leading_reindeer: scores[lr.name] += 1 leader = max(scores, key=lambda x: scores[x]) return leader, scores[leader] example_reindeer_specs = '''Comet can fly 14 km/s for 10 seconds, but then must rest for 127 seconds. Dancer can fly 16 km/s for 11 seconds, but then must rest for 162 seconds.'''.split( '\n') reindeer = parse_reindeer(example_reindeer_specs) winner = race_all(reindeer, 1000) assert winner.name == 'Comet' and winner.distance == 1120 restart_all(reindeer) winner, winning_score = new_scoring(reindeer, 1000) assert winner == 'Dancer' and winning_score == 689 reindeer_specs = helper.read_input_lines(14) reindeer = parse_reindeer(reindeer_specs) winner = race_all(reindeer, 2503) print('Part 1:', winner.name, winner.distance) restart_all(reindeer) winner, winning_score = new_scoring(reindeer, 2503) print('Part 2:', winner, winning_score)
# This method would be nicely vectorizable, and it's cleaner anyway seat_ids = sorted(seat_ids) for l, r in zip(seat_ids[:-1], seat_ids[1:]): if r-l == 2: return (r + l) // 2 return -1 ### TESTS ################################# assert seat_decode('FBFBBFFRLR') == (44, 5) assert seat_id('FBFBBFFRLR') == 357 assert seat_decode('BFFFBBFRRR') == (70, 7) assert seat_id('BFFFBBFRRR') == 567 assert seat_decode('FFFBBBFRRR') == (14, 7) assert seat_id('FFFBBBFRRR') == 119 assert seat_decode('BBFFBBFRLL') == (102, 4) assert seat_id('BBFFBBFRLL') == 820 ### THE REAL THING ######################## seat_codes = helper.read_input_lines(5) seat_ids = [seat_id(code) for code in seat_codes] highest_seat_id = max(seat_ids) print('Part 1:', highest_seat_id) print('Part 2:', find_missing_seat(seat_ids)) print('Part 2 v2:', find_missing_seat2(seat_ids))
nenwswwsewswnenenewsenwsenwnesesenew enewnwewneswsewnwswenweswnenwsenwsw sweneswneswneneenwnewenewwneswswnese swwesenesewenwneswnwwneseswwne enesenwswwswneneswsenwnewswseenwsese wnwnesenesenenwwnenwsewesewsesesew nenewswnwewswnenesenwnesewesw eneswnwswnwsenenwnwnwwseeswneewsenese neswnwewnwnwseenwseesewsenwsweewe wseweeenwnesenwwwswnew'''.split('\n') tiles = flip_tiles(example_instructions) black_tiles = count_black_tiles(tiles) assert black_tiles == 10 tiles = evolve_tiles(tiles, verbose=False) black_tiles = count_black_tiles(tiles) assert black_tiles == 2208 ### THE REAL THING ############################### instructions = helper.read_input_lines(24) tiles = flip_tiles(instructions) black_tiles = count_black_tiles(tiles) print('Part 1:', black_tiles) tiles = evolve_tiles(tiles) black_tiles = count_black_tiles(tiles) print('Part 2:', black_tiles)
cube = parse_init(sample_init) assert len(cube) == 5 assert cube[(1, 0, 0)] == 1 assert cube[(2, 1, 0)] == 1 assert cube[(0, 2, 0)] == 1 assert cube[(1, 2, 0)] == 1 assert cube[(2, 2, 0)] == 1 cube = cycle_cube(cube, 6) assert sum(cube[coords] for coords in cube) == 112 cube = parse_init(sample_init, 4) assert len(cube) == 5 assert cube[(1, 0, 0, 0)] == 1 assert cube[(2, 1, 0, 0)] == 1 assert cube[(0, 2, 0, 0)] == 1 assert cube[(1, 2, 0, 0)] == 1 assert cube[(2, 2, 0, 0)] == 1 cube = cycle_cube(cube, 6) assert sum(cube[coords] for coords in cube) == 848 init = helper.read_input_lines(17) cube = parse_init(init) cube = cycle_cube(cube, 6) print('Part 1:', sum(cube[coords] for coords in cube)) cube = parse_init(init, 4) cube = cycle_cube(cube, 6) print('Part 2:', sum(cube[coords] for coords in cube))
for point in vent_line.points: point_counts[point] += 1 return sum(1 for point in point_counts if point_counts[point] > 1) ### TESTS test_vent_line_defs = '''0,9 -> 5,9 8,0 -> 0,8 9,4 -> 3,4 2,2 -> 2,1 7,0 -> 7,4 6,4 -> 2,0 0,9 -> 2,9 3,4 -> 1,4 0,0 -> 8,8 5,5 -> 8,2'''.split('\n') test_vent_lines = parse_vent_lines(test_vent_line_defs) assert test_vent_lines[1].is_diagonal() assert not test_vent_lines[0].is_diagonal() assert test_vent_lines[0].line_length == 5 assert count_overlaps(test_vent_lines) == 5 assert count_overlaps(test_vent_lines, True) == 12 ### THE REAL THING vent_line_defs = read_input_lines(5) vent_lines = parse_vent_lines(vent_line_defs) print(f'Part 1: {count_overlaps(vent_lines)}') print(f'Part 2: {count_overlaps(vent_lines, True)}')
jmp -3 acc -99 acc +1 jmp -4 acc +6'''.split('\n') sample_program = compile_program(sample_program) interp = Interpreter() try: interp.execute_program(sample_program) except InfiniteLoopError: interp.play_back() assert interp.accumulator == 5 fixed_sample_program = fix_program(sample_program) print(fixed_sample_program) interp.execute_program(fixed_sample_program) assert interp.accumulator == 8 program = compile_program(helper.read_input_lines(8)) interp = Interpreter() try: interp.execute_program(program) except InfiniteLoopError: print('Accumulator at infinite loop:', interp.accumulator) fixed_program = fix_program(program) interp.execute_program(fixed_program) print('Accumulator on successful execution:', interp.accumulator)
continue break sorted_containers = [sc for sc in sorted_containers[::-1]] for i in range(1, n+1): cont_vol = sum(sorted_containers[:i]) if cont_vol >= volume: shortest_combo = i else: continue break if min_number: longest_combo = shortest_combo combos = [] for combo_len in range(shortest_combo, longest_combo+1): for combo in combinations(containers, combo_len): if sum(combo) == volume: combos.append(combo) return combos test_containers = [20, 15, 10, 5, 5] assert len(get_combos(25, test_containers)) == 4 containers = [int(c) for c in helper.read_input_lines(17)] print('Part 1:', len(get_combos(150, containers))) print('Part 2:', len(get_combos(150, containers, True)))
def is_nice_new(string: str) -> bool: test2 = False test1 = False for i, c in enumerate(string[:-2]): test2 = test2 or c == string[i + 2] # Inserting a 0 here so I don't catch false matches from pairs of characters on either side of the pair being tested # The last pair is never tested, but it would have already been in the string earlier, so that's OK # Actually, I don't really have to test all pairs, just those in the first half of the string... could speed up by oh well test1 = test1 or string[i:i + 2] in string[:i] + '0' + string[i + 2:] return test1 and test2 assert is_nice('ugknbfddgicrmopn') assert is_nice('aaa') assert not is_nice('jchzalrnumimnmhp') assert not is_nice('haegwjzuvuyypxyu') assert not is_nice('dvszwmarrgswjxmb') assert is_nice_new('qjhvhtzxzqqjkmpb') assert is_nice_new('xxyxx') assert not is_nice_new('uurcxstgmygtbstg') assert not is_nice_new('ieodomkazucvgmuy') string_list = helper.read_input_lines(5) print("Part 1:", sum(1 for string in string_list if is_nice(string))) print("Part 2:", sum(1 for string in string_list if is_nice_new(string)))
test_course = """forward 5 down 5 forward 8 up 3 down 8 forward 2 """.strip().split('\n') test_position = Submarine() test_position.chart_course(test_course) assert test_position.horizontal == 15 assert test_position.depth == 10 assert test_position.get_position_hash() == 150 test_position = AimedSubmarine() test_position.chart_course(test_course) assert test_position.horizontal == 15 assert test_position.depth == 60 assert test_position.get_position_hash() == 900 course = read_input_lines(2) position = Submarine() position.chart_course(course) print(f'Part 1: {position.get_position_hash()}') second_position = AimedSubmarine() second_position.chart_course(course) print(f'Part 2: {second_position.get_position_hash()}')
elif exp_pieces[0] == '*': val *= val2 else: raise ValueError(f'Unexpected operator {exp_pieces[1]}') exp_pieces = exp_pieces[2:] return val ### TESTS ################################################################# assert evaluate("1 + 2 * 3 + 4 * 5 + 6") == 71 assert evaluate('1 + (2 * 3) + (4 * (5 + 6))') == 51 assert evaluate('2 * 3 + (4 * 5)') == 26 assert evaluate('5 + (8 * 3 + 9 + 3 * 4 * 3)') == 437 assert evaluate('5 * 9 * (7 * 3 * 3 + 9 * 3 + (8 + 6 * 4))') == 12240 assert evaluate('((2 + 4 * 9) * (6 + 9 * 8 + 6) + 6) + 2 + 4 * 2') == 13632 assert evaluate("1 + 2 * 3 + 4 * 5 + 6", True) == 231 assert evaluate('1 + (2 * 3) + (4 * (5 + 6))', True) == 51 assert evaluate('2 * 3 + (4 * 5)', True) == 46 assert evaluate('5 + (8 * 3 + 9 + 3 * 4 * 3)', True) == 1445 assert evaluate('5 * 9 * (7 * 3 * 3 + 9 * 3 + (8 + 6 * 4))', True) == 669060 assert evaluate('((2 + 4 * 9) * (6 + 9 * 8 + 6) + 6) + 2 + 4 * 2', True) == 23340 ### THE REAL THING ######################################################## expressions = helper.read_input_lines(18) total = sum(evaluate(expression) for expression in expressions) print('Part 1:', total) total = sum(evaluate(expression, True) for expression in expressions) print('Part 2:', total)
sub_results = dirac_game(p1_start, p2_pos, p1_score, new_p2_score, 0, turn + 1) results['p1_wins'] += n_vals * sub_results['p1_wins'] results['p2_wins'] += n_vals * sub_results['p2_wins'] else: results['p2_wins'] += n_vals return results if __name__ == '__main__': ### THE TESTS test_p1_start = 4 test_p2_start = 8 test_game = DiracDiceGame(test_p1_start, test_p2_start, DeterministicDie()) while test_game.winner() < 0: test_game.take_turn() assert min(test_game.scores) * test_game.die_rolls == 739785 test_results = dirac_game(test_p1_start, test_p2_start) assert max(test_results.values()) == 444356092776315 ### THE REAL THING puzzle_input = helper.read_input_lines() p1_start = int(puzzle_input[0][-1]) p2_start = int(puzzle_input[1][-1]) game = DiracDiceGame(p1_start, p2_start, DeterministicDie()) while game.winner() < 0: game.take_turn() print(f'Part 1: {min(game.scores) * game.die_rolls}') results = dirac_game(p1_start, p2_start) print(f'Part 2: {max(results.values())}')
### TESTS ########################################################################### sample_food_data = '''mxmxvkd kfcds sqjhc nhms (contains dairy, fish) trh fvjkl sbzzf mxmxvkd (contains dairy) sqjhc fvjkl (contains soy) sqjhc mxmxvkd sbzzf (contains fish)'''.split('\n') sample_food = parse_food_data(sample_food_data) allergens_to_ingredients = match_allergens_to_ingredients(sample_food) non_allergenic_ingredients = find_non_allergenic_ingredients( sample_food, allergens_to_ingredients) assert count_ingredient_occurrences(sample_food, non_allergenic_ingredients) == 5 assert get_dangerous_ingredient_list( sample_food, allergens_to_ingredients, non_allergenic_ingredients) == 'mxmxvkd,sqjhc,fvjkl' ### THE REAL THING ################################################################### food_data = helper.read_input_lines(21) foods = parse_food_data(food_data) allergens_to_ingredients = match_allergens_to_ingredients(foods) non_allergenic_ingredients = find_non_allergenic_ingredients( foods, allergens_to_ingredients) print('Part 1:', count_ingredient_occurrences(foods, non_allergenic_ingredients)) print( 'Part 2:', get_dangerous_ingredient_list(foods, allergens_to_ingredients, non_allergenic_ingredients))