use std::fmt::{Debug, Display};
#[derive(Clone, PartialEq, Eq, Default, Hash, PartialOrd, Ord)]
pub struct BitSet {
entries: Vec<u8>,
}
impl BitSet {
pub fn new(max_bit_count: u32) -> Self {
Self { entries: vec![0; ((max_bit_count + 7) / 8) as usize] }
}
pub fn has_bit(&self, bit: u32) -> bool {
(self.entries[bit as usize / 8] & (1 << (bit & 7))) != 0
}
pub fn set_bit(&mut self, bit: u32) {
self.entries[bit as usize / 8] |= 1 << (bit & 7);
}
pub fn is_empty(&self) -> bool {
self.entries.iter().all(|&e| e == 0)
}
pub fn union(&mut self, other: &Self) {
for (i, &e) in other.entries.iter().enumerate() {
self.entries[i] |= e;
}
}
}
impl Display for BitSet {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
let bit_string =
self.entries.iter().map(|e| format!("{e:08b}")).collect::<Vec<String>>().join("_");
f.write_str(&bit_string)
}
}
impl Debug for BitSet {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
let bit_string =
self.entries.iter().map(|e| format!("{e:08b}")).collect::<Vec<String>>().join("_");
f.debug_tuple("BitSet").field(&bit_string).finish()
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn basic() {
let mut bs = BitSet::new(1);
assert_eq!(bs.to_string(), "00000000");
bs.set_bit(0);
bs.set_bit(1);
bs.set_bit(7);
assert_eq!(bs.to_string(), "10000011");
let mut bs = BitSet::new(9);
assert_eq!(bs.to_string(), "00000000_00000000");
bs.set_bit(0);
bs.set_bit(1);
bs.set_bit(7);
assert_eq!(bs.to_string(), "10000011_00000000");
bs.set_bit(8);
assert_eq!(bs.to_string(), "10000011_00000001");
bs.set_bit(15);
assert_eq!(bs.to_string(), "10000011_10000001");
}
#[test]
fn union() {
let mut bs = BitSet::new(9);
assert_eq!(bs.to_string(), "00000000_00000000");
let mut bs2 = bs.clone();
bs.set_bit(0);
bs.set_bit(1);
bs.set_bit(7);
assert_eq!(bs.to_string(), "10000011_00000000");
bs2.set_bit(8);
bs2.set_bit(15);
assert_eq!(bs2.to_string(), "00000000_10000001");
bs.union(&bs2);
assert_eq!(bs.to_string(), "10000011_10000001");
}
}