mirror of
https://github.com/bertptrs/adventofcode.git
synced 2025-12-25 21:00:31 +01:00
102 lines
2.1 KiB
Rust
102 lines
2.1 KiB
Rust
use std::io::Read;
|
|
|
|
use crate::common::LineIter;
|
|
|
|
fn parse_bit(bit: char) -> usize {
|
|
if bit == '1' {
|
|
1
|
|
} else {
|
|
0
|
|
}
|
|
}
|
|
|
|
pub fn part1(input: &mut dyn Read) -> String {
|
|
let mut reader = LineIter::new(input);
|
|
|
|
let mut totals: Vec<usize> = reader.next().unwrap().chars().map(parse_bit).collect();
|
|
|
|
let mut count = 1;
|
|
|
|
while let Some(line) = reader.next() {
|
|
line.chars()
|
|
.map(parse_bit)
|
|
.zip(totals.iter_mut())
|
|
.for_each(|(b, t)| *t += b);
|
|
|
|
count += 1;
|
|
}
|
|
|
|
let bitmask = (1 << totals.len()) - 1;
|
|
|
|
let gamma = totals.into_iter().fold(0, |mut current, total| {
|
|
current <<= 1;
|
|
if total > count / 2 {
|
|
current |= 1;
|
|
};
|
|
|
|
current
|
|
});
|
|
|
|
let epsilon = (!gamma) & bitmask;
|
|
|
|
(gamma * epsilon).to_string()
|
|
}
|
|
|
|
fn find_remaining(mut strings: Vec<u32>, most: bool, len: usize) -> u32 {
|
|
for pos in 1..=len {
|
|
if strings.len() == 1 {
|
|
break;
|
|
}
|
|
|
|
let bit = 1 << (len - pos);
|
|
|
|
let occurrences = strings.iter().filter(|&&b| (b & bit) == bit).count();
|
|
|
|
let keep = if (occurrences * 2 < strings.len()) ^ most {
|
|
bit
|
|
} else {
|
|
0
|
|
};
|
|
|
|
strings.retain(|&b| (b & bit) == keep);
|
|
}
|
|
|
|
strings[0]
|
|
}
|
|
|
|
pub fn part2(input: &mut dyn Read) -> String {
|
|
let mut strings = Vec::new();
|
|
let mut reader = LineIter::new(input);
|
|
let mut read_line = reader.next();
|
|
let len = read_line.unwrap().len();
|
|
|
|
while let Some(line) = read_line {
|
|
strings.push(u32::from_str_radix(line, 2).unwrap());
|
|
read_line = reader.next();
|
|
}
|
|
|
|
let oxygen = find_remaining(strings.clone(), true, len);
|
|
let co2 = find_remaining(strings, false, len);
|
|
|
|
(oxygen * co2).to_string()
|
|
}
|
|
|
|
#[cfg(test)]
|
|
mod tests {
|
|
use crate::test_implementation;
|
|
|
|
use super::*;
|
|
|
|
const SAMPLE: &[u8] = include_bytes!("samples/03.txt");
|
|
|
|
#[test]
|
|
fn sample_part1() {
|
|
test_implementation(part1, SAMPLE, 198);
|
|
}
|
|
|
|
#[test]
|
|
fn sample_part2() {
|
|
test_implementation(part2, SAMPLE, 230)
|
|
}
|
|
}
|