2021: day03: factorize
This commit is contained in:
parent
03746a1dec
commit
a776f56915
|
@ -73,10 +73,12 @@ fn part2(input: &str) -> Result<u64> {
|
||||||
Ok(oxygen_generator_rating * co2_scrubber_rating)
|
Ok(oxygen_generator_rating * co2_scrubber_rating)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// To find oxygen generator rating, determine the most common value (0 or 1) in the current bit
|
enum FilterStrategy {
|
||||||
/// position, and keep only numbers with that bit in that position. If 0 and 1 are equally common,
|
MostCommon,
|
||||||
/// keep values with a 1 in the position being considered.
|
LeastCommon,
|
||||||
fn compute_oxygen_generator_rating(binary_numbers: &[&str], size: usize) -> Result<u64> {
|
}
|
||||||
|
|
||||||
|
fn filter_by_strat(binary_numbers: &[&str], size: usize, strat: FilterStrategy) -> Result<u64> {
|
||||||
let mut numbers = binary_numbers.to_vec();
|
let mut numbers = binary_numbers.to_vec();
|
||||||
|
|
||||||
for pos in 0..size {
|
for pos in 0..size {
|
||||||
|
@ -85,18 +87,24 @@ fn compute_oxygen_generator_rating(binary_numbers: &[&str], size: usize) -> Resu
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
let most_common = if count_ones(&numbers, pos) >= ((numbers.len() + 1) / 2) {
|
let digit_of_interest = if count_ones(&numbers, pos) >= ((numbers.len() + 1) / 2) {
|
||||||
// majority of ones, or equality
|
// majority of ones, or equality
|
||||||
'1'
|
match strat {
|
||||||
|
FilterStrategy::MostCommon => '1',
|
||||||
|
FilterStrategy::LeastCommon => '0',
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
// majority of zeroes
|
// majority of zeroes
|
||||||
'0'
|
match strat {
|
||||||
|
FilterStrategy::MostCommon => '0',
|
||||||
|
FilterStrategy::LeastCommon => '1',
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
// TODO: use drain_filter when stable
|
// TODO: use drain_filter when stable
|
||||||
let mut i = 0;
|
let mut i = 0;
|
||||||
while i < numbers.len() {
|
while i < numbers.len() {
|
||||||
if numbers[i].chars().nth(pos).unwrap() != most_common {
|
if numbers[i].chars().nth(pos).unwrap() != digit_of_interest {
|
||||||
numbers.remove(i);
|
numbers.remove(i);
|
||||||
} else {
|
} else {
|
||||||
i += 1;
|
i += 1;
|
||||||
|
@ -109,40 +117,18 @@ fn compute_oxygen_generator_rating(binary_numbers: &[&str], size: usize) -> Resu
|
||||||
u64::from_str_radix(numbers[0], 2).context("couldn't parse binary number")
|
u64::from_str_radix(numbers[0], 2).context("couldn't parse binary number")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// To find oxygen generator rating, determine the most common value (0 or 1) in the current bit
|
||||||
|
/// position, and keep only numbers with that bit in that position. If 0 and 1 are equally common,
|
||||||
|
/// keep values with a 1 in the position being considered.
|
||||||
|
fn compute_oxygen_generator_rating(binary_numbers: &[&str], size: usize) -> Result<u64> {
|
||||||
|
filter_by_strat(binary_numbers, size, FilterStrategy::MostCommon)
|
||||||
|
}
|
||||||
|
|
||||||
/// To find CO2 scrubber rating, determine the least common value (0 or 1) in the current bit
|
/// To find CO2 scrubber rating, determine the least common value (0 or 1) in the current bit
|
||||||
/// position, and keep only numbers with that bit in that position. If 0 and 1 are equally
|
/// position, and keep only numbers with that bit in that position. If 0 and 1 are equally
|
||||||
/// common, keep values with a 0 in the position being considered.
|
/// common, keep values with a 0 in the position being considered.
|
||||||
fn compute_co2_scrubber_rating(binary_numbers: &[&str], size: usize) -> Result<u64> {
|
fn compute_co2_scrubber_rating(binary_numbers: &[&str], size: usize) -> Result<u64> {
|
||||||
let mut numbers = binary_numbers.to_vec();
|
filter_by_strat(binary_numbers, size, FilterStrategy::LeastCommon)
|
||||||
|
|
||||||
for pos in 0..size {
|
|
||||||
if numbers.len() == 1 {
|
|
||||||
// only one number left, we're done!
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
let least_common = if count_ones(&numbers, pos) < ((numbers.len() + 1) / 2) {
|
|
||||||
// majority of ones
|
|
||||||
'1'
|
|
||||||
} else {
|
|
||||||
// majority of zeroes, or equality
|
|
||||||
'0'
|
|
||||||
};
|
|
||||||
|
|
||||||
// TODO: use drain_filter when stable
|
|
||||||
let mut i = 0;
|
|
||||||
while i < numbers.len() {
|
|
||||||
if numbers[i].chars().nth(pos).unwrap() != least_common {
|
|
||||||
numbers.remove(i);
|
|
||||||
} else {
|
|
||||||
i += 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
debug_assert_eq!(numbers.len(), 1);
|
|
||||||
|
|
||||||
u64::from_str_radix(numbers[0], 2).context("couldn't parse binary number")
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
|
|
Loading…
Reference in a new issue