2021-12-01 05:51:55 +00:00
|
|
|
#![feature(test)]
|
|
|
|
extern crate test;
|
|
|
|
|
2021-12-03 05:38:45 +00:00
|
|
|
const INPUTS: [&'static str; 2] = [
|
|
|
|
include_str!("../inputs/day3.sample.txt"),
|
|
|
|
include_str!("../inputs/day3.txt"),
|
|
|
|
];
|
2021-12-02 05:14:07 +00:00
|
|
|
|
2021-12-03 05:38:45 +00:00
|
|
|
fn cmds(input: &'static str) -> Vec<u64> {
|
|
|
|
input
|
|
|
|
.lines()
|
|
|
|
.filter(|&x| !x.is_empty())
|
|
|
|
.map(|x| u64::from_str_radix(x, 2).unwrap())
|
|
|
|
.collect()
|
2021-12-01 05:16:08 +00:00
|
|
|
}
|
|
|
|
|
2021-12-03 13:33:56 +00:00
|
|
|
fn solution<const MAX_LENGTH: usize>(levels: Vec<u64>) -> u64 {
|
|
|
|
let oxygen_gen_rating = filter_candidates::<MAX_LENGTH>(levels.clone(), true);
|
|
|
|
let co2_scrub_rating = filter_candidates::<MAX_LENGTH>(levels, false);
|
|
|
|
|
|
|
|
oxygen_gen_rating * co2_scrub_rating
|
|
|
|
}
|
|
|
|
|
|
|
|
fn filter_candidates<const MAX_LENGTH: usize>(mut levels: Vec<u64>, dominant: bool) -> u64 {
|
|
|
|
let mut i = 0;
|
|
|
|
while levels.len() > 1 {
|
|
|
|
let count = count_bits::<MAX_LENGTH>(&levels, dominant);
|
|
|
|
let leading = count & (1 << (MAX_LENGTH - i - 1));
|
|
|
|
|
|
|
|
levels = levels
|
|
|
|
.into_iter()
|
|
|
|
.filter(|&x| {
|
|
|
|
let pos = x & (1 << (MAX_LENGTH - i - 1));
|
|
|
|
|
|
|
|
return pos == leading;
|
|
|
|
})
|
|
|
|
.collect();
|
|
|
|
|
|
|
|
i += 1;
|
2021-12-03 05:38:45 +00:00
|
|
|
}
|
2021-12-02 05:14:07 +00:00
|
|
|
|
2021-12-03 13:33:56 +00:00
|
|
|
levels[0]
|
2021-12-02 05:18:04 +00:00
|
|
|
}
|
|
|
|
|
2021-12-03 13:33:56 +00:00
|
|
|
fn count_bits<const MAX_LENGTH: usize>(levels: &[u64], dominant: bool) -> u64 {
|
2021-12-03 05:38:45 +00:00
|
|
|
let n = levels.len();
|
2021-12-03 13:33:56 +00:00
|
|
|
let mut count = [0; MAX_LENGTH];
|
|
|
|
let mut mask = 0;
|
2021-12-03 05:38:45 +00:00
|
|
|
|
|
|
|
for &level in levels.iter() {
|
2021-12-03 13:33:56 +00:00
|
|
|
for i in 0..MAX_LENGTH {
|
|
|
|
let c = level & (1 << (MAX_LENGTH - i - 1));
|
2021-12-02 05:14:07 +00:00
|
|
|
|
2021-12-03 05:38:45 +00:00
|
|
|
if c != 0 {
|
|
|
|
count[i as usize] += 1;
|
2021-12-02 05:18:04 +00:00
|
|
|
}
|
2021-12-01 05:16:08 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-12-03 05:38:45 +00:00
|
|
|
for (i, c) in count.into_iter().enumerate() {
|
|
|
|
if c >= n - c {
|
2021-12-03 13:33:56 +00:00
|
|
|
mask |= 1 << (MAX_LENGTH - i - 1);
|
2021-12-03 05:38:45 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if dominant {
|
|
|
|
mask
|
|
|
|
} else {
|
|
|
|
!mask
|
|
|
|
}
|
2021-12-01 05:51:55 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
fn main() {
|
2021-12-03 05:38:45 +00:00
|
|
|
let moves = cmds(INPUTS[0]);
|
2021-12-03 13:33:56 +00:00
|
|
|
let count = solution::<5>(moves);
|
2021-12-03 05:38:45 +00:00
|
|
|
println!("Result {}", count);
|
|
|
|
let moves = cmds(INPUTS[1]);
|
2021-12-03 13:33:56 +00:00
|
|
|
let count = solution::<12>(moves);
|
2021-12-03 05:38:45 +00:00
|
|
|
println!("Result {}", count);
|
2021-12-01 05:16:08 +00:00
|
|
|
}
|
2021-12-01 05:51:55 +00:00
|
|
|
|
|
|
|
#[bench]
|
|
|
|
fn solution_bench(b: &mut test::Bencher) {
|
2021-12-03 05:38:45 +00:00
|
|
|
let moves = cmds(INPUTS[1]);
|
2021-12-01 05:51:55 +00:00
|
|
|
b.iter(|| {
|
2021-12-03 13:33:56 +00:00
|
|
|
let v = solution::<12>(moves.clone());
|
2021-12-01 05:51:55 +00:00
|
|
|
test::black_box(v);
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn solution_test() {
|
2021-12-03 13:33:56 +00:00
|
|
|
assert_eq!(solution::<5>(cmds(INPUTS[0])), 230);
|
|
|
|
assert_eq!(solution::<12>(cmds(INPUTS[1])), 4406844);
|
2021-12-01 05:51:55 +00:00
|
|
|
}
|