Added Solution for 2021 day 03
This commit is contained in:
parent
028b30f131
commit
690296f00a
5 changed files with 1184 additions and 0 deletions
83
2021/day03_binary_diagnostic/src/lib.rs
Normal file
83
2021/day03_binary_diagnostic/src/lib.rs
Normal file
|
@ -0,0 +1,83 @@
|
|||
use core::fmt::Display;
|
||||
|
||||
#[derive(Debug, PartialEq, Eq)]
|
||||
pub enum ParseError {
|
||||
ParseIntError(char),
|
||||
}
|
||||
|
||||
impl Display for ParseError {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
match self {
|
||||
Self::ParseIntError(e) => write!(f, "Unable to parse into integer {e}"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn run(input: &str) -> Result<(usize, usize), ParseError> {
|
||||
let bits: Vec<_> = input.lines().map(|line| line.chars().map(|i| i.to_digit(10).ok_or(ParseError::ParseIntError(i))).collect::<Result<Vec<_>, _>>()).collect::<Result<Vec<_>, _>>()?;
|
||||
let mut ones = vec![0; bits[0].len()];
|
||||
bits.iter().for_each(|number| number.iter().enumerate().for_each(|(idx, bit)| ones[idx] += bit));
|
||||
let half = bits.len() as u32/2;
|
||||
let mut gamma = 0;
|
||||
let mut epsilon = 0;
|
||||
ones.iter().for_each(|bit_count| {
|
||||
gamma *= 2;
|
||||
epsilon *= 2;
|
||||
if bit_count > &half {
|
||||
gamma += 1;
|
||||
} else {
|
||||
epsilon += 1;
|
||||
}
|
||||
});
|
||||
let first = gamma as usize * epsilon as usize;
|
||||
|
||||
let bit_count = bits.len();
|
||||
let mut oxygen_rating = bits.clone();
|
||||
for idx in 0..bit_count {
|
||||
if oxygen_rating.len() > 1 {
|
||||
if oxygen_rating.iter().map(|bits| bits[idx]).sum::<u32>() >= (oxygen_rating.len() as u32 + 1) / 2 {
|
||||
oxygen_rating.retain(|bits| bits[idx] == 1);
|
||||
} else {
|
||||
oxygen_rating.retain(|bits| bits[idx] == 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
let oxygen_rating = oxygen_rating[0].iter().fold(0, |acc, bit| 2 * acc + *bit);
|
||||
|
||||
let mut co2_rating = bits.clone();
|
||||
for idx in 0..bit_count {
|
||||
if co2_rating.len() > 1 {
|
||||
if co2_rating.iter().map(|bits| bits[idx]).sum::<u32>() >= (co2_rating.len() as u32 + 1) / 2 {
|
||||
co2_rating.retain(|bits| bits[idx] == 0);
|
||||
} else {
|
||||
co2_rating.retain(|bits| bits[idx] == 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
let co2_rating = co2_rating[0].iter().fold(0, |acc, bit| 2 * acc + *bit);
|
||||
|
||||
let second = oxygen_rating as usize * co2_rating as usize;
|
||||
Ok((first, second))
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
use std::fs::read_to_string;
|
||||
|
||||
fn read_file(name: &str) -> String {
|
||||
read_to_string(name).expect(&format!("Unable to read file: {name}")[..]).trim().to_string()
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_sample() {
|
||||
let sample_input = read_file("tests/sample_input");
|
||||
assert_eq!(run(&sample_input), Ok((198, 230)));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_challenge() {
|
||||
let challenge_input = read_file("tests/challenge_input");
|
||||
assert_eq!(run(&challenge_input), Ok((2498354, 3277956)));
|
||||
}
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue