Day 3 clean-up
This commit is contained in:
parent
40121a400a
commit
79da3ab4aa
148
src/day3.rs
148
src/day3.rs
@ -1,94 +1,115 @@
|
|||||||
use std::io::{self, BufRead};
|
use std::io::{self, BufRead};
|
||||||
|
|
||||||
fn most_common_bits(report: &Vec<String>) -> String {
|
struct Diagnostics<const N: usize> {
|
||||||
(0..12)
|
report: Vec<String>,
|
||||||
.map(|i| {
|
}
|
||||||
let counts = report
|
|
||||||
|
impl<const N: usize> Diagnostics<N> {
|
||||||
|
fn gamma_rate(&self) -> u32 {
|
||||||
|
u32::from_str_radix(&self.most_common_bits(), 2).unwrap()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn epsilon_rate(&self) -> u32 {
|
||||||
|
0xfff ^ self.gamma_rate()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn oxygen_generator_rating(&self) -> u32 {
|
||||||
|
u32::from_str_radix(&self.most_common_value(), 2).unwrap()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn co2_scrubber_rating(&self) -> u32 {
|
||||||
|
u32::from_str_radix(&self.least_common_value(), 2).unwrap()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn count_bit(&self, values: &Vec<String>, bit: usize) -> (usize, usize) {
|
||||||
|
values
|
||||||
.iter()
|
.iter()
|
||||||
.fold((0, 0), |acc, x| match x.chars().nth(i).unwrap() {
|
.fold((0, 0), |acc, x| match x.chars().nth(bit).unwrap() {
|
||||||
'0' => (acc.0 + 1, acc.1),
|
'0' => (acc.0 + 1, acc.1),
|
||||||
'1' => (acc.0, acc.1 + 1),
|
'1' => (acc.0, acc.1 + 1),
|
||||||
_ => acc,
|
_ => acc,
|
||||||
});
|
})
|
||||||
if counts.0 > counts.1 {
|
}
|
||||||
|
|
||||||
|
fn most_common_bits(&self) -> String {
|
||||||
|
(0..N)
|
||||||
|
.map(|i| {
|
||||||
|
let (zeros, ones) = self.count_bit(&self.report, i);
|
||||||
|
if zeros > ones {
|
||||||
'0'
|
'0'
|
||||||
} else {
|
} else {
|
||||||
'1'
|
'1'
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
.collect()
|
.collect()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn most_common_value(report: Vec<String>, n: usize) -> Option<String> {
|
fn filter_values(
|
||||||
(0..n)
|
&self,
|
||||||
.fold(report, |r, i| {
|
values: Vec<String>,
|
||||||
if r.len() > 1 {
|
bit: usize,
|
||||||
let counts = r
|
predicate: impl Fn(usize, usize) -> bool,
|
||||||
|
) -> Vec<String> {
|
||||||
|
if values.len() <= 1 {
|
||||||
|
return values;
|
||||||
|
}
|
||||||
|
let (zeros, ones) = self.count_bit(&values, bit);
|
||||||
|
values
|
||||||
.iter()
|
.iter()
|
||||||
.fold((0, 0), |acc, x| match x.chars().nth(i).unwrap() {
|
.filter(|x| match x.chars().nth(bit).unwrap() {
|
||||||
'0' => (acc.0 + 1, acc.1),
|
'0' if !predicate(zeros, ones) => true,
|
||||||
'1' => (acc.0, acc.1 + 1),
|
'1' if predicate(zeros, ones) => true,
|
||||||
_ => acc,
|
|
||||||
});
|
|
||||||
r.iter()
|
|
||||||
.filter(|x| match x.chars().nth(i).unwrap() {
|
|
||||||
'0' if counts.0 > counts.1 => true,
|
|
||||||
'1' if counts.0 <= counts.1 => true,
|
|
||||||
_ => false,
|
_ => false,
|
||||||
})
|
})
|
||||||
.cloned()
|
.cloned()
|
||||||
.collect()
|
.collect()
|
||||||
} else {
|
|
||||||
r
|
|
||||||
}
|
}
|
||||||
})
|
|
||||||
.first()
|
|
||||||
.cloned()
|
|
||||||
}
|
|
||||||
|
|
||||||
fn least_common_value(report: Vec<String>) -> Option<String> {
|
fn most_common_value(&self) -> String {
|
||||||
(0..12)
|
(0..N)
|
||||||
.fold(report, |r, i| {
|
.fold(self.report.clone(), |r, i| {
|
||||||
if r.len() > 1 {
|
self.filter_values(r, i, |zeros, ones| ones >= zeros)
|
||||||
let counts = r
|
|
||||||
.iter()
|
|
||||||
.fold((0, 0), |acc, x| match x.chars().nth(i).unwrap() {
|
|
||||||
'0' => (acc.0 + 1, acc.1),
|
|
||||||
'1' => (acc.0, acc.1 + 1),
|
|
||||||
_ => acc,
|
|
||||||
});
|
|
||||||
r.iter()
|
|
||||||
.filter(|x| match x.chars().nth(i).unwrap() {
|
|
||||||
'0' if counts.0 <= counts.1 => true,
|
|
||||||
'1' if counts.0 > counts.1 => true,
|
|
||||||
_ => false,
|
|
||||||
})
|
|
||||||
.cloned()
|
|
||||||
.collect()
|
|
||||||
} else {
|
|
||||||
r
|
|
||||||
}
|
|
||||||
})
|
})
|
||||||
.first()
|
.first()
|
||||||
.cloned()
|
.unwrap()
|
||||||
|
.clone()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn least_common_value(&self) -> String {
|
||||||
|
(0..N)
|
||||||
|
.fold(self.report.clone(), |r, i| {
|
||||||
|
self.filter_values(r, i, |zeros, ones| ones < zeros)
|
||||||
|
})
|
||||||
|
.first()
|
||||||
|
.unwrap()
|
||||||
|
.clone()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
const INPUT: &'static str = include_str!("../inputs/day3.txt");
|
const INPUT: &'static str = include_str!("../inputs/day3.txt");
|
||||||
let report: Vec<String> = io::Cursor::new(INPUT).lines().map(|l| l.unwrap()).collect();
|
let report: Vec<String> = io::Cursor::new(INPUT).lines().map(|l| l.unwrap()).collect();
|
||||||
let gamma_rate = u32::from_str_radix(&most_common_bits(&report), 2).unwrap();
|
let diagnostics = Diagnostics::<12> { report: report };
|
||||||
let epsilon_rate = 0xfff ^ gamma_rate;
|
|
||||||
println!("gamma rate {} epsilon rate {}", gamma_rate, epsilon_rate);
|
|
||||||
println!("solution {}", gamma_rate * epsilon_rate);
|
|
||||||
|
|
||||||
let oxygen_generator_rating =
|
println!(
|
||||||
u32::from_str_radix(&most_common_value(report.clone(), 12).unwrap(), 2).unwrap();
|
"gamma rate {} epsilon rate {}",
|
||||||
println!("oxygen generator rating {}", oxygen_generator_rating);
|
diagnostics.gamma_rate(),
|
||||||
|
diagnostics.epsilon_rate()
|
||||||
|
);
|
||||||
|
println!(
|
||||||
|
"solution {}",
|
||||||
|
diagnostics.gamma_rate() * diagnostics.epsilon_rate()
|
||||||
|
);
|
||||||
|
|
||||||
let co2_scrubber_rating = u32::from_str_radix(&least_common_value(report).unwrap(), 2).unwrap();
|
println!(
|
||||||
println!("CO2 scrubber rating {}", co2_scrubber_rating);
|
"oxygen generator rating {} CO2 scrubber rating {}",
|
||||||
|
diagnostics.oxygen_generator_rating(),
|
||||||
println!("solution {}", oxygen_generator_rating * co2_scrubber_rating);
|
diagnostics.co2_scrubber_rating()
|
||||||
|
);
|
||||||
|
println!(
|
||||||
|
"solution {}",
|
||||||
|
diagnostics.oxygen_generator_rating() * diagnostics.co2_scrubber_rating()
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
@ -107,5 +128,6 @@ fn oxygen_generator_rating() {
|
|||||||
"00010".to_string(),
|
"00010".to_string(),
|
||||||
"01010".to_string(),
|
"01010".to_string(),
|
||||||
];
|
];
|
||||||
assert_eq!(most_common_value(report, 5).unwrap(), "10111");
|
let diagnostics = Diagnostics::<5> { report: report };
|
||||||
|
assert_eq!(diagnostics.most_common_value(), "10111");
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user