Skip to content

Commit 2a6d0c8

Browse files
committed
2025/10
1 parent 8e9c919 commit 2a6d0c8

4 files changed

Lines changed: 125 additions & 72 deletions

File tree

2025/Day10/README.md

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,3 +27,12 @@ Say that **K** has 3 columns. Now we can start brute-forcing by setting the valu
2727
This way we eventually get a feasible solution for the original problem, say with the total button-press count equal to 100 or so. Then it’s enough to continue the above iteration while the sum of `yᵢ` is ≤ 100. That gives us a termination condition. During the search we might run into better solutions, which further lowers the upper bound.
2828

2929
I prototyped [this idea](gauss.py) in Python with ChatGPT. I think, if anything, this could be ported to C#, but I don’t feel the urge. Although it uses first principles that one could potentially implement, it’s a much slower solution than the one using z3.
30+
31+
## Update
32+
33+
Based on the ingenious idea of [tenthmascot](https://www.reddit.com/r/adventofcode/comments/1pk87hl/2025_day_10_part_2_bifurcate_your_way_to_victory/), I could create a plain C# implementation for the problem.
34+
35+
As he says: find all possible sets of buttons you can push so that the remaining voltages are even,
36+
and divide by 2 and recurse.
37+
38+
All credits goes to him, but I'll give an extra ⭐ to myself for learning something new again!

2025/Day10/Solution.cs

Lines changed: 75 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -5,41 +5,90 @@ namespace AdventOfCode.Y2025.Day10;
55
using System.Linq;
66
using System.Text.RegularExpressions;
77

8-
record Problem(int target, int[] buttons);
8+
record Problem(int[] target, int[] buttons, int[] joltage);
9+
10+
record SinglePress(int buttonCount, int[] joltageChange);
911

1012
[ProblemName("Factory")]
1113
class Solution : Solver {
1214

1315
public object PartOne(string input) {
1416
var res = 0;
1517
foreach (var p in Parse(input)) {
16-
var minPressCount =
17-
Enumerable.Range(0, 1 << p.buttons.Length)
18-
.Where(mask => XorMasked(p.buttons, mask) == p.target)
19-
.Min(BitCount);
18+
var minPressCount = SinglePresses(p)
19+
.Where(press => Enumerable.SequenceEqual(p.target, press.joltageChange.Select(i => i % 2)))
20+
.Min(press => press.buttonCount);
2021
res += minPressCount;
2122
}
2223
return res;
2324
}
2425

2526
public object PartTwo(string input) {
26-
// I found this problem against the spirit of Advent of Code,
27-
// solved with z3 in Python. ¯\_(ツ)_/¯
28-
return 18011;
29-
}
27+
// Implements the idea presented by tenthmascot
28+
// https://www.reddit.com/r/adventofcode/comments/1pk87hl/2025_day_10_part_2_bifurcate_your_way_to_victory/
3029

31-
int XorMasked(int[] nums, int mask) {
3230
var res = 0;
33-
for (int i = 0; i < nums.Length; i++) {
34-
if (((mask >> i) & 1) != 0) {
35-
res ^= nums[i];
36-
}
31+
foreach (var p in Parse(input)) {
32+
res += Solve(p.joltage, SinglePresses(p), new Dictionary<string, int>());
3733
}
3834
return res;
3935
}
4036

41-
// Brian Kernighan’s bit-counting
42-
int BitCount(int n) => n != 0 ? 1 + BitCount(n & (n-1)) : 0;
37+
// Collect changes in joltages when each button is pressed at most once
38+
List<SinglePress> SinglePresses(Problem p) {
39+
var presses = new List<SinglePress>();
40+
41+
foreach (var buttonMask in Enumerable.Range(0, 1 << p.buttons.Length)) {
42+
var joltageChange = new int[p.joltage.Length];
43+
var buttonCount = 0;
44+
45+
for (int ibutton = 0; ibutton < p.buttons.Length; ibutton++) {
46+
if ((buttonMask >> ibutton) % 2 == 1) {
47+
buttonCount++;
48+
var button = p.buttons[ibutton];
49+
for (int ijoltage = 0; ijoltage < p.joltage.Length; ijoltage++) {
50+
if ((button >> ijoltage) % 2 == 1) {
51+
joltageChange[ijoltage]++;
52+
}
53+
}
54+
}
55+
}
56+
presses.Add(new SinglePress(buttonCount, joltageChange));
57+
}
58+
return presses;
59+
}
60+
61+
int Solve(int[] joltages, List<SinglePress> singlePresses, Dictionary<string, int> cache) {
62+
63+
if (joltages.All(jolt => jolt == 0)) {
64+
return 0;
65+
}
66+
67+
var key = string.Join("-", joltages);
68+
if (!cache.ContainsKey(key)) {
69+
var best = 10_000_000;
70+
foreach (var singlePress in singlePresses) {
71+
72+
var buttonCount = singlePress.buttonCount;
73+
var joltageChange = singlePress.joltageChange;
74+
75+
var evens =
76+
Enumerable.Range(0, joltages.Length)
77+
.All(i => joltages[i] >= joltageChange[i] && (joltages[i] - joltageChange[i]) % 2 == 0);
78+
79+
if (evens) {
80+
var subProblem =
81+
Enumerable.Range(0, joltages.Length)
82+
.Select(i => (joltages[i] - joltageChange[i]) / 2)
83+
.ToArray();
84+
85+
best = Math.Min(best, buttonCount + 2 * Solve(subProblem, singlePresses, cache));
86+
}
87+
}
88+
cache[key] = best;
89+
}
90+
return cache[key];
91+
}
4392

4493
IEnumerable<Problem> Parse(string input) {
4594
var lines = input.Split("\n");
@@ -48,20 +97,20 @@ IEnumerable<Problem> Parse(string input) {
4897
var parts = line.Split(" ").ToArray();
4998

5099
var target =
51-
parts[0]
52-
.Trim("[]".ToCharArray())
53-
.Reverse()
54-
.Aggregate(0, (acc, ch) => acc * 2 + (ch == '#' ? 1 : 0));
100+
from ch in parts[0].Trim("[]".ToCharArray())
101+
select ch == '#' ? 1 : 0;
55102

56103
var buttons =
57104
from part in parts[1..^1]
58-
let digits = Regex.Matches(part, @"\d").Select(m => int.Parse(m.Value))
59-
let mask = (from d in digits select 1 << d).Sum()
105+
let digits = Regex.Matches(part, @"\d+").Select(m => int.Parse(m.Value))
106+
let mask = digits.Aggregate(0, (acc, d) => acc | (1 << d))
60107
select mask;
61108

62-
yield return new Problem(target, [.. buttons]);
109+
var joltage =
110+
from m in Regex.Matches(parts[^1], @"\d+")
111+
select int.Parse(m.Value);
112+
113+
yield return new Problem([.. target], [.. buttons], [.. joltage]);
63114
}
64115
}
65-
66-
67-
}
116+
}

2025/SplashScreen.cs

Lines changed: 25 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -8,24 +8,24 @@ public void Show() {
88

99
var color = Console.ForegroundColor;
1010
Write(0xcc00, false, " ▄█▄ ▄▄█ ▄ ▄ ▄▄▄ ▄▄ ▄█▄ ▄▄▄ ▄█ ▄▄ ▄▄▄ ▄▄█ ▄▄▄\n █▄█ █ █ █ █ █▄█ █ █ █ █ █ █▄ ");
11-
Write(0xcc00, false, " █ █ █ █ █ █▄█\n █ █ █▄█ ▀▄▀ █▄▄ █ █ █▄ █▄█ █ █▄ █▄█ █▄█ █▄▄ /^2025$/\n \n ");
12-
Write(0xcc00, false, " ");
13-
Write(0xffffff, false, ". . ____ . .. ");
14-
Write(0xffff66, true, "* ");
15-
Write(0xffffff, false, ". '' . ");
11+
Write(0xcc00, false, " █ █ █ █ █ █▄█\n █ █ █▄█ ▀▄▀ █▄▄ █ █ █▄ █▄█ █ █▄ █▄█ █▄█ █▄▄ $year = 2025\n ");
12+
Write(0xcc00, false, "\n ");
13+
Write(0xffffff, false, "' '' ' ____ .. .'. ");
14+
Write(0xffff66, true, "* ");
15+
Write(0xffffff, false, ". . ' ");
1616
Write(0xff9900, false, "<");
17-
Write(0xffffff, false, "o ' \n ________/");
17+
Write(0xffffff, false, "o . \n ________/");
1818
Write(0x999999, false, "O___");
1919
Write(0xffffff, false, "\\__________");
2020
Write(0xff0000, false, "|");
2121
Write(0xffffff, false, "_________________O______ ");
2222
Write(0xcccccc, false, " 1 ");
2323
Write(0xffff66, false, "**\n ");
24-
Write(0x32211a, false, "' ");
24+
Write(0x32211a, false, ". ");
2525
Write(0x999999, false, "_______");
2626
Write(0xaabbcc, false, "||");
27-
Write(0x999999, false, "_________ ");
28-
Write(0x32211a, false, ". ' ' ' ' ' . ' \n .' ");
27+
Write(0x999999, false, "_________ ");
28+
Write(0x32211a, false, "' . ..' .' \n ");
2929
Write(0x999999, false, "| ");
3030
Write(0x9b715b, false, "_");
3131
Write(0xbb66ff, false, "@");
@@ -37,8 +37,7 @@ public void Show() {
3737
Write(0xff0000, false, "'.");
3838
Write(0x999999, false, "|_ _________________________ ");
3939
Write(0xcccccc, false, " 2 ");
40-
Write(0xffff66, false, "**\n ");
41-
Write(0x32211a, false, ".. ");
40+
Write(0xffff66, false, "**\n ");
4241
Write(0x999999, false, "|_");
4342
Write(0xff0000, false, "&");
4443
Write(0x999999, false, "_");
@@ -63,7 +62,7 @@ public void Show() {
6362
Write(0xff0000, false, ".");
6463
Write(0x666666, false, ". ");
6564
Write(0x999999, false, "| \n ");
66-
Write(0x32211a, false, "' ..' .' ' ");
65+
Write(0x32211a, false, "' '' ' ' ' ");
6766
Write(0x999999, false, "\\_");
6867
Write(0xaabbcc, false, "]");
6968
Write(0x999999, false, "__");
@@ -80,7 +79,7 @@ public void Show() {
8079
Write(0x999999, false, "_| ");
8180
Write(0xcccccc, false, " 3 ");
8281
Write(0xffff66, false, "**\n ");
83-
Write(0x32211a, false, ".' .. ''. ' . ' ");
82+
Write(0x32211a, false, ". .' ' . . ' ' . ");
8483
Write(0x999999, false, "____________");
8584
Write(0xaabbcc, false, "//");
8685
Write(0x999999, false, "___ \n __________________________ ");
@@ -138,14 +137,12 @@ public void Show() {
138137
Write(0x9b715b, false, "T");
139138
Write(0x999999, false, "_");
140139
Write(0xaa7744, false, "...' ");
141-
Write(0x32211a, false, ".' . ' . ? ");
140+
Write(0x32211a, false, "'' ..' . ''. ");
142141
Write(0xcccccc, false, " 5 ");
143142
Write(0xffff66, false, "**\n ");
144143
Write(0x9900, false, "|| ");
145-
Write(0x999999, false, "____________ ");
146-
Write(0x32211a, false, ".' ");
147-
Write(0x999999, false, "_______________________ ");
148-
Write(0x32211a, false, "? \n ");
144+
Write(0x999999, false, "____________ _______________________ ");
145+
Write(0x32211a, false, ". \n ");
149146
Write(0x999999, false, "_");
150147
Write(0x9900, false, "||");
151148
Write(0x999999, false, "__/");
@@ -157,8 +154,8 @@ public void Show() {
157154
Write(0xff0000, false, "~ ");
158155
Write(0xff00, false, ".'");
159156
Write(0xff0000, false, "'. .");
160-
Write(0x999999, false, "| ");
161-
Write(0x32211a, false, "' ");
157+
Write(0x999999, false, "| ");
158+
Write(0x32211a, false, ". ");
162159
Write(0xcccccc, false, " 6 ");
163160
Write(0xffff66, false, "**\n ");
164161
Write(0x999999, false, "|");
@@ -196,7 +193,7 @@ public void Show() {
196193
Write(0x999999, false, "| ");
197194
Write(0xcccccc, false, " 7 ");
198195
Write(0xffff66, false, "**\n ");
199-
Write(0x32211a, false, ".' . . ");
196+
Write(0x32211a, false, ". .. . '' ");
200197
Write(0xffff66, false, "'...");
201198
Write(0x999999, false, "|");
202199
Write(0xffff66, false, "<>");
@@ -214,8 +211,8 @@ public void Show() {
214211
Write(0x9b715b, false, "[");
215212
Write(0x999999, false, "_");
216213
Write(0xaabbcc, false, "O");
217-
Write(0x999999, false, "_| \n __________________________ ");
218-
Write(0x32211a, false, "' . ");
214+
Write(0x999999, false, "_| \n __________________________ ");
215+
Write(0x32211a, false, "'' '..' '' ");
219216
Write(0xaabbcc, false, "| ");
220217
Write(0xcccccc, false, " 8 ");
221218
Write(0xffff66, false, "**\n ");
@@ -282,8 +279,7 @@ public void Show() {
282279
Write(0x999999, false, "| \n |_");
283280
Write(0xaabbcc, false, "|");
284281
Write(0xff0000, false, "'");
285-
Write(0xff00, false, ".");
286-
Write(0xff0000, false, ".");
282+
Write(0xff00, false, "..");
287283
Write(0xaabbcc, false, "|");
288284
Write(0x999999, false, "_");
289285
Write(0xaabbcc, false, "(");
@@ -299,10 +295,9 @@ public void Show() {
299295
Write(0xffff66, true, "* ");
300296
Write(0x999999, false, "| ");
301297
Write(0xcccccc, false, "11 ");
302-
Write(0xffff66, false, "**\n ");
303-
Write(0x32211a, false, "'. ");
298+
Write(0xffff66, false, "**\n ");
304299
Write(0xaabbcc, false, "| ");
305-
Write(0x32211a, false, "''' ");
300+
Write(0x32211a, false, ". ' ");
306301
Write(0xaabbcc, false, ".--. ");
307302
Write(0x999999, false, "| ");
308303
Write(0x9900, false, "<");
@@ -314,8 +309,8 @@ public void Show() {
314309
Write(0x9900, false, "> ");
315310
Write(0xbb66ff, false, "o");
316311
Write(0x9900, false, "^> ");
317-
Write(0x999999, false, "| \n ");
318-
Write(0x32211a, false, "'' ");
312+
Write(0x999999, false, "| \n ");
313+
Write(0x32211a, false, "... ");
319314
Write(0xaabbcc, false, "'------' '---#");
320315
Write(0x999999, false, "_");
321316
Write(0x9900, false, "<<^");

0 commit comments

Comments
 (0)