return a, b # f(x) = ax + b # Returns the position of card x after applying the shuffle def apply_shuffle(a, b, x, size): return (a * x + b) % size # Returns which card will be on position x after applying the shuffle def apply_shuffle_inverted(a, b, x, size): return ((x - b) * modular_inverse(a, size)) % size # g(f(x)) = cf(x) + d = cax + cb + d def combine_functions(a, b, c, d, size): return (c * a) % size, (c * b + d) % size def modular_inverse(x, size): ret, _ = modular_exponentiation(x, 0, size - 2, size) return ret def modular_exponentiation(a, b, iterations, size): if iterations == 1: return a, b elif iterations % 2 == 0: a, b = combine_functions(a, b, a, b, size) return modular_exponentiation(a, b, iterations / 2, size) else: c, d = modular_exponentiation(a, b, iterations - 1, size) return combine_functions(a, b, c, d, size) aoc.run_lines(main, "day22.txt")
resources[ORE] = TRILLION resources[FUEL] = -part2 nanofactory(reactions, resources) ore_remaining = resources[ORE] if ore_remaining <= 0: part2 -= 1 break else: part2 += max(1, int(ore_remaining / ore_per_fuel)) return part1, part2 def nanofactory(reactions, resources): while any(r != ORE and resources[r] < 0 for r in resources): for target in resources: if resources[target] < 0: new_resources = False for reaction in reactions: if target in reaction[1]: reaction_count = max(1, int(-resources[target] / reaction[1][target])) for item in reaction[0]: if item not in resources: new_resources = True resources[item] -= reaction[0][item] * reaction_count for item in reaction[1]: resources[item] += reaction[1][item] * reaction_count if new_resources: break aoc.run_lines(main, "day14.txt")
return part1, part2 def run_program(program, instruction_to_flip): seen_instructions = [] nop_jmp_counter = 0 program_pointer = 0 acc = 0 while program_pointer not in seen_instructions and program_pointer < len(program): seen_instructions.append(program_pointer) instruction = program[program_pointer][0] value = program[program_pointer][1] program_pointer += 1 if nop_jmp_counter == instruction_to_flip: if instruction == "nop": instruction = "jmp" elif instruction == "jmp": instruction = "nop" if instruction == "acc": acc += value elif instruction == "jmp": program_pointer += value - 1 nop_jmp_counter += 1 elif instruction == "nop": nop_jmp_counter += 1 return acc, program_pointer >= len(program) aoc.run_lines(main, "day08.txt")