diff options
Diffstat (limited to 'src/rectangular.rs')
| -rw-r--r-- | src/rectangular.rs | 92 |
1 files changed, 90 insertions, 2 deletions
diff --git a/src/rectangular.rs b/src/rectangular.rs index b1c4a23..8dcfa8b 100644 --- a/src/rectangular.rs +++ b/src/rectangular.rs @@ -2,7 +2,7 @@ use std::collections::{HashMap, HashSet}; use bitvec::{bitvec, order::Lsb0, vec::BitVec}; -use crate::CalanderPuzzle; +use crate::{CalendarBoardState, CalendarPuzzle}; // clockwise #[derive(Clone, Copy)] @@ -205,6 +205,10 @@ impl Puzzle { } } +pub struct BoardState { + bitvec: BitVec<u64>, +} + pub struct Placement { bitvec: BitVec<u64>, } @@ -215,9 +219,88 @@ impl Placement { } } -impl CalanderPuzzle for Puzzle { +fn intersects(a: &BitVec<u64>, b: &BitVec<u64>) -> bool { + match (a.domain(), b.domain()) { + (bitvec::domain::Domain::Region {head: ha, body: ba, tail: ta}, + bitvec::domain::Domain::Region {head: hb, body: bb, tail: tb}) => { + if let (Some(ha), Some(hb)) = (ha, hb) { + if ha.load_value() & hb.load_value() != 0 { + return true; + } + }; + + if ba.iter().zip(bb.iter()).any(|(a, b)| a & b != 0) { + return true; + } + + if let (Some(ta), Some(tb)) = (ta, tb) { + if ta.load_value() & tb.load_value() != 0 { + return true; + } + }; + + return false; + }, + _ => { + a.iter().by_vals().zip(b.iter().by_vals()).any(|(a,b)| a && b) + }, + } +} + +fn contains(a: &BitVec<u64>, b: &BitVec<u64>) -> bool { + match (a.domain(), b.domain()) { + (bitvec::domain::Domain::Region {head: ha, body: ba, tail: ta}, + bitvec::domain::Domain::Region {head: hb, body: bb, tail: tb}) => { + if let (Some(ha), Some(hb)) = (ha, hb) { + if !ha.load_value() & hb.load_value() != 0 { + return false; + } + }; + + if ba.iter().zip(bb.iter()).any(|(a, b)| !a & b != 0) { + return false; + } + + if let (Some(ta), Some(tb)) = (ta, tb) { + if !ta.load_value() & tb.load_value() != 0 { + return false; + } + }; + + return true; + }, + _ => { + a.iter().by_vals().zip(b.iter().by_vals()).any(|(a,b)| a || !b) + }, + } +} + +impl CalendarBoardState for BoardState { type Placement = Placement; + fn add_placement(&mut self, placement: &Self::Placement) -> bool { + if intersects(&self.bitvec, &placement.bitvec) { + false + } else { + self.bitvec |= &placement.bitvec; + true + } + } + + fn remove_placement(&mut self, placement: &Self::Placement) -> bool { + if contains(&self.bitvec, &placement.bitvec) { + self.bitvec ^= &placement.bitvec; + true + } else { + false + } + } +} + +impl CalendarPuzzle for Puzzle { + type Placement = Placement; + type BoardState = BoardState; + fn placements(&self, allow_flips: bool) -> Vec<Vec<Placement>> { // TODO remove identical placements let orientations = if allow_flips { @@ -280,5 +363,10 @@ impl CalanderPuzzle for Puzzle { } placements } + + fn empty_board_state(&self) -> BoardState { + BoardState { bitvec: bitvec![u64, Lsb0; 0; self.board.len()] } + } } + |
