day10: small performance boost
This commit is contained in:
46
src/day10.rs
46
src/day10.rs
@@ -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);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user