Add (ugly) working day 3 in rust
This commit is contained in:
parent
b487214421
commit
d664a9efa8
7
d03/Cargo.lock
generated
Normal file
7
d03/Cargo.lock
generated
Normal file
@ -0,0 +1,7 @@
|
||||
# This file is automatically @generated by Cargo.
|
||||
# It is not intended for manual editing.
|
||||
version = 3
|
||||
|
||||
[[package]]
|
||||
name = "d03"
|
||||
version = "0.1.0"
|
8
d03/Cargo.toml
Normal file
8
d03/Cargo.toml
Normal file
@ -0,0 +1,8 @@
|
||||
[package]
|
||||
name = "d03"
|
||||
version = "0.1.0"
|
||||
edition = "2021"
|
||||
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
[dependencies]
|
1000
d03/input.txt
Normal file
1000
d03/input.txt
Normal file
File diff suppressed because it is too large
Load Diff
12
d03/input_short.txt
Normal file
12
d03/input_short.txt
Normal file
@ -0,0 +1,12 @@
|
||||
00100
|
||||
11110
|
||||
10110
|
||||
10111
|
||||
10101
|
||||
01111
|
||||
00111
|
||||
11100
|
||||
10000
|
||||
11001
|
||||
00010
|
||||
01010
|
207
d03/src/main.rs
Normal file
207
d03/src/main.rs
Normal file
@ -0,0 +1,207 @@
|
||||
use std::fs::File;
|
||||
use std::io::{self, BufRead};
|
||||
use std::path::Path;
|
||||
|
||||
fn read_lines<P>(filename: P) -> io::Result<io::Lines<io::BufReader<File>>>
|
||||
where
|
||||
P: AsRef<Path>,
|
||||
{
|
||||
let file = File::open(filename)?;
|
||||
Ok(io::BufReader::new(file).lines())
|
||||
}
|
||||
|
||||
fn str_to_bit_vec(binary_string: &str) -> Vec<u32> {
|
||||
binary_string
|
||||
.chars()
|
||||
.map(|c| {
|
||||
c.to_digit(2)
|
||||
.expect(format!("Unknown binary string: {}", binary_string).as_str())
|
||||
})
|
||||
.collect()
|
||||
}
|
||||
|
||||
struct MeanBits {
|
||||
bits: Vec<u32>,
|
||||
count: u32,
|
||||
}
|
||||
|
||||
fn calc_gamma_epsilon(bit_mask: u32, values: Vec<Vec<u32>>) -> (u32, u32) {
|
||||
let result = values
|
||||
.iter()
|
||||
.map(|bits| MeanBits {
|
||||
bits: bits.clone(),
|
||||
count: 1,
|
||||
})
|
||||
// Reduce by summing each bit and keeping count
|
||||
.reduce(|acc, these_bits| MeanBits {
|
||||
bits: acc
|
||||
.bits
|
||||
.iter()
|
||||
.zip(these_bits.bits.iter())
|
||||
.map(|val| val.0 + val.1)
|
||||
.collect(),
|
||||
count: acc.count + these_bits.count,
|
||||
})
|
||||
.expect(format!("No results!").as_str());
|
||||
|
||||
// Calc the gamma value from the MeanBits result
|
||||
let gamma = result
|
||||
.bits
|
||||
.iter()
|
||||
.map(|b| (b * 10) / result.count)
|
||||
.map(|b| {
|
||||
println!("digit {}, count {}", b, result.count);
|
||||
b
|
||||
})
|
||||
.map(|b| match b {
|
||||
b if b < 5 => "0".to_string(),
|
||||
b if b >= 5 => "1".to_string(),
|
||||
_ => panic!("not possible?"),
|
||||
})
|
||||
.reduce(|result, b| (&[result, b]).join(""))
|
||||
.map(|gamma| {
|
||||
println!("gamma {}", gamma);
|
||||
gamma
|
||||
})
|
||||
.map(|gamma| u32::from_str_radix(gamma.as_str(), 2))
|
||||
.expect("Could not parse gama value")
|
||||
.unwrap();
|
||||
|
||||
// NOT the gamma and apply mask
|
||||
let epsilon = !gamma & bit_mask;
|
||||
|
||||
(gamma, epsilon)
|
||||
}
|
||||
|
||||
fn part1() -> (u32, u32) {
|
||||
// Mask should be the length of a line
|
||||
let bit_mask = u32::from_str_radix("111111111111", 2).unwrap();
|
||||
let result = read_lines("input.txt")
|
||||
.expect("Expected a file to read")
|
||||
.map(|line| line.expect("Could not read line"))
|
||||
.map(|line| str_to_bit_vec(&line))
|
||||
// Prep for mean calc
|
||||
.map(|bits| MeanBits {
|
||||
bits: bits,
|
||||
count: 1,
|
||||
})
|
||||
// Reduce by summing each bit and keeping count
|
||||
.reduce(|acc, these_bits| MeanBits {
|
||||
bits: acc
|
||||
.bits
|
||||
.iter()
|
||||
.zip(these_bits.bits.iter())
|
||||
.map(|val| val.0 + val.1)
|
||||
.collect(),
|
||||
count: acc.count + these_bits.count,
|
||||
})
|
||||
.expect(format!("No results!").as_str());
|
||||
|
||||
// Calc the gamma value from the MeanBits result
|
||||
let gamma = result
|
||||
.bits
|
||||
.iter()
|
||||
.map(|b| (b * 10) / result.count)
|
||||
.map(|b| {
|
||||
println!("digit {}, count {}", b, result.count);
|
||||
b
|
||||
})
|
||||
.map(|b| match b {
|
||||
b if b < 5 => "0".to_string(),
|
||||
b if b >= 5 => "1".to_string(),
|
||||
_ => panic!("not possible?"),
|
||||
})
|
||||
.reduce(|result, b| (&[result, b]).join(""))
|
||||
.map(|gamma| {
|
||||
println!("gamma {}", gamma);
|
||||
gamma
|
||||
})
|
||||
.map(|gamma| u32::from_str_radix(gamma.as_str(), 2))
|
||||
.expect("Could not parse gama value")
|
||||
.unwrap();
|
||||
|
||||
// NOT the gamma and apply mask
|
||||
let epsilon = !gamma & bit_mask;
|
||||
|
||||
println!(
|
||||
"Result for part 1: gamma: {} epsilon: {} result: {}",
|
||||
gamma,
|
||||
epsilon,
|
||||
gamma * epsilon
|
||||
);
|
||||
|
||||
(gamma, epsilon)
|
||||
}
|
||||
|
||||
fn part2() {
|
||||
// Oh wow... Getting uggly as my rust is not so great.
|
||||
// This can almost certainly be done with less iterations, but I'm getting lazy now
|
||||
let mask_length: u32 = 12;
|
||||
let bit_mask =
|
||||
u32::from_str_radix("1".repeat(mask_length.try_into().unwrap()).as_str(), 2).unwrap();
|
||||
let bit_vects: Vec<Vec<u32>> = read_lines("input.txt")
|
||||
.expect("Expected a file to read")
|
||||
.map(|line| line.expect("Could not read line"))
|
||||
.map(|line| str_to_bit_vec(&line))
|
||||
.collect();
|
||||
|
||||
let mut index: u32 = 0;
|
||||
let mut oxy_vects = bit_vects.clone();
|
||||
while oxy_vects.len() > 1 {
|
||||
println!("Length of vectors is {}", oxy_vects.len());
|
||||
let (gamma, _epsilon) = calc_gamma_epsilon(bit_mask, oxy_vects.clone());
|
||||
let mask_bit: u32 = mask_length - index - 1;
|
||||
let gamma_bit = gamma >> mask_bit & 1;
|
||||
println!(
|
||||
"Gamma is {:#b} and bit at index {} is {}",
|
||||
gamma, mask_bit, gamma_bit
|
||||
);
|
||||
// let epsilon_bit = epsilon >> index & mask_bit;
|
||||
let iu: usize = index.try_into().unwrap();
|
||||
oxy_vects.retain(|bits| bits[iu] == gamma_bit);
|
||||
index += 1;
|
||||
}
|
||||
let oxygen_rating = oxy_vects[0]
|
||||
.iter()
|
||||
.map(|b| b.to_string())
|
||||
.reduce(|result, b| (&[result, b]).join(""))
|
||||
.map(|oxy| u32::from_str_radix(oxy.as_str(), 2))
|
||||
.expect("No oxygen rating")
|
||||
.unwrap();
|
||||
|
||||
index = 0;
|
||||
let mut co2_vects = bit_vects.clone();
|
||||
while co2_vects.len() > 1 {
|
||||
println!("Length of vectors is {}", co2_vects.len());
|
||||
let (_gamma, epsilon) = calc_gamma_epsilon(bit_mask, co2_vects.clone());
|
||||
let mask_bit: u32 = mask_length - index - 1;
|
||||
let epsilon_bit = epsilon >> mask_bit & 1;
|
||||
println!(
|
||||
"Gamma is {:#b} and bit at index {} is {}",
|
||||
epsilon, mask_bit, epsilon_bit
|
||||
);
|
||||
// let epsilon_bit = epsilon >> index & mask_bit;
|
||||
let iu: usize = index.try_into().unwrap();
|
||||
co2_vects.retain(|bits| bits[iu] == epsilon_bit);
|
||||
index += 1;
|
||||
}
|
||||
let co2_rating = co2_vects[0]
|
||||
.iter()
|
||||
.map(|b| b.to_string())
|
||||
.reduce(|result, b| (&[result, b]).join(""))
|
||||
.map(|oxy| u32::from_str_radix(oxy.as_str(), 2))
|
||||
.expect("No oxygen rating")
|
||||
.unwrap();
|
||||
|
||||
println!(
|
||||
"Part 2! O2 = {}, CO2 = {}, Result is {}",
|
||||
oxygen_rating,
|
||||
co2_rating,
|
||||
oxygen_rating * co2_rating
|
||||
)
|
||||
}
|
||||
|
||||
fn main() {
|
||||
part1();
|
||||
part2()
|
||||
}
|
Loading…
Reference in New Issue
Block a user