feat: solve day 3, part 1 & 2
This commit is contained in:
parent
71cd3daec3
commit
2a2139c681
1000
input3.txt
Normal file
1000
input3.txt
Normal file
File diff suppressed because it is too large
Load Diff
103
src/day3.rs
Normal file
103
src/day3.rs
Normal file
@ -0,0 +1,103 @@
|
||||
use std::{num::ParseIntError, slice::Iter};
|
||||
|
||||
pub fn parse_input(input: &str) -> Result<Vec<i32>, ParseIntError> {
|
||||
input.split_whitespace()
|
||||
.map(|s| i32::from_str_radix(s, 2))
|
||||
.collect()
|
||||
}
|
||||
|
||||
fn calculate_max_bits(nums: &[i32]) -> u32 {
|
||||
let mut max_bits = 0;
|
||||
for num in nums {
|
||||
max_bits = max_bits.max((*num as f32).log2().ceil() as u32);
|
||||
}
|
||||
return max_bits;
|
||||
}
|
||||
|
||||
fn count_bits(nums: Iter<i32>, power: &i32) -> u32 {
|
||||
let mut bits = 0;
|
||||
for num in nums {
|
||||
if num & power > 0 {
|
||||
bits += 1;
|
||||
}
|
||||
}
|
||||
return bits;
|
||||
}
|
||||
|
||||
pub fn part1(diagnostics: &[i32]) -> i32 {
|
||||
let n = diagnostics.len() as u32;
|
||||
let mut gamma = 0;
|
||||
let mut epsilon = 0;
|
||||
|
||||
let max_bits = calculate_max_bits(&diagnostics);
|
||||
let mut power = 1;
|
||||
for _ in 1..=max_bits {
|
||||
let bits = count_bits(diagnostics.iter(), &power);
|
||||
if 2*bits >= n {
|
||||
gamma += power;
|
||||
} else {
|
||||
epsilon += power;
|
||||
}
|
||||
power *= 2;
|
||||
}
|
||||
|
||||
return gamma * epsilon;
|
||||
}
|
||||
|
||||
pub fn part2(diagnostics: &[i32]) -> i32 {
|
||||
let mut carbon_diagnostics = Vec::new();
|
||||
let mut oxygen_diagnostics = Vec::new();
|
||||
|
||||
carbon_diagnostics.extend_from_slice(diagnostics);
|
||||
oxygen_diagnostics.extend_from_slice(diagnostics);
|
||||
|
||||
let max_bits = calculate_max_bits(&diagnostics);
|
||||
let mut power = 2i32.pow(max_bits-1);
|
||||
for _ in 1..=max_bits {
|
||||
let oxygen_len = oxygen_diagnostics.len() as u32;
|
||||
if oxygen_len > 1 {
|
||||
let bit_count = count_bits(oxygen_diagnostics.iter(), &power);
|
||||
if 2*bit_count >= oxygen_len {
|
||||
oxygen_diagnostics = oxygen_diagnostics.into_iter().filter(|n| n & power > 0).collect();
|
||||
} else {
|
||||
oxygen_diagnostics = oxygen_diagnostics.into_iter().filter(|n| n & power == 0).collect();
|
||||
}
|
||||
}
|
||||
|
||||
let carbon_len = carbon_diagnostics.len() as u32;
|
||||
if carbon_len > 1 {
|
||||
let bit_count = count_bits(carbon_diagnostics.iter(), &power);
|
||||
if 2*bit_count < carbon_len {
|
||||
carbon_diagnostics = carbon_diagnostics.into_iter().filter(|n| n & power > 0).collect();
|
||||
} else {
|
||||
carbon_diagnostics = carbon_diagnostics.into_iter().filter(|n| n & power == 0).collect();
|
||||
}
|
||||
}
|
||||
|
||||
if oxygen_len == 1 && carbon_len == 1 { break; }
|
||||
|
||||
power /= 2;
|
||||
}
|
||||
|
||||
return carbon_diagnostics[0] * oxygen_diagnostics[0];
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn part1_example() {
|
||||
let diagnostics = [0b00100, 0b11110, 0b10110, 0b10111, 0b10101, 0b01111, 0b00111, 0b11100, 0b10000, 0b11001, 0b00010, 0b01010];
|
||||
let result = part1(&diagnostics);
|
||||
assert_eq!(result, 198);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn part2_example() {
|
||||
let diagnostics = [0b00100, 0b11110, 0b10110, 0b10111, 0b10101, 0b01111, 0b00111, 0b11100, 0b10000, 0b11001, 0b00010, 0b01010];
|
||||
let result = part2(&diagnostics);
|
||||
assert_eq!(result, 230);
|
||||
}
|
||||
}
|
||||
|
11
src/main.rs
11
src/main.rs
@ -1,11 +1,10 @@
|
||||
mod day1;
|
||||
mod day2;
|
||||
mod day3;
|
||||
|
||||
use std::fs::File;
|
||||
use std::io::prelude::*;
|
||||
|
||||
fn main() {
|
||||
let input_filename = "input1.txt";
|
||||
let input_filename = "input3.txt";
|
||||
|
||||
let mut input_file = File::open(input_filename)
|
||||
.expect("Input file not found");
|
||||
@ -14,10 +13,10 @@ fn main() {
|
||||
input_file.read_to_string(&mut contents)
|
||||
.expect("Could not read input file");
|
||||
|
||||
let input = day2::parse_input(input_filename)
|
||||
let input = day3::parse_input(&contents)
|
||||
.expect("Failed to parse input");
|
||||
|
||||
println!("Part 1 result: {}", day2::part1(&input));
|
||||
println!("Part 2 result: {}", day2::part2(&input));
|
||||
println!("Part 1 result: {}", day3::part1(&input));
|
||||
println!("Part 2 result: {}", day3::part2(&input));
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user