diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/day_3.rs | 106 | ||||
| -rw-r--r-- | src/main.rs | 2 |
2 files changed, 108 insertions, 0 deletions
diff --git a/src/day_3.rs b/src/day_3.rs new file mode 100644 index 0000000..89951ea --- /dev/null +++ b/src/day_3.rs @@ -0,0 +1,106 @@ +use std::ops::AddAssign; + +#[derive(Clone)] +struct Oneness(isize); + +fn part1(input: &[String]) +{ + let scale = calculate_scale(input); + + let mut gamma = 0; + let mut epsilon = 0; + for (i, oneness) in scale.iter().rev().enumerate() { + gamma += (oneness.is_one() || oneness.is_balanced()) as usize * 2_usize.pow(i as u32); + epsilon += (oneness.is_zero() || oneness.is_balanced()) as usize * 2_usize.pow(i as u32); + } + + println!("Solution to part 1: {}", gamma * epsilon); +} + +fn part2(input: Vec<String>) +{ + let mut oxygen = input.clone(); + let mut pos: usize = 0; + while oxygen.len() != 1 { + let scale = calculate_scale(&oxygen); + let looking_for_one = scale[pos].is_one() || scale[pos].is_balanced(); + oxygen = oxygen + .into_iter() + .filter(|s| { + let char_is_one = s.as_bytes()[pos] == '1' as u8; + looking_for_one == char_is_one + }) + .collect(); + + pos += 1; + } + + let mut co2 = input; + pos = 0; + while co2.len() != 1 { + let scale = calculate_scale(&co2); + let looking_for_one = scale[pos].is_zero(); + co2 = co2 + .into_iter() + .filter(|s| { + let char_is_one = s.as_bytes()[pos] == '1' as u8; + looking_for_one == char_is_one + }) + .collect(); + + pos += 1; + } + + let oxygen = usize::from_str_radix(&oxygen[0], 2).unwrap(); + let co2 = usize::from_str_radix(&co2[0], 2).unwrap(); + + println!("Solution to part 2: {}", oxygen * co2); +} + +fn calculate_scale(input: &[String]) -> Vec<Oneness> +{ + let mut one_scale = vec![Oneness::balanced(); input[0].len()]; + for s in input.iter() { + for (i, c) in s.char_indices() { + one_scale[i] += match c { + '1' => true, + '0' => false, + o => panic!("Invalid input: {}", o), + }; + } + } + + one_scale +} + +pub fn run(input: Vec<String>) +{ + // Determine the number of bits by taking a look at the first string. + let num_bits = input[0].len(); + let mut one_scale = vec![Oneness::balanced(); num_bits]; + + part1(&input); + part2(input); +} + +impl Oneness +{ + pub const fn balanced() -> Self { Self(0) } + + pub fn is_one(&self) -> bool { self.0 > 0 } + + pub fn is_zero(&self) -> bool { self.0 < 0 } + + pub fn is_balanced(&self) -> bool { self.0 == 0 } +} + +impl AddAssign<bool> for Oneness +{ + fn add_assign(&mut self, rhs: bool) + { + match rhs { + true => self.0 += 1, + false => self.0 -= 1, + } + } +} diff --git a/src/main.rs b/src/main.rs index 0c3f0a7..094d48b 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,5 +1,6 @@ mod day_1; mod day_2; +mod day_3; use std::fs::File; use std::io::{BufRead, BufReader}; @@ -28,6 +29,7 @@ fn run(day: u8, input: Vec<String>) match day { 1 => day_1::run(input), 2 => day_2::run(input), + 3 => day_3::run(input), o => panic!("Day {} is not implemented (yet)", o), } } |
