diff options
Diffstat (limited to '08/src/bitfield.rs')
-rw-r--r-- | 08/src/bitfield.rs | 109 |
1 files changed, 109 insertions, 0 deletions
diff --git a/08/src/bitfield.rs b/08/src/bitfield.rs new file mode 100644 index 0000000..8c513cb --- /dev/null +++ b/08/src/bitfield.rs @@ -0,0 +1,109 @@ +#[derive(Clone, Copy, Eq, PartialEq)] +pub struct Bitfield { + pub data: usize +} + +impl Bitfield { + pub fn new() -> Self { Self { data: 0 } } + pub fn set(self: &mut Self, i: u8) { + self.data |= 1_usize << i; + } + pub fn unset(self: &mut Self, i: u8) { + self.data ^= 1_usize << i; + } + pub fn get(self: & Self, i: u8) -> bool { + (self.data & 1_usize << i) != 0 + } + pub fn pop_count(self: & Self) -> usize { + self.data.count_ones() as usize + } + pub fn swap(self: &mut Self, i: u8, j: u8) { + let mask_a = self.data & (1_usize << i); + let mask_b = self.data & (1_usize << j); + let mask_c = (mask_a >> i) ^ (mask_b >> j); + self.data ^= (mask_c << i) | (mask_c << j); + } + pub fn permute<'a, I: std::iter::Iterator<Item = &'a usize>>(self: & Self, it: I) -> Self { + let mut ret: usize = 0; + for (i, &j) in it.enumerate() { + let x = self.data & (1_usize << i); + ret ^= (x >> i) << j; + } + Self { data: ret } + } +} + +impl Default for Bitfield { + fn default() -> Self { Self { data: 0 } } +} + +impl std::ops::BitOr for Bitfield { + type Output = Self; + fn bitor(self, rhs: Self) -> Self::Output { Self { data: self.data | rhs.data } } +} + +impl std::ops::BitOrAssign for Bitfield { + fn bitor_assign(self: &mut Self, rhs: Self) { self.data |= rhs.data } +} + +impl std::ops::BitXorAssign for Bitfield { + fn bitxor_assign(self: &mut Self, rhs: Self) { self.data ^= rhs.data } +} + +impl TryFrom<char> for Bitfield { + type Error = &'static str; + fn try_from(c: char) -> Result<Self, Self::Error> { + match c { + 'a' => Ok(Bitfield { data: 1 << 0 }), + 'b' => Ok(Bitfield { data: 1 << 1 }), + 'c' => Ok(Bitfield { data: 1 << 2 }), + 'd' => Ok(Bitfield { data: 1 << 3 }), + 'e' => Ok(Bitfield { data: 1 << 4 }), + 'f' => Ok(Bitfield { data: 1 << 5 }), + 'g' => Ok(Bitfield { data: 1 << 6 }), + _ => Err("Invalid character for Bitfield.") + } + } +} + +impl From<Bitfield> for String { + fn from(x: Bitfield) -> Self { + let mut ret: String = String::new(); + if x.get(0) { ret.push('a'); } + if x.get(1) { ret.push('b'); } + if x.get(2) { ret.push('c'); } + if x.get(3) { ret.push('d'); } + if x.get(4) { ret.push('e'); } + if x.get(5) { ret.push('f'); } + if x.get(6) { ret.push('g'); } + ret + } +} + +impl TryFrom<& str> for Bitfield { + type Error = &'static str; + fn try_from(s: & str) -> Result<Self, Self::Error> { + let mut ret: Bitfield = Bitfield::new(); + for c in s.chars() { + ret |= Bitfield::try_from(c)?; + } + Ok(ret) + } +} + +pub fn parse_input(s: & str) -> ([Bitfield; 10], [Bitfield; 4]) { + let mut halves = s.split(" | "); + let mut all_digits_it = halves.next().unwrap().split(' '); + let mut output_digits_it = halves.next().unwrap().split(' '); + + let mut all_digits: [Bitfield; 10] = [Bitfield::new(); 10]; + for (i, w) in (0..10).zip(all_digits_it) { + all_digits[i] = Bitfield::try_from(w).unwrap(); + } + let mut output_digits: [Bitfield; 4] = [Bitfield::new(); 4]; + for (i, w) in (0..4).zip(output_digits_it) { + output_digits[i] = Bitfield::try_from(w).unwrap(); + } + + (all_digits, output_digits) +} |