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