riichi_elements/tile_set/
tile_mask_34.rs1use core::fmt::{Display, Formatter};
2
3use derive_more::{
4 Constructor, From, Into,
5 BitAnd, BitOr, BitXor,
6 BitAndAssign, BitOrAssign, BitXorAssign,
7};
8
9use crate::tile::Tile;
10use super::{TileSet37, TileSet34};
11
12#[derive(
14 Copy, Clone, Debug, Default, Eq, PartialEq,
15 Constructor, From, Into,
16 BitAnd, BitOr, BitXor,
17 BitAndAssign, BitOrAssign, BitXorAssign,
18)]
19#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
20#[cfg_attr(feature = "serde", serde(transparent))] pub struct TileMask34(pub u64);
22
23impl TileMask34 {
24 pub const fn empty_set() -> Self { Self(0) }
26
27 pub const fn complete_set() -> Self { Self((1 << 34) - 1) }
29
30 pub fn is_empty(self) -> bool { self.0 == 0 }
32
33 pub fn any(self) -> bool { self.0 > 0 }
35
36 pub fn has(self, tile: Tile) -> bool {
38 (self.0 >> (tile.normal_encoding() as u64)) & 1 == 1
39 }
40
41 pub fn has_i(self, i: u8) -> bool {
43 (self.0 >> (i as u64)) & 1 == 1
44 }
45
46 pub fn set(&mut self, tile: Tile) {
48 self.0 |= 1 << (tile.normal_encoding() as u64);
49 }
50
51 pub fn clear(&mut self, tile: Tile) {
53 self.0 &= !(1 << (tile.normal_encoding() as u64));
54 }
55}
56
57impl FromIterator<Tile> for TileMask34 {
58 fn from_iter<T: IntoIterator<Item=Tile>>(tiles: T) -> Self {
59 let mut mask = 0u64;
60 for tile in tiles {
61 mask |= 1u64 << tile.normal_encoding() as u64;
62 }
63 Self(mask)
64 }
65}
66
67impl From<TileSet37> for TileMask34 {
68 fn from(ts37: TileSet37) -> Self {
69 let mut mask = 0u64;
70 for i in 0..34 {
71 if ts37[i] > 0 {
72 mask |= 1 << i;
73 }
74 }
75 if ts37[34] > 0 { mask |= 1 << 4; }
76 if ts37[35] > 0 { mask |= 1 << 13; }
77 if ts37[36] > 0 { mask |= 1 << 22; }
78 Self(mask)
79 }
80}
81
82impl From<TileSet34> for TileMask34 {
83 fn from(ts34: TileSet34) -> Self {
84 let mut mask = 0u64;
85 for i in 0..34 {
86 if ts34[i] > 0 {
87 mask |= 1 << i;
88 }
89 }
90 Self(mask)
91 }
92}
93
94impl Display for TileMask34 {
95 fn fmt(&self, f: &mut Formatter<'_>) -> core::fmt::Result {
96 for r in [0..9, 9..18, 18..27, 27..34] {
97 for i in r {
98 write!(f, "{}", (self.0 >> i) & 1)?;
99 }
100 write!(f, ",")?;
101 }
102 Ok(())
103 }
104}
105
106#[cfg(test)]
107mod tests {
108 use super::*;
109 use crate::tile::*;
110
111 #[test]
112 fn mask34_examples() {
113 let tiles1 = tiles_from_str("147m208p369s77z");
114 let mask1 = TileMask34::from_iter(tiles1);
115 assert_eq!(u64::from(mask1), 0b1000000100100100010010010001001001u64);
116
117 let tiles2 = tiles_from_str("1112345678999m");
118 let mask2 = TileMask34::from_iter(tiles2);
119 assert_eq!(u64::from(mask2), 0b111111111u64);
120
121 let mask_and = mask1 & mask2;
122 assert_eq!(u64::from(mask_and), 0b001001001u64);
123 }
124}