diff --git a/src/main.rs b/src/main.rs index fc41c56..7ae8744 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,11 +1,11 @@ use palette::{IntoColor, OklabHue, Oklch, Srgb}; use std::{ - collections::{BinaryHeap, HashMap, HashSet, VecDeque}, + collections::{BinaryHeap, HashMap, HashSet}, fmt::Display, hash::{DefaultHasher, Hash, Hasher}, io::{self, Write, stdin, stdout}, iter, - num::{self, NonZero}, + num::NonZero, ops::ControlFlow, }; @@ -60,12 +60,6 @@ pub struct Tower { pub rings: [Option; TOWER_HEIGHT], } -macro_rules! tower { - ($($rings: literal),*) => { - Tower::new(&[$(Ring(std::num::NonZero::new($rings).unwrap())),*]) - }; -} - impl Tower { const EMPTY: Self = Self { rings: [None; TOWER_HEIGHT], @@ -74,7 +68,7 @@ impl Tower { pub fn new(rings: &[Ring]) -> Self { let mut tower = Self::EMPTY; - for (src, dst) in rings.into_iter().zip(&mut tower.rings) { + for (src, dst) in rings.iter().zip(&mut tower.rings) { *dst = Some(*src); } @@ -87,22 +81,19 @@ impl Tower { let mut max_same_ring_type_score = 0; let mut burried_score = 0; - for i in self.rings.iter().rev() { - if let Some(ring) = i { - if let Some(existing_ring_type) = ring_type { - if existing_ring_type == *ring { - same_ring_type_score += 2; - } else { - max_same_ring_type_score = - max_same_ring_type_score.max(same_ring_type_score); - burried_score += 2usize.pow(max_same_ring_type_score); - same_ring_type_score = 0; - ring_type = Some(*ring); - } + for ring in self.rings.iter().rev().flatten() { + if let Some(existing_ring_type) = ring_type { + if existing_ring_type == *ring { + same_ring_type_score += 2; } else { + max_same_ring_type_score = max_same_ring_type_score.max(same_ring_type_score); + burried_score += 2usize.pow(max_same_ring_type_score); same_ring_type_score = 0; ring_type = Some(*ring); } + } else { + same_ring_type_score = 0; + ring_type = Some(*ring); } } @@ -206,18 +197,16 @@ impl Tower { let mut ring_type = None; let mut count = 0; - for i in &self.rings { - if let Some(ring) = i { - if let Some(existing_ring_type) = ring_type { - if existing_ring_type == *ring { - count += 1; - } else { - return None; - } + for ring in self.rings.iter().flatten() { + if let Some(existing_ring_type) = ring_type { + if existing_ring_type == *ring { + count += 1; } else { - count = 1; - ring_type = Some(*ring); + return None; } + } else { + count = 1; + ring_type = Some(*ring); } } @@ -256,14 +245,12 @@ impl Game { let mut ring_sets = HashMap::new(); for t in &towers { t.check(); - for r in &t.rings { - if let Some(r) = r { - *ring_sets.entry(*r).or_insert(0) += 1; - } + for r in t.rings.iter().flatten() { + *ring_sets.entry(*r).or_insert(0) += 1; } } - for (ring, _num) in &ring_sets { + for ring in ring_sets.keys() { // ok as long as the goal isn't sets of 4 but single-ringtype towers // if num != TOWER_HEIGHT { // panic!("incomplete ring set: expected {TOWER_HEIGHT} of {ring} but found {num}"); @@ -332,9 +319,14 @@ impl Game { hasher.finish() }; - #[derive(PartialEq, PartialOrd)] + #[derive(PartialEq)] struct Ordf32(f32); impl Eq for Ordf32 {} + impl PartialOrd for Ordf32 { + fn partial_cmp(&self, other: &Self) -> Option { + Some(self.cmp(other)) + } + } impl Ord for Ordf32 { fn cmp(&self, other: &Self) -> std::cmp::Ordering { self.0.total_cmp(&other.0) @@ -749,6 +741,12 @@ impl UndoStack { } } +impl Default for UndoStack { + fn default() -> Self { + Self::new() + } +} + fn main() -> io::Result<()> { let mut g = GameGenerator { num_extra_towers: 2, @@ -784,6 +782,12 @@ fn main() -> io::Result<()> { mod tests { use crate::{Game, Move, Ring, Tower}; + macro_rules! tower { + ($($rings: literal),*) => { + Tower::new(&[$(Ring(std::num::NonZero::new($rings).unwrap())),*]) + }; + } + #[test] fn test_moves() { let mut g = Game::<4>::new(vec![tower![1, 2, 1, 2], Tower::EMPTY, Tower::EMPTY]);