day10: part1

This commit is contained in:
2025-12-09 22:13:52 -08:00
parent 72d7dc1cbb
commit 73b44b1377
4 changed files with 190 additions and 1 deletions

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.7 KiB

View File

@@ -1,6 +1,6 @@
<!-- AOC TILES BEGIN --> <!-- AOC TILES BEGIN -->
<h1 align="center"> <h1 align="center">
2025 - 17 ⭐ - Rust 2025 - 18 ⭐ - Rust
</h1> </h1>
<a href="src/day1.rs"> <a href="src/day1.rs">
<img src=".aoc_tiles/tiles/2025/01.png" width="161px"> <img src=".aoc_tiles/tiles/2025/01.png" width="161px">
@@ -29,4 +29,7 @@
<a href="src/day9.rs"> <a href="src/day9.rs">
<img src=".aoc_tiles/tiles/2025/09.png" width="161px"> <img src=".aoc_tiles/tiles/2025/09.png" width="161px">
</a> </a>
<a href="src/day10.rs">
<img src=".aoc_tiles/tiles/2025/10.png" width="161px">
</a>
<!-- AOC TILES END --> <!-- AOC TILES END -->

185
src/day10.rs Normal file
View File

@@ -0,0 +1,185 @@
use std::{collections::BinaryHeap, iter::repeat_n};
use aoc_runner_derive::{aoc, aoc_generator};
use itertools::Itertools;
use regex::Regex;
#[derive(Clone, Debug, Default)]
struct MachineDefinition {
desired: Vec<bool>,
buttons: Vec<Vec<usize>>,
joltages: Vec<u64>,
}
impl MachineDefinition {
fn create<'a>(&'a self) -> Machine<'a> {
Machine {
d: self,
lights: Vec::from_iter(repeat_n(false, self.desired.len())),
}
}
}
impl From<&str> for MachineDefinition {
fn from(value: &str) -> Self {
let parse_re = Regex::new(
r##"\[(?<desired>[.#]+)\] (?<buttons>(\([0-9,]+\) ?)+) \{(?<joltages>[0-9,]+)\}"##,
)
.unwrap();
let parts = parse_re.captures(value).unwrap();
MachineDefinition {
desired: parts["desired"].chars().map(|c| c == '#').collect(),
buttons: parts["buttons"]
.split_ascii_whitespace()
.map(|s| {
s[1..s.len() - 1]
.split(',')
.map(|n| n.parse().unwrap())
.collect()
})
.collect(),
joltages: parts["joltages"]
.split(',')
.map(|n| n.parse().unwrap())
.collect(),
}
}
}
#[derive(Clone, Debug)]
struct Machine<'a> {
d: &'a MachineDefinition,
lights: Vec<bool>,
}
impl<'a> Machine<'a> {
/// Get the state after pressing `button`, returns None if the state is as desired
fn press(&self, button: usize) -> Option<Self> {
let mut new_state = self.lights.clone();
for light in &self.d.buttons[button] {
new_state[*light] = !new_state[*light]
}
if new_state == self.d.desired {
None
} else {
Some(Machine {
d: self.d,
lights: new_state,
})
}
}
/// Get the possible states from the current position
fn next_states(&self) -> Vec<(usize, Option<Machine<'a>>)> {
self.d
.buttons
.iter()
.enumerate()
.map(|(i, _but)| (i, self.press(i)))
.collect()
}
}
#[derive(Debug, Clone)]
struct PressSet<'a> {
machine: Machine<'a>,
presses: Vec<usize>,
}
// NOTE: All compares are reversed so our max heap becomes a min heap
impl<'a> Eq for PressSet<'a> {}
impl<'a> PartialEq for PressSet<'a> {
fn eq(&self, other: &Self) -> bool {
other.presses.len().eq(&self.presses.len())
}
}
impl<'a> PartialOrd for PressSet<'a> {
fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
other.presses.len().partial_cmp(&self.presses.len())
}
}
impl<'a> Ord for PressSet<'a> {
fn cmp(&self, other: &Self) -> std::cmp::Ordering {
other.presses.len().cmp(&self.presses.len())
}
}
fn find_best<'a>(md: &'a MachineDefinition) -> Vec<usize> {
let m = md.create();
let mut to_check = BinaryHeap::new();
for next in m.next_states() {
if let Some(new_m) = next.1 {
to_check.push(PressSet {
presses: vec![next.0],
machine: new_m.clone(),
})
} else {
// what we found a solution on the first move?
return vec![next.0];
}
}
while let Some(candidate) = to_check.pop() {
let cm = candidate.machine.clone();
for next in cm.next_states() {
let mut presses = candidate.presses.clone();
presses.push(next.0);
if let Some(new_m) = next.1 {
to_check.push(PressSet {
presses,
machine: new_m.clone(),
})
} else {
return presses;
}
}
}
panic!()
}
#[aoc_generator(day10)]
fn parse(input: &str) -> Vec<MachineDefinition> {
input.lines().map(|l| l.into()).collect()
}
#[aoc(day10, part1)]
fn part1(input: &Vec<MachineDefinition>) -> u64 {
input
.into_iter()
.map(|md| find_best(md))
// .inspect(|sol| println!(" [{sol:?}]"))
.map(|sol| sol.len() as u64)
.sum()
}
#[aoc(day10, part2)]
fn part2(input: &Vec<MachineDefinition>) -> u64 {
0
}
#[cfg(test)]
mod tests {
use rstest::rstest;
use super::*;
const EXAMPLE: &str = "[.##.] (3) (1,3) (2) (2,3) (0,2) (0,1) {3,5,4,7}
[...#.] (0,2,3,4) (2,3) (0,4) (0,1,2) (1,2,3,4) {7,5,12,7,2}
[.###.#] (0,1,2,3,4) (0,3,4) (0,1,2,4,5) (1,2) {10,11,11,5,10,5}";
#[rstest]
#[case(EXAMPLE, 7)]
fn part1_example(#[case] input: &str, #[case] expected: u64) {
assert_eq!(part1(&parse(input)), expected);
}
#[rstest]
#[case(EXAMPLE, 0)]
fn part2_example(#[case] input: &str, #[case] expected: u64) {
assert_eq!(part2(&parse(input)), expected);
}
}

View File

@@ -1,4 +1,5 @@
mod day1; mod day1;
mod day10;
mod day2; mod day2;
mod day3; mod day3;
mod day4; mod day4;