#!/usr/bin/env python # https://adventofcode.com/2025/day/10 from itertools import combinations, product from sympy import symbols, Matrix, solve_linear_system f = open("day10input.txt", "r") # regular input input = f.readlines() # testinput #input = "[.##.] (3) (1,3) (2) (2,3) (0,2) (0,1) {3,5,4,7}\n[...#.] (0,2,3,4) (2,3) (0,4) (0,1,2) (1,2,3,4) {7,5,12,7,2}\n[.###.#] (0,1,2,3,4) (0,3,4) (0,1,2,4,5) (1,2) {10,11,11,5,10,5}".split("\n") machines = [] for input_line in input: line = input_line.rstrip("\n").split(" ") machine = {} # final state fs = line[0][1:-1].replace(".", "0").replace("#", "1") machine["fs"] = int(fs, base=2) # switches switches = [] for switch in line[1:-1]: s = ["0"] * len(fs) for i in [int(j) for j in switch[1:-1].split(",")]: s[i] = "1" switches.append("".join(s)) machine["s"] = sorted([int(s, base=2) for s in switches], key=int.bit_count) # joltage req's machine["j"] = [int(n) for n in line[-1][1:-1].split(",")] machines.append(machine) def print_machines(machines: list[dict]) -> None: for i in range(len(machines)): print(f"Machine no. {i}") for k in machines[i].keys(): print(f"key:\t{k}\tvalue:\t{machines[i][k]}") def part1_bfs(m): for steps in range(1, len(m["s"])): # check if current step no yields a solution for c in list(combinations(m["s"], steps)): lights = 0 for i in c: lights ^= i if lights == m["fs"]: print(f"Success with combo {i} and step count of {steps}") return steps return None def part2(m): switches = [list(map(int, list("{0:b}".format(switch).zfill(len(m["j"]))))) for switch in m["s"]] joltages = m["j"] # define sympy symbols and equations x = symbols(f"x:{len(switches)}", integer=True) system = Matrix([[switch[j] for switch in switches] + [joltages[j]] for j in range(len(joltages))]) print(f"Equation system to solve: {system}") # solve system with sympy solutions = solve_linear_system(system, *x) print(f"Solutions: {solutions}") # isolate free variables free_vars = [var for var in x if var not in solutions.keys()] print(f"{free_vars=}") # find smallest solution smallest_sum = None # loop over the cartesian product of sensible numbers for button presses times the number of free variables for lv in product(range(max(joltages)), repeat=len(free_vars)): # print(f"{lv=}") current_sum = sum(lv) for v in solutions.values(): for i in range(len(lv)): v = v.subs(free_vars[i], lv[i]) # print(f"{v=}") if v < 0: # print(f"negative button press number for {lv=} -> skipping") current_sum = -1 break current_sum += v if current_sum < 0: continue # print(f"-> {current_sum=}") # check current sum if not current_sum.is_Integer: continue elif not smallest_sum or current_sum < smallest_sum: smallest_sum = current_sum print(f"Smallest number of presses found: {smallest_sum}") return smallest_sum #print_machines(machines) #print(sum(list(map(part1_bfs, machines))))bin steps = 0 for machine in machines: steps += part2(machine) print(f"current total step number: {steps}") print(f"final total step number: {steps}")