use std::io::{self, BufRead}; use std::path::Path; use std::fs::File; fn main(){ // Submarine is breaking, do diagnostics by checking power consumption // Calculate gamma rate * epsilon rate // Diagnostics are encoded by series of binary numbers // Gamma rate is most common bit for each bit in the series // Epsilon rate is the opposite, i.e. least common bit // So when gamma rate would be 10011, epsilon rate automatically is 01100 println!("Advent of Code #3!\n"); let path = Path::new("./3.txt"); let display = path.display(); let file = match File::open(&path) { Err(why) => panic!("Couldn't open {}: {}", display, why), Ok(file) => file, }; let lines = io::BufReader::new(file).lines(); let mut diagnostics = Vec::>::new(); for line in lines{ let mut d_line = Vec::::new(); if let Ok(l) = line { for c in l.chars() { match c { '0' => d_line.push(false), '1' => d_line.push(true), _ => (), } } } diagnostics.push(d_line); } let mut line_numbers = 0; let b_len = diagnostics[0].len(); let mut ones = vec![0; b_len]; for line in &diagnostics { line_numbers += 1; for i in 0 .. b_len { match line[i] { true => ones[i] += 1, false => (), } } } let mut gamma_rate = Vec::new(); for n in ones { if n > line_numbers / 2 { gamma_rate.push(true); } else { gamma_rate.push(false); } } let mut gamma_rate_decimal = 0; let mut pow = 1; gamma_rate.reverse(); for b in &gamma_rate { match b { true => gamma_rate_decimal += pow, false => (), } pow *= 2; } println!("Gamma rate in decimal is {}, epsilon rate in decimal is {}, yielding product of {}", gamma_rate_decimal, pow - gamma_rate_decimal - 1, gamma_rate_decimal * (pow - gamma_rate_decimal - 1)); // Now on to the second part of day 3 // Verify life support rating, by multiplying oxygen generator rating by co2 scrubber rating // Oxygen generator rating is determined by finding the most common bit for the first bit // Then, throw out all diagnostics line that do not have the same most common bit for the first position // Repeat until only one line remains, this is the oxygen generator rating // For the co2 scrubber rating, do the same but for the least common bit per position gamma_rate.reverse(); let mut viable_oxygen = vec![true; line_numbers]; let mut viable_scrubber = vec![true; line_numbers]; let mut n_oxygen = line_numbers; let mut n_scrubber = line_numbers; for bit_n in 0 .. b_len { for line_n in 0 .. line_numbers { if viable_oxygen[line_n] && n_oxygen > 1 { if diagnostics[line_n][bit_n] != gamma_rate[bit_n] { n_oxygen -= 1; viable_oxygen[line_n] = false; } } if viable_scrubber[line_n] && n_scrubber > 1 { if diagnostics[line_n][bit_n] == gamma_rate[bit_n] { n_scrubber -= 1; viable_scrubber[line_n] = false; } } } if n_oxygen == 1 && n_scrubber == 1 { break; } } let mut oxygen_ans = 0; let mut scrubber_ans = 0; for i in 0 .. line_numbers { if viable_oxygen[i] { oxygen_ans = i; } if viable_scrubber[i] { scrubber_ans = i; } } diagnostics[oxygen_ans].reverse(); diagnostics[scrubber_ans].reverse(); let oxygen_dec = bit_to_decimal(&diagnostics[oxygen_ans]); let scrubber_dec = bit_to_decimal(&diagnostics[scrubber_ans]); println!("Oxygen generator rating is {}, co2 scrubber rating is {}, yields product of {}", oxygen_dec, scrubber_dec, oxygen_dec * scrubber_dec); } fn bit_to_decimal(bits: &Vec::) -> u64 { let mut pow = 1; let mut result = 0; for b in bits { match b { true => result += pow, false => (), } pow *= 2; } return result; }