day10: small performance boost

This commit is contained in:
2025-12-09 22:45:33 -08:00
parent 73b44b1377
commit 0a5e5c8798

View File

@@ -1,7 +1,6 @@
use std::{collections::BinaryHeap, iter::repeat_n};
use std::{collections::BinaryHeap, hash::Hash, iter::repeat_n};
use aoc_runner_derive::{aoc, aoc_generator};
use itertools::Itertools;
use regex::Regex;
#[derive(Clone, Debug, Default)]
@@ -54,6 +53,19 @@ struct Machine<'a> {
lights: Vec<bool>,
}
impl<'a> Eq for Machine<'a> {}
impl<'a> PartialEq for Machine<'a> {
fn eq(&self, other: &Self) -> bool {
self.lights == other.lights
}
}
impl<'a> Hash for Machine<'a> {
fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
self.lights.hash(state)
}
}
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> {
@@ -85,7 +97,7 @@ impl<'a> Machine<'a> {
#[derive(Debug, Clone)]
struct PressSet<'a> {
machine: Machine<'a>,
presses: Vec<usize>,
presses: usize,
}
// NOTE: All compares are reversed so our max heap becomes a min heap
@@ -93,41 +105,41 @@ 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())
other.presses.eq(&self.presses)
}
}
impl<'a> PartialOrd for PressSet<'a> {
fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
other.presses.len().partial_cmp(&self.presses.len())
Some(self.cmp(other))
}
}
impl<'a> Ord for PressSet<'a> {
fn cmp(&self, other: &Self) -> std::cmp::Ordering {
other.presses.len().cmp(&self.presses.len())
other.presses.cmp(&self.presses)
}
}
fn find_best<'a>(md: &'a MachineDefinition) -> Vec<usize> {
fn find_best(md: &MachineDefinition) -> 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],
presses: 1,
machine: new_m.clone(),
})
} else {
// what we found a solution on the first move?
return vec![next.0];
return 1;
}
}
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);
let presses = candidate.presses + 1;
if let Some(new_m) = next.1 {
to_check.push(PressSet {
presses,
@@ -147,17 +159,17 @@ fn parse(input: &str) -> Vec<MachineDefinition> {
}
#[aoc(day10, part1)]
fn part1(input: &Vec<MachineDefinition>) -> u64 {
fn part1(input: &[MachineDefinition]) -> u64 {
input
.into_iter()
.map(|md| find_best(md))
.iter()
.map(find_best)
// .inspect(|sol| println!(" [{sol:?}]"))
.map(|sol| sol.len() as u64)
.map(|sol| sol as u64)
.sum()
}
#[aoc(day10, part2)]
fn part2(input: &Vec<MachineDefinition>) -> u64 {
fn part2(input: &[MachineDefinition]) -> u64 {
0
}
@@ -178,7 +190,7 @@ mod tests {
}
#[rstest]
#[case(EXAMPLE, 0)]
#[case(EXAMPLE, 33)]
fn part2_example(#[case] input: &str, #[case] expected: u64) {
assert_eq!(part2(&parse(input)), expected);
}