diff --git a/src/main.rs b/src/main.rs index 25a2adc..4aea29f 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}, + collections::{BinaryHeap, HashMap, HashSet, VecDeque}, fmt::Display, hash::{DefaultHasher, Hash, Hasher}, io::{self, Write, stdin, stdout}, iter, - num::NonZero, + num::{self, NonZero}, ops::ControlFlow, }; @@ -60,6 +60,12 @@ 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], @@ -68,7 +74,7 @@ impl Tower { pub fn new(rings: &[Ring]) -> Self { let mut tower = Self::EMPTY; - for (src, dst) in rings.iter().zip(&mut tower.rings) { + for (src, dst) in rings.into_iter().zip(&mut tower.rings) { *dst = Some(*src); } @@ -81,19 +87,22 @@ impl Tower { let mut max_same_ring_type_score = 0; let mut burried_score = 0; - 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; + 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); + } } 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); } } @@ -197,16 +206,18 @@ impl Tower { let mut ring_type = None; let mut count = 0; - for ring in self.rings.iter().flatten() { - if let Some(existing_ring_type) = ring_type { - if existing_ring_type == *ring { - count += 1; + 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; + } } else { - return None; + count = 1; + ring_type = Some(*ring); } - } else { - count = 1; - ring_type = Some(*ring); } } @@ -245,12 +256,14 @@ impl Game { let mut ring_sets = HashMap::new(); for t in &towers { t.check(); - for r in t.rings.iter().flatten() { - *ring_sets.entry(*r).or_insert(0) += 1; + for r in &t.rings { + if let Some(r) = r { + *ring_sets.entry(*r).or_insert(0) += 1; + } } } - for ring in ring_sets.keys() { + for (ring, _num) in &ring_sets { // 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}"); @@ -319,14 +332,9 @@ impl Game { hasher.finish() }; - #[derive(PartialEq)] + #[derive(PartialEq, PartialOrd)] 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) @@ -741,12 +749,6 @@ impl UndoStack { } } -impl Default for UndoStack { - fn default() -> Self { - Self::new() - } -} - fn main() -> io::Result<()> { let mut g = GameGenerator { num_extra_towers: 2, @@ -782,12 +784,6 @@ 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]);