Skip to content

Commit b5b2cf6

Browse files
committed
chore: WIP of y2025::day_10
1 parent 0f0094e commit b5b2cf6

File tree

7 files changed

+159
-3
lines changed

7 files changed

+159
-3
lines changed

.run/run_aoc.run.xml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
<component name="ProjectRunConfigurationManager">
22
<configuration default="false" name="run_aoc" type="CargoCommandRunConfiguration" factoryName="Cargo Command">
33
<option name="buildProfileId" value="dev" />
4-
<option name="command" value="run --package aoclp_solutions --bin aoclp_solutions -- --year 2025 --day 9" />
4+
<option name="command" value="run --package aoclp_solutions --bin aoclp_solutions -- --year 2025 --day 10" />
55
<option name="workingDirectory" value="file://$PROJECT_DIR$" />
66
<envs />
77
<option name="emulateTerminal" value="true" />

Cargo.lock

Lines changed: 46 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,5 +14,6 @@ itertools = "0.14.0"
1414
num = "0.4.3"
1515
paste = "1.0.15"
1616
primes = "0.4.0"
17+
rayon = "1.11.0"
1718
regex = "1.12.2"
1819
strum = { version = "0.27.2", features = ["derive"] }

aoclp_solutions/Cargo.toml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
name = "aoclp_solutions"
33
version = "0.1.0"
44
edition = "2021"
5-
rust-version = "1.81.0"
5+
rust-version = "1.82.0"
66

77
[dependencies]
88
aoclp = { path = "../aoclp" }
@@ -11,4 +11,5 @@ clap = { workspace = true, features = ["derive"] }
1111
derive-where = { workspace = true }
1212
itertools = { workspace = true }
1313
primes = { workspace = true }
14+
rayon = { workspace = true }
1415
strum = { workspace = true, features = ["derive"] }

aoclp_solutions/src/lib.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,5 +11,5 @@ pub mod y2025;
1111
build_solvers! {
1212
{ 2017, [01, 02, 03, 04, 05, 06, 07, 08, 09, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25] },
1313
{ 2024, [01, 02, 03, 04, 05, 06, 07, 08, 09, 10] },
14-
{ 2025, [01, 02, 03, 04, 05, 06, 07, 08, 09] }
14+
{ 2025, [01, 02, 03, 04, 05, 06, 07, 08, 09, 10] }
1515
}
Lines changed: 107 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,107 @@
1+
use std::collections::HashMap;
2+
use rayon::iter::{IntoParallelRefIterator, ParallelIterator};
3+
use std::str::FromStr;
4+
use std::sync::OnceLock;
5+
use itertools::Itertools;
6+
use aoclp::anyhow::Context;
7+
use aoclp::regex::Regex;
8+
use aoclp::solvers_impl::input::safe_get_input_as_many;
9+
10+
pub fn part_1() -> usize {
11+
input().iter().map(Machine::fewest_presses_for_lights).sum()
12+
}
13+
14+
pub fn part_2() -> usize {
15+
input().par_iter().map(Machine::fewest_presses_for_joltage).sum()
16+
}
17+
18+
#[derive(Debug, Clone)]
19+
struct Machine {
20+
target_lights: Vec<bool>,
21+
button_wirings: Vec<Vec<usize>>,
22+
joltage_reqs: Vec<usize>,
23+
}
24+
25+
impl Machine {
26+
fn fewest_presses_for_lights(&self) -> usize {
27+
let mut presses = 0;
28+
let mut states = vec![vec![false; self.target_lights.len()]];
29+
loop {
30+
if states.iter().contains(&self.target_lights) {
31+
break presses;
32+
}
33+
34+
states = states
35+
.into_iter()
36+
.flat_map(|l| {
37+
self.button_wirings
38+
.iter()
39+
.map(move |wiring| {
40+
let mut next = l.clone();
41+
for w in wiring {
42+
next[*w] = !next[*w]
43+
}
44+
next
45+
})
46+
})
47+
.unique()
48+
.collect();
49+
presses += 1;
50+
}
51+
}
52+
53+
fn fewest_presses_for_joltage(&self) -> usize {
54+
let mut cache = HashMap::new();
55+
self.fewest_presses_for_joltage_from(vec![0; self.joltage_reqs.len()], 0, usize::MAX, &mut cache)
56+
}
57+
58+
fn fewest_presses_for_joltage_from(&self, cur: Vec<usize>, steps: usize, max_steps: usize, cache: &mut HashMap<Vec<usize>, usize>) -> usize {
59+
if *cur == self.joltage_reqs {
60+
return steps;
61+
} else if let Some(presses) = cache.get(&cur) {
62+
return *presses;
63+
} else if steps == max_steps || cur.iter().zip(self.joltage_reqs.iter()).any(|(cur, req)| *cur > *req) {
64+
return max_steps;
65+
}
66+
67+
let presses = self.button_wirings
68+
.iter()
69+
.fold(max_steps, |max, wiring| {
70+
let mut next = cur.clone();
71+
for w in wiring {
72+
next[*w] += 1;
73+
}
74+
self.fewest_presses_for_joltage_from(next, steps + 1, max, cache)
75+
});
76+
cache.insert(cur, presses);
77+
presses
78+
}
79+
}
80+
81+
impl FromStr for Machine {
82+
type Err = aoclp::Error;
83+
84+
fn from_str(s: &str) -> Result<Self, Self::Err> {
85+
static REGEX: OnceLock<Regex> = OnceLock::new();
86+
let re = REGEX.get_or_init(|| {
87+
Regex::new(r"^\s*\[(?<lights>[.#]+)]\s+(?<buttons>(?:\((?:\d+,?)+\)\s+)+)\s*\{(?<joltage>(?:\d+,?)+)}\s*$").unwrap()
88+
});
89+
90+
let captures = re.captures(s).with_context(|| format!("invalid machine spec: {s}"))?;
91+
let target_lights = &captures["lights"];
92+
let button_wirings = &captures["buttons"];
93+
let joltage_reqs = &captures["joltage"];
94+
95+
let target_lights = target_lights.chars().map(|c| c == '#').collect();
96+
let button_wirings = button_wirings.split_ascii_whitespace().map(|bw| {
97+
bw[1..bw.len() - 1].split(',').map(|l| l.parse::<usize>()).try_collect()
98+
}).try_collect()?;
99+
let joltage_reqs = joltage_reqs.split(',').map(|j| j.parse::<usize>()).try_collect()?;
100+
101+
Ok(Self { target_lights, button_wirings, joltage_reqs })
102+
}
103+
}
104+
105+
fn input() -> Vec<Machine> {
106+
safe_get_input_as_many(2025, 10)
107+
}

aoclp_solutions/src/y2025/mod.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,3 +7,4 @@ pub mod day_06;
77
pub mod day_07;
88
pub mod day_08;
99
pub mod day_09;
10+
pub mod day_10;

0 commit comments

Comments
 (0)