Skip to content

Commit d4fe958

Browse files
committed
[2025] Working day 10
1 parent 4796f10 commit d4fe958

File tree

3 files changed

+222
-0
lines changed

3 files changed

+222
-0
lines changed

README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ Thank you to [Eric Wastl](http://was.tl) for running this incredible yearly even
1414
- [Day 07: Laboratories](aoc_2025/src/day_07.rs)
1515
- [Day 08: Playground](aoc_2025/src/day_08.rs)
1616
- [Day 09: Movie Theater](aoc_2025/src/day_09.rs)
17+
- [Day 10: Factory](aoc_2025/src/day_10.rs)
1718
<!-- MARKER -->
1819

1920
## [2024](https://adventofcode.com/2024) [![aoc_2024](https://github.com/connorslade/advent-of-code/actions/workflows/aoc_2024.yml/badge.svg)](https://github.com/connorslade/advent-of-code/actions/workflows/aoc_2024.yml)

aoc_2025/src/day_10.rs

Lines changed: 219 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,219 @@
1+
use std::{
2+
collections::{HashMap, HashSet, VecDeque},
3+
u64,
4+
};
5+
6+
use common::{Answer, solution};
7+
use itertools::Itertools;
8+
9+
solution!("Factory", 10);
10+
11+
#[derive(Debug)]
12+
struct Machine {
13+
lights: Vec<bool>,
14+
buttons: Vec<Vec<usize>>,
15+
joltage: Vec<u64>,
16+
}
17+
18+
impl Machine {
19+
fn parse(line: &str) -> Self {
20+
let (lights, line) = line.split_once(' ').unwrap();
21+
let lights = lights[1..lights.len() - 1]
22+
.chars()
23+
.map(|x| x == '#')
24+
.collect::<Vec<_>>();
25+
26+
let (buttons, joltage) = line.rsplit_once(' ').unwrap();
27+
let buttons = buttons
28+
.split_whitespace()
29+
.map(|x| {
30+
x[1..x.len() - 1]
31+
.split(',')
32+
.map(|x| x.parse::<usize>().unwrap())
33+
.collect::<Vec<_>>()
34+
})
35+
.collect::<Vec<_>>();
36+
37+
let joltage = joltage[1..joltage.len() - 1]
38+
.split(',')
39+
.map(|x| x.parse::<u64>().unwrap())
40+
.collect::<Vec<_>>();
41+
42+
Machine {
43+
lights,
44+
buttons,
45+
joltage,
46+
}
47+
}
48+
49+
fn min_presses_a(&self) -> u64 {
50+
let mut queue = VecDeque::new();
51+
let mut seen = HashSet::new();
52+
queue.push_back((vec![false; self.lights.len()], 0));
53+
54+
while let Some((lights, presses)) = queue.pop_front() {
55+
dbg!(queue.len());
56+
if lights == self.lights {
57+
return presses;
58+
}
59+
60+
for buttons in &self.buttons {
61+
let mut next = lights.clone();
62+
for button in buttons {
63+
next[*button] ^= true;
64+
}
65+
66+
if !seen.contains(&next) {
67+
seen.insert(next.clone());
68+
queue.push_back((next, presses + 1));
69+
}
70+
}
71+
}
72+
73+
0
74+
}
75+
76+
fn inner(&self, seen: &mut HashMap<Vec<u64>, u64>, joltage: Vec<u64>, depth: u64) -> u64 {
77+
if let Some(seen) = seen.get(&joltage) {
78+
return *seen;
79+
}
80+
81+
if *joltage == self.joltage {
82+
return 1;
83+
}
84+
85+
if joltage
86+
.iter()
87+
.zip(self.joltage.iter())
88+
.any(|(a, b)| *a > *b)
89+
{
90+
return u64::MAX - 1;
91+
}
92+
93+
let mut min = u64::MAX - 1;
94+
95+
for buttons in &self.buttons {
96+
let mut next = joltage.clone();
97+
for button in buttons {
98+
next[*button] += 1;
99+
}
100+
101+
min = min.min(self.inner(seen, next, depth + 1) + 1);
102+
}
103+
104+
seen.insert(joltage.to_owned(), min);
105+
min
106+
}
107+
108+
fn min_presses_b(&self) -> u64 {
109+
let mut queue = VecDeque::new();
110+
let mut seen = HashSet::new();
111+
queue.push_back(vec![0; self.buttons.len()]);
112+
113+
while let Some(buttons) = queue.pop_front() {
114+
let mut joltage = vec![0; self.joltage.len()];
115+
let mut presses = 0;
116+
117+
for (count, buttons) in buttons.iter().zip(self.buttons.iter()) {
118+
presses += count;
119+
for button in buttons.iter() {
120+
joltage[*button] += count;
121+
}
122+
}
123+
124+
if joltage == self.joltage {
125+
return presses;
126+
}
127+
128+
for i in 0..self.buttons.len() {
129+
let mut next = buttons.clone();
130+
next[i] += 1;
131+
132+
if !seen.contains(&next) {
133+
seen.insert(next.clone());
134+
queue.push_back(next);
135+
}
136+
}
137+
}
138+
139+
0
140+
// self.inner(&mut HashMap::new(), vec![0; self.joltage.len()], 0) - 1
141+
}
142+
}
143+
144+
fn parse(input: &str) -> Vec<Machine> {
145+
input.lines().map(|x| Machine::parse(x)).collect()
146+
}
147+
148+
fn part_a(input: &str) -> Answer {
149+
let machines = parse(input);
150+
151+
let mut sum = 0;
152+
for machine in machines {
153+
sum += dbg!(machine.min_presses_a());
154+
}
155+
156+
sum.into()
157+
}
158+
159+
// currently generating code to paste into mathematica :eyes:
160+
fn part_b(input: &str) -> Answer {
161+
let machines = parse(input);
162+
163+
let chars = b"abcdefghijklmnopqrstuvwxyz";
164+
for machine in machines {
165+
let mut constraints = Vec::new();
166+
for (i, j) in machine.joltage.iter().enumerate() {
167+
let pos = machine
168+
.buttons
169+
.iter()
170+
.enumerate()
171+
.filter(|(_i, x)| x.contains(&i))
172+
.map(|(i, _)| chars[i] as char)
173+
.join("+");
174+
constraints.push(format!("{j}=={pos}"));
175+
}
176+
177+
for i in 0..machine.buttons.len() {
178+
constraints.push(format!(
179+
"{c}>=0,{c}\\[Element] Integers",
180+
c = chars[i] as char
181+
));
182+
}
183+
184+
let sum = (0..machine.buttons.len())
185+
.map(|i| (chars[i] as char).to_string())
186+
.join("+");
187+
let vars = (0..machine.buttons.len())
188+
.map(|i| (chars[i] as char).to_string())
189+
.join(",");
190+
191+
println!(
192+
"Total[#[[2]] & /@ LinearOptimization[{sum}, {{{}}}, {{{vars}}}]] +",
193+
constraints.join(",")
194+
);
195+
}
196+
197+
().into()
198+
}
199+
200+
#[cfg(test)]
201+
mod test {
202+
use indoc::indoc;
203+
204+
const CASE: &str = indoc! {"
205+
[.##.] (3) (1,3) (2) (2,3) (0,2) (0,1) {3,5,4,7}
206+
[...#.] (0,2,3,4) (2,3) (0,4) (0,1,2) (1,2,3,4) {7,5,12,7,2}
207+
[.###.#] (0,1,2,3,4) (0,3,4) (0,1,2,4,5) (1,2) {10,11,11,5,10,5}
208+
"};
209+
210+
#[test]
211+
fn part_a() {
212+
assert_eq!(super::part_a(CASE), 7.into());
213+
}
214+
215+
#[test]
216+
fn part_b() {
217+
assert_eq!(super::part_b(CASE), ().into());
218+
}
219+
}

aoc_2025/src/lib.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ mod day_06;
99
mod day_07;
1010
mod day_08;
1111
mod day_09;
12+
mod day_10;
1213
// [import_marker]
1314

1415
pub const SOLUTIONS: &[Solution] = &[
@@ -21,5 +22,6 @@ pub const SOLUTIONS: &[Solution] = &[
2122
day_07::SOLUTION,
2223
day_08::SOLUTION,
2324
day_09::SOLUTION,
25+
day_10::SOLUTION,
2426
// [list_marker]
2527
];

0 commit comments

Comments
 (0)