Skip to content

Commit 323b938

Browse files
committed
qqq
1 parent 0dded0a commit 323b938

7 files changed

Lines changed: 434 additions & 76 deletions

File tree

2025/Day10/Solution.cs

Lines changed: 87 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,8 @@ namespace AdventOfCode.Y2025.Day10;
1414

1515
record Problem(int target, int[] buttons, int[] jolts);
1616

17+
record Equation(int[] buttonIndices, int sum);
18+
1719
[ProblemName("Factory")]
1820
class Solution : Solver {
1921

@@ -41,16 +43,12 @@ public object PartOne(string input) {
4143

4244
public object PartTwo(string input) {
4345
var res = 0L;
44-
var i = 1;
4546
foreach (var p in Parse(input)) {
46-
Console.WriteLine(i + " " + p.buttons.Length + " " + p.jolts.Length);
47-
i++;
47+
var s = Solve(p);
48+
Console.WriteLine(s);
49+
res += s;
4850
}
49-
return res;
50-
}
51-
52-
bool TooMuch(Problem p, int[] state) {
53-
return Enumerable.Range(0, state.Length).Any(i => state[i] > p.jolts[i]);
51+
return 0;
5452
}
5553

5654
int Xor(int[] buttons, int mask) {
@@ -66,35 +64,84 @@ int Xor(int[] buttons, int mask) {
6664
return res;
6765
}
6866

69-
int Solve(Problem p, int pushes, int[] state) {
70-
if (pushes > 11) {
71-
return int.MaxValue;
67+
Dictionary<string, int> cache;
68+
69+
int Solve(Problem p) {
70+
var equations = new List<Equation>();
71+
for(int i = 0; i < p.jolts.Length; i++) {
72+
var jolt = p.jolts[i];
73+
var buttonIndices = new List<int>();
74+
for(var buttonIndex = 0; buttonIndex < p.buttons.Length; buttonIndex++) {
75+
var button = p.buttons[buttonIndex];
76+
if ((button & 1 << i) != 0) {
77+
buttonIndices.Add(buttonIndex);
78+
}
79+
}
80+
equations.Add(new Equation(buttonIndices.ToArray(), jolt));
7281
}
82+
Console.WriteLine(p.target + " " + equations.Count);
7383

74-
if (Array.Equals(state, p.jolts)) {
75-
return pushes;
84+
return SolveEquations(equations);
85+
}
86+
87+
int SolveEquations(List<Equation> equations) {
88+
// [.##.] (3) (1,3) (2) (2,3) (0,2) (0,1) {3,5,4,7}
89+
90+
if (equations.Count == 0) {
91+
return 0;
7692
}
7793

78-
if (Enumerable.Range(0, state.Length).Any(i => state[i] > p.jolts[i])) {
79-
return int.MaxValue;
80-
}
94+
var res = int.MaxValue / 2;
95+
var eq = equations.MinBy(eq => eq.buttonIndices.Length);
96+
var q = Choose(eq.sum, eq.buttonIndices, new int[20]).ToArray();
97+
98+
foreach (var xs in q) {
8199

82-
var res = int.MaxValue;
83-
for (int i = 0; i < p.buttons.Length; i++) {
84-
var stateT = Push(state, p.buttons[i]);
85-
var m = Solve(p, pushes + 1, stateT);
86-
if (m < res) {
87-
res = m;
100+
var substitutedEquations =
101+
equations.Select(eqT => Substitute(eqT, eq.buttonIndices, xs)).ToArray();
102+
103+
if (substitutedEquations.Any(eq => eq.sum < 0) ||
104+
substitutedEquations.Any(eq => eq.sum > 0 && !eq.buttonIndices.Any())
105+
) {
106+
continue;
107+
}
108+
109+
var remainingEquations = substitutedEquations.Where(eq =>
110+
eq.sum != 0 || eq.buttonIndices.Any()
111+
).ToArray();
112+
113+
var cur = xs.Sum() + SolveEquations(remainingEquations.ToList());
114+
if (cur < res) {
115+
res = cur;
88116
}
89117
}
90118
return res;
91119
}
92120

93-
int[] Push(int[] state, int button) {
121+
Equation Substitute(Equation eq, int[] indices, int[] values) {
122+
var sum = eq.sum;
123+
var remainingIndices = eq.buttonIndices.ToList();
124+
for (int i = 0; i < indices.Length; i++) {
125+
var index = indices[i];
126+
var value = values[index];
127+
if (remainingIndices.Contains(index)) {
128+
remainingIndices.Remove(index);
129+
sum -= value;
130+
}
131+
}
132+
return new Equation(remainingIndices.ToArray(), sum);
133+
}
134+
135+
136+
bool TooMuch(Problem p, int[] state) {
137+
return Enumerable.Range(0, p.jolts.Length).Any(i => state[i] > p.jolts[i]);
138+
}
139+
140+
int[] Push(int[] state, int button, int n) {
94141
var res = state.ToArray();
95142
for (int i = 0; i < state.Length; i++) {
96143
if ((button & (1 << i)) != 0) {
97-
res[i]++;
144+
res[i] += n;
98145
}
99146
}
100147
return res;
@@ -142,4 +189,20 @@ from part in parts[1..^1]
142189
}
143190
}
144191

192+
IEnumerable<int[]> Choose(int s, int[] indices, int[] acc) {
193+
if (indices.Length == 1) {
194+
acc = acc.ToArray();
195+
acc[indices[0]] = s;
196+
yield return acc;
197+
yield break;
198+
}
199+
for (int i = 0; i <= s; i++) {
200+
foreach (var v in Choose(s - i, indices[1..].ToArray(), acc)) {
201+
var vT = v.ToArray();
202+
vT[indices[0]] = i;
203+
yield return vT;
204+
}
205+
}
206+
}
207+
145208
}

2025/Day10/bar.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -265,10 +265,10 @@ def combinations(n):
265265
s = np.sum(x)
266266
if s < best:
267267
best = s
268-
print(" x =", x, "i=", i, "sum=", s, "res=", res)
268+
# print(" x =", x, "i=", i, "sum=", s, "res=", res)
269269

270270
if i is None or np.sum(i) >= best:
271271
break
272-
272+
print(" best:", best)
273273
res += best
274274
print(int(res))

2025/Day10/eq.py

Lines changed: 125 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,125 @@
1+
import re
2+
from z3 import *
3+
4+
5+
def parse_input(text):
6+
"""
7+
Example input:
8+
[..##.#...#] (0,3,4,7,9) ... (0,2,6,7,8,9) {87,70,44,58,58,67,44,54,55,54}
9+
10+
Returns:
11+
pattern: list[int] 0/1 from [] section ('.' -> 0, '#' -> 1)
12+
index_lists: list[list[int]] from () groups (each list is a column vector index list)
13+
b: list[int] from {} section
14+
"""
15+
# 1) pattern from []
16+
pattern = None
17+
m = re.search(r"\[(.*?)\]", text)
18+
if m:
19+
raw = m.group(1).strip()
20+
pattern = [1 if ch == '#' else 0 for ch in raw if ch in ".#"]
21+
22+
# 2) index lists from () groups
23+
groups = re.findall(r"\((.*?)\)", text)
24+
index_lists = []
25+
for g in groups:
26+
g = g.strip()
27+
if g == "":
28+
index_lists.append([])
29+
else:
30+
index_lists.append([int(x.strip()) for x in g.split(",")])
31+
32+
# 3) b vector from {}
33+
b = None
34+
m = re.search(r"\{(.*?)\}", text)
35+
if m:
36+
raw = m.group(1)
37+
b = [int(x.strip()) for x in raw.split(",") if x.strip() != ""]
38+
39+
return pattern, index_lists, b
40+
41+
42+
def solve_with_z3(pattern, index_lists, b):
43+
"""
44+
Given:
45+
pattern: list[int] used only for dimension (len(pattern) rows)
46+
index_lists: for each variable x_j, the list of row indices where x_j appears
47+
b: RHS values per row
48+
49+
Builds and solves:
50+
for each row r: sum_{j: r in index_lists[j]} x_j = b[r]
51+
x_j >= 0, x_j integer
52+
min sum_j x_j
53+
"""
54+
if pattern is None or b is None:
55+
raise ValueError("Missing pattern or b vector.")
56+
57+
dim = len(pattern)
58+
if len(b) != dim:
59+
raise ValueError("pattern and b lengths do not match.")
60+
61+
n_vars = len(index_lists)
62+
63+
# Integer variables x0 ... x_(n_vars-1)
64+
x = [Int(f"x{j}") for j in range(n_vars)]
65+
66+
opt = Optimize()
67+
68+
# Non-negativity
69+
for xj in x:
70+
opt.add(xj >= 0)
71+
72+
# Row constraints
73+
for row in range(dim):
74+
vars_in_row = []
75+
for j, idxs in enumerate(index_lists):
76+
if row in idxs:
77+
vars_in_row.append(x[j])
78+
79+
if vars_in_row:
80+
opt.add(Sum(vars_in_row) == b[row])
81+
else:
82+
# No variable in this row: enforce 0 = b[row]
83+
opt.add(0 == b[row])
84+
85+
# Objective: minimize sum xi
86+
obj = Sum(x)
87+
opt.minimize(obj)
88+
89+
# Solve
90+
result = opt.check()
91+
if result == sat:
92+
model = opt.model()
93+
solution = [model[xj].as_long() for xj in x]
94+
obj_val = model.eval(obj).as_long()
95+
return solution, obj_val
96+
elif result == unsat:
97+
return None, None
98+
else: # unknown
99+
return None, None
100+
101+
102+
if __name__ == "__main__":
103+
with open("input.in", "r", encoding="utf-8") as f:
104+
res = 0
105+
for line_no, line in enumerate(f, start=1):
106+
line = line.strip()
107+
if line == "":
108+
continue
109+
110+
pattern, index_lists, b = parse_input(line)
111+
112+
try:
113+
solution, obj_val = solve_with_z3(pattern, index_lists, b)
114+
except ValueError as e:
115+
print("Error:", e)
116+
continue
117+
118+
if solution is None:
119+
print(f"===== Line {line_no} =====")
120+
print("No solution (unsat or unknown).")
121+
else:
122+
# print("min sum xi =", obj_val)
123+
res += obj_val
124+
125+
print("grand total =", res)

0 commit comments

Comments
 (0)