summaryrefslogtreecommitdiff
path: root/src/rectangular.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/rectangular.rs')
-rw-r--r--src/rectangular.rs92
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()] }
+ }
}
+