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