Skip to content

Commit 03221a4

Browse files
committed
day10 p2 as submitted
1 parent c30715f commit 03221a4

File tree

1 file changed

+118
-5
lines changed

1 file changed

+118
-5
lines changed

aoc2025_wasm/src/impl_2025_10.rs

Lines changed: 118 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
use anyhow::{Context, Result, bail};
2+
use rayon::prelude::*;
23
use std::{
4+
cmp::Reverse,
35
collections::{HashSet, VecDeque},
46
str::FromStr,
57
};
@@ -28,7 +30,7 @@ impl FromStr for InputLine {
2830
.map(|c| c == b'#')
2931
.collect::<Vec<_>>();
3032

31-
let wiring: Vec<Vec<usize>> = groups
33+
let mut wiring: Vec<Vec<usize>> = groups
3234
.get(1..groups.len() - 1)
3335
.context("not enough groups")?
3436
.iter()
@@ -40,6 +42,8 @@ impl FromStr for InputLine {
4042
})
4143
.collect::<Result<_, _>>()?;
4244

45+
wiring.sort_unstable_by_key(|w| Reverse(w.len()));
46+
4347
let joltages = groups
4448
.last()
4549
.context("not enough groups on line")?
@@ -104,15 +108,119 @@ fn calculate_p1_line(line: &InputLine) -> Result<u64> {
104108
bail!("no p1 solution");
105109
}
106110

107-
fn calculate(inp: &str) -> Result<(u64, &str)> {
111+
fn calc_lower_bound(state: &[i32]) -> i32 {
112+
*state.iter().max().unwrap_or(&i32::MAX)
113+
}
114+
115+
fn calc_upper_bound(state: &[i32]) -> i32 {
116+
state.iter().sum::<i32>()
117+
}
118+
119+
fn make_inequalities(line: &InputLine) -> Result<Vec<Vec<(usize, usize)>>> {
120+
// Inequalities where state[a] >= state[b] for a valid solution
121+
let mut inequalities = vec![];
122+
123+
for btn_idx in 0..line.wiring.len() {
124+
let mut ineq = vec![];
125+
for a in 0..line.joltages.len() {
126+
for b in 0..line.joltages.len() {
127+
if a == b {
128+
continue;
129+
}
130+
131+
if !line
132+
.wiring
133+
.iter()
134+
.skip(btn_idx)
135+
.any(|btn| btn.contains(&b) && !btn.contains(&a))
136+
{
137+
ineq.push((a, b));
138+
}
139+
}
140+
}
141+
inequalities.push(ineq);
142+
}
143+
Ok(inequalities)
144+
}
145+
146+
fn calculate_p2_line(line: &InputLine) -> Result<i32> {
147+
// (state, num_pushes)
148+
let mut q = vec![];
149+
150+
q.push((line.joltages.to_vec(), 0, 0));
151+
152+
let target_state = vec![0; line.joltages.len()];
153+
154+
let mut best = calc_upper_bound(&line.joltages);
155+
156+
// Inequalities where state[a] >= state[b] for a valid solution
157+
let inequalities = make_inequalities(line)?;
158+
159+
while let Some((state, num_pushes, button_idx)) = q.pop() {
160+
if state == target_state {
161+
if num_pushes < best {
162+
best = num_pushes;
163+
}
164+
continue;
165+
}
166+
167+
let lower_bound = calc_lower_bound(&state);
168+
169+
if num_pushes + lower_bound >= best
170+
|| inequalities
171+
.get(button_idx)
172+
.unwrap_or(&vec![])
173+
.iter()
174+
.any(|(a, b)| {
175+
if let Some(a) = state.get(*a)
176+
&& let Some(b) = state.get(*b)
177+
{
178+
a < b
179+
} else {
180+
true
181+
}
182+
})
183+
{
184+
continue;
185+
}
186+
187+
for button in button_idx..line.wiring.len() {
188+
let mut new_state = state.clone();
189+
let mut invalid = false;
190+
for itm in line.wiring.get(button).unwrap_or(&vec![]).iter() {
191+
let elem = new_state.get_mut(*itm).context("invalid itm")?;
192+
*elem -= 1;
193+
if *elem < 0 {
194+
invalid = true;
195+
break;
196+
}
197+
}
198+
199+
if invalid {
200+
continue;
201+
}
202+
203+
q.push((new_state, num_pushes + 1, button));
204+
}
205+
}
206+
207+
Ok(best)
208+
}
209+
210+
fn calculate(inp: &str) -> Result<(u64, i32)> {
108211
let lines = inp
109212
.lines()
110213
.map(|line| line.parse())
111214
.collect::<Result<Vec<InputLine>>>()?;
112215

113216
let p1 = lines.iter().map(calculate_p1_line).sum::<Result<u64>>()?;
114217

115-
Ok((p1, "p2 not implemented yet"))
218+
let p2 = lines
219+
.par_iter()
220+
.map(calculate_p2_line)
221+
.sum::<Result<i32>>()?;
222+
223+
Ok((p1, p2))
116224
}
117225

118226
pub fn run_2025_10(inp: &str) -> Result<String> {
@@ -132,8 +240,13 @@ mod tests {
132240
assert_eq!(calculate(EXAMPLE_DATA).unwrap().0, 7);
133241
}
134242

243+
// #[test]
244+
// fn test_real_p1() {
245+
// assert_eq!(calculate(REAL_DATA).unwrap().0, 422);
246+
// }
247+
135248
#[test]
136-
fn test_real_p1() {
137-
assert_eq!(calculate(REAL_DATA).unwrap().0, 422);
249+
fn test_example_p2() {
250+
assert_eq!(calculate(EXAMPLE_DATA).unwrap().1, 33);
138251
}
139252
}

0 commit comments

Comments
 (0)