AoC2021/src/bin/day3.rs

106 lines
3.0 KiB
Rust

use std::error::Error;
use std::fs::File;
use std::io::{self, BufRead};
use std::vec::Vec;
const WORD_LEN: usize = 12;
fn to_weights(line: String) -> Vec<i32> {
let mut result = zero_fill(WORD_LEN);
for i in 0..WORD_LEN {
result[i] = match line.chars().nth(i) {
Some('1') => 1,
Some('0') => -1,
_ => panic!("Line to short"),
};
}
result
}
fn sum_weights(acc: Vec<i32>, weights: &Vec<i32>) -> Vec<i32> {
acc.iter().zip(weights.iter()).map(|(a, b)| a + b).collect()
}
fn zero_fill(len: usize) -> Vec<i32> {
let mut res = Vec::<i32>::new();
res.resize(len, 0);
res
}
fn weights_to_int(weights: &Vec<i32>) -> i32 {
let mut res = 0;
for i in 0..weights.len() {
if weights[i] > 0 {
res |= 1 << WORD_LEN - 1 - i;
}
}
res
}
fn main() -> Result<(), Box<dyn Error>> {
let file = File::open("inputs/day3.txt")?;
let lines = io::BufReader::new(file).lines().map(|l| l.unwrap());
let weights: Vec<Vec<i32>> = lines.map(|l| to_weights(l)).collect();
let bits: Vec<i32> = weights.iter().fold(zero_fill(WORD_LEN), sum_weights);
let mut gamma = 0;
let mut epsilon = 0;
for i in 0..bits.len() {
if bits[i] > 0 {
gamma |= 1 << WORD_LEN - 1 - i;
} else {
epsilon |= 1 << WORD_LEN - 1 - i;
}
}
println!("Gamma: {}", gamma);
println!("epsilon: {}", epsilon);
println!("Answer1: {}", gamma * epsilon);
let mut selection_pos = 0;
let mut oxy_weights = weights.clone();
let mut oxy_bits = bits.clone();
while oxy_weights.len() > 1 {
oxy_weights = oxy_weights
.into_iter()
.filter(|weights| {
(weights[selection_pos] == 1 && oxy_bits[selection_pos] > 0)
|| (weights[selection_pos] == -1 && oxy_bits[selection_pos] < 0)
|| (weights[selection_pos] == 1 && oxy_bits[selection_pos] == 0)
})
.collect();
selection_pos += 1;
oxy_bits = oxy_weights.iter().fold(zero_fill(WORD_LEN), sum_weights);
}
println!("oxy_weights: {:?}", oxy_weights);
selection_pos = 0;
let mut co2_weights = weights.clone();
let mut co2_bits = bits.clone();
while co2_weights.len() > 1 {
co2_weights = co2_weights
.into_iter()
.filter(|weights| {
(weights[selection_pos] == -1 && co2_bits[selection_pos] > 0)
|| (weights[selection_pos] == 1 && co2_bits[selection_pos] < 0)
|| (weights[selection_pos] == -1 && co2_bits[selection_pos] == 0)
})
.collect();
selection_pos += 1;
co2_bits = co2_weights.iter().fold(zero_fill(WORD_LEN), sum_weights);
}
println!("co2_weights: {:?}", co2_weights);
let oxy = weights_to_int(&oxy_weights[0]);
let co2 = weights_to_int(&co2_weights[0]);
println!("Answer2: {}", oxy * co2);
Ok(())
}