use std::fmt;
use std::collections::HashMap;
use crate::bitgrid8::BitGrid8;
use derive_more::*;
use arrayvec::*;
use crate::bitlib::swap_mask_shift_u64;
#[derive(Copy, Clone, Eq, PartialEq, Hash, PartialOrd, Ord,
BitAnd, BitAndAssign, BitOr, BitOrAssign, BitXor, BitXorAssign,
)]
pub struct BitPara8(pub u64);
impl fmt::Debug for BitPara8 {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "BitGrid8({:#010x})", self.0)
}
}
impl fmt::Display for BitPara8 {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "{}",
(0..8).rev().map(|y|
(0..8)
.map(|x| format!("{}", if (self.0 >> (x + 8*y)) & 0x1 == 1 { "🟥" } else { "⬜" }))
.collect::<String>()
+"\n")
.collect::<String>()
)
}
}
pub const HEX4: BitPara8 = BitPara8(0x78_7c7e_7f3f_1f0f);
pub const FULL: BitPara8 = BitPara8(0xffff_ffff_ffff_ffff);
pub const ASTERISK: BitPara8 = BitPara8(0x4828187f0c0a09);
pub const THREE_HEX: BitPara8 = BitPara8(0x6c7e360c0e06);
pub const LARGE_X: BitPara8 = BitPara8(0x8142_2418_1824_4281);
pub const LARGE_Z: BitPara8 = BitPara8(0xff40_2010_0804_02ff);
pub const SLASH: BitPara8 = BitPara8(0x8040_2010_0804_0201);
impl BitPara8 {
pub fn has_overlap(self, other: Self) -> bool {
self.0 & other.0 != 0
}
#[inline(always)]
pub fn is_empty(self) -> bool {
self.0 == 0
}
pub fn rotate_all_vec(self) -> ArrayVec::<Self, 4> {
let mut vec = ArrayVec::<Self, 4>::new();
let mut x = self;
vec.push(x);
for _ in 0..2 { x = x.rotate_180(); vec.push(x); }
vec.sort_unstable();
let symmetries = vec.partition_dedup().0.len(); vec.truncate(symmetries);
vec
}
#[inline]
pub fn rotate_180(self) -> Self {
let mut grid: u64 = self.0;
swap_mask_shift_u64(&mut grid, 0x0f0f_0f0f, 36);
swap_mask_shift_u64(&mut grid, 0xf0f0_f0f0, 28);
swap_mask_shift_u64(&mut grid, 0x0000_3333_0000_3333, 18);
swap_mask_shift_u64(&mut grid, 0x0000_cccc_0000_cccc, 14);
swap_mask_shift_u64(&mut grid, 0x0055_0055_0055_0055, 9);
swap_mask_shift_u64(&mut grid, 0x00aa_00aa_00aa_00aa, 7);
Self(grid)
}
pub fn flip_x(self) -> Self {
let mut grid = self.0;
swap_mask_shift_u64(&mut grid, 0xffff_ffff, 32);
swap_mask_shift_u64(&mut grid, 0xffff_0000_ffff, 16);
swap_mask_shift_u64(&mut grid, 0x00ff_00ff_00ff_00ff, 8);
Self(grid)
}
pub fn flip_ne(self) -> Self {
let mut grid = self.0;
swap_mask_shift_u64(&mut grid, 0x0f0f_0f0f, 36);
swap_mask_shift_u64(&mut grid, 0x0000_3333_0000_3333, 18);
swap_mask_shift_u64(&mut grid, 0x0055_0055_0055_0055, 9);
Self(grid)
}
pub fn flip_nw(self) -> Self {
let mut grid = self.0;
swap_mask_shift_u64(&mut grid, 0xf0f0_f0f0, 28);
swap_mask_shift_u64(&mut grid, 0x0000_cccc_0000_cccc, 14);
swap_mask_shift_u64(&mut grid, 0x00aa_00aa_00aa_00aa, 7);
Self(grid)
}
}
#[cfg(test)]
mod test {
use super::*;
#[test]
fn test_bithex8_display() {
println!("{}", FULL);
assert_eq!(format!("{}", FULL),
"🟥🟥🟥🟥🟥🟥🟥🟥\n🟥🟥🟥🟥🟥🟥🟥🟥\n🟥🟥🟥🟥🟥🟥🟥🟥\n🟥🟥🟥🟥🟥🟥🟥🟥\n🟥🟥🟥🟥🟥🟥🟥🟥\n🟥🟥🟥🟥🟥🟥🟥🟥\n🟥🟥🟥🟥🟥🟥🟥🟥\n🟥🟥🟥🟥🟥🟥🟥🟥\n");
assert_eq!(format!("{}", BitPara8(0x1)),
"⬜⬜⬜⬜⬜⬜⬜⬜\n⬜⬜⬜⬜⬜⬜⬜⬜\n⬜⬜⬜⬜⬜⬜⬜⬜\n⬜⬜⬜⬜⬜⬜⬜⬜\n⬜⬜⬜⬜⬜⬜⬜⬜\n⬜⬜⬜⬜⬜⬜⬜⬜\n⬜⬜⬜⬜⬜⬜⬜⬜\n🟥⬜⬜⬜⬜⬜⬜⬜\n");
}
#[test]
fn test_bitpara_rotate_180() {
assert_eq!(FULL, FULL.rotate_180());
println!("{}", LARGE_Z);
assert_eq!(LARGE_Z, LARGE_Z.rotate_180());
assert_ne!(ASTERISK, ASTERISK.rotate_180());
assert_eq!(ASTERISK, ASTERISK.rotate_180().rotate_180());
}
#[test]
fn test_bitpara_flip_x() {
assert_eq!(FULL, FULL.flip_x());
assert_eq!(LARGE_X, LARGE_X.flip_x());
assert_ne!(ASTERISK, ASTERISK.flip_x());
assert_eq!(ASTERISK, ASTERISK.flip_x().flip_x());
assert_ne!(THREE_HEX, THREE_HEX.flip_x());
assert_eq!(THREE_HEX, THREE_HEX.flip_x().flip_x());
assert_ne!(SLASH, SLASH.flip_x());
assert_eq!(SLASH, SLASH.flip_x().flip_x());
}
#[test]
fn test_bitpara_flip_ne() {
assert_eq!(FULL, FULL.flip_ne());
assert_eq!(LARGE_X, LARGE_X.flip_ne());
assert_eq!(SLASH, SLASH.flip_ne());
assert_ne!(ASTERISK, ASTERISK.flip_ne());
assert_eq!(ASTERISK, ASTERISK.flip_ne().flip_ne());
assert_ne!(THREE_HEX, THREE_HEX.flip_ne());
assert_eq!(THREE_HEX, THREE_HEX.flip_ne().flip_ne());
}
#[test]
fn test_bitpara_flip_nw() {
assert_eq!(FULL, FULL.flip_nw());
assert_eq!(LARGE_X, LARGE_X.flip_nw());
assert_eq!(SLASH, SLASH.flip_nw());
assert_eq!(ASTERISK, ASTERISK.flip_nw());
assert_ne!(LARGE_Z, LARGE_Z.flip_nw());
assert_eq!(LARGE_Z, LARGE_Z.flip_nw().flip_nw());
assert_ne!(THREE_HEX, THREE_HEX.flip_nw());
assert_eq!(THREE_HEX, THREE_HEX.flip_nw().flip_nw());
}
}