2021: day 4 solution
[?]
Dec 7, 2021, 8:55 PM
ZW7LNZTW4AZWJBHXZ5IU25PXTVFBAE5NPP7OD3JJNS54WCWYQ34QCDependencies
- [2]
HUHAFQLN2021 day 1
Change contents
- file addition: day3.rs[2.16]
#[derive(Clone, Copy, Debug)]struct BitCount {ones: u64,zeros: u64,}impl BitCount {fn new() -> Self {Self { ones: 0, zeros: 0 }}fn count_char(&mut self, c: char) {match c {'1' => self.count_one(),'0' => self.count_zero(),_ => (),}}fn count_bit(&mut self, b: bool) {if b {self.count_one()} else {self.count_zero()}}fn count_one(&mut self) {self.ones += 1;}fn count_zero(&mut self) {self.zeros += 1;}fn gamma(&self) -> bool {self.ones >= self.zeros}fn epsilon(&self) -> bool {self.zeros > self.ones}}impl Default for BitCount {fn default() -> Self {Self::new()}}struct StretchZip<'a, Item, Rhs> {lhs: &'a mut Vec<Item>,ix: usize,rhs: Rhs,}impl<'a, Item: Default, Rhs: Iterator> StretchZip<'a,Item,Rhs> {fn new(lhs: &'a mut Vec<Item>, rhs: Rhs) -> Self {Self { lhs, ix: 0, rhs }}}impl<'a, Item: Default, Rhs: Iterator> Iterator for StretchZip<'a,Item,Rhs> {type Item = (&'a mut Item, <Rhs as Iterator>::Item);fn next(&mut self) -> Option<(&'a mut Item, <Rhs as Iterator>::Item)> {let r = self.rhs.next()?;if self.ix >= self.lhs.len() {self.lhs.push(<Item as Default>::default());}let l = unsafe {std::mem::transmute::<&mut Item, &'a mut Item>(self.lhs.get_mut(self.ix)?)};self.ix += 1;Some((l,r))}}trait CounterList<C> {fn count<I: Iterator<Item=C>>(&mut self, item: I);}impl CounterList<char> for Vec<BitCount> {fn count<I: Iterator<Item=char>>(&mut self, item: I) {for (counter, bit) in StretchZip::new(self, item) {counter.count_char(bit);}}}fn life_support(field: bool, readings: &Vec<Vec<bool>>) -> u64 {let mut remaining_1 = Vec::new();let mut remaining_2 = Vec::new();for ix in 0 .. readings[0].len() {let (source, sink) = if ix == 0 {(readings, &mut remaining_1)} else if ix % 2 == 0 {(&remaining_2, &mut remaining_1)} else {(&remaining_1, &mut remaining_2)};let mut counter = BitCount::new();for reading in source.iter() {counter.count_bit(reading[ix]);}let target = if field {counter.gamma()} else {counter.epsilon()};sink.clear();sink.extend(source.iter().filter(|reading| reading[ix] == target).cloned());match sink.len() {0 => { sink.extend(source.iter().cloned()); }1 => { return from_bits(sink[0].iter().copied()); }_ => {}}}from_bits(if remaining_1.len() <= remaining_2.len() {&remaining_1[0]} else {&remaining_2[0]}.iter().copied())}fn from_bits<I: Iterator<Item=bool>>(source: I) -> u64 {let mut result = 0;for b in source {result = result * 2 + (if b { 1 } else { 0 });}result}fn main() {use std::io::BufRead;let filename = std::env::args().nth(1).expect("Expected filename");let file = std::io::BufReader::new(std::fs::File::open(<String as AsRef<std::path::Path>>::as_ref(&filename)).unwrap());let mut counters = Vec::new();let mut record = Vec::new();for line in file.lines().filter_map(Result::ok) {counters.count(line.chars());record.push(line.chars().filter_map(|c| match c {'0' => Some(false),'1' => Some(true),_ => None}).collect::<Vec<_>>())};let gamma = from_bits(counters.iter().map(BitCount::gamma));println!("Gamma: {}", gamma);let epsilon = from_bits(counters.iter().map(BitCount::epsilon));println!("Epsilon: {}", epsilon);println!("Product: {}", gamma * epsilon);let oxygen = life_support(true, &record);println!("Oxygen: {}", oxygen);let scrubber = life_support(false, &record);println!("CO2 Scrubber: {}", scrubber);println!("Product: {}", oxygen * scrubber);}