Don’t use log2 to get around bit count

This commit is contained in:
kageru 2021-12-03 14:41:02 +01:00
parent 312f526345
commit 5d90f44f2b

@ -1,9 +1,8 @@
#![feature(int_log)]
#![feature(test)] #![feature(test)]
extern crate test; extern crate test;
use aoc2021::common::*; use aoc2021::common::*;
const DAY: usize = 03; const DAY: usize = 3;
type Parsed = Vec<usize>; type Parsed = Vec<usize>;
fn parse_input(raw: &str) -> Parsed { fn parse_input(raw: &str) -> Parsed {
@ -22,13 +21,13 @@ fn most_common_at(parsed: &Parsed, n: usize) -> bool {
parsed.iter().filter(|&&x| bit_at(x, n)).count() * 2 >= parsed.len() parsed.iter().filter(|&&x| bit_at(x, n)).count() * 2 >= parsed.len()
} }
fn invert(n: usize) -> usize { fn invert(n: usize, bits: usize) -> usize {
!n & ((1 << n.log2()) - 1) !n & ((1 << bits) - 1)
} }
fn part1(parsed: &Parsed, bits: usize) -> usize { fn part1(parsed: &Parsed, bits: usize) -> usize {
let gamma = most_common(parsed, bits); let gamma = most_common(parsed, bits);
let epsilon = invert(gamma); let epsilon = invert(gamma, bits);
gamma * epsilon gamma * epsilon
} }
@ -39,7 +38,9 @@ fn part2(parsed: &Parsed, bits: usize) -> usize {
for i in (0..bits).rev() { for i in (0..bits).rev() {
let gamma = most_common_at(&matching_gamma, i); let gamma = most_common_at(&matching_gamma, i);
let epsilon = !most_common_at(&matching_epsilon, i); let epsilon = !most_common_at(&matching_epsilon, i);
// TODO: Find out why retain is significantly slower than filter().collect()
matching_gamma.retain(|&n| bit_at(n, i) == gamma); matching_gamma.retain(|&n| bit_at(n, i) == gamma);
// matching_gamma = matching_gamma.into_iter().filter(|&n| bit_at(n, i) == gamma).collect();
if matching_epsilon.len() > 1 { if matching_epsilon.len() > 1 {
matching_epsilon.retain(|&n| bit_at(n, i) == epsilon); matching_epsilon.retain(|&n| bit_at(n, i) == epsilon);
} }
@ -50,9 +51,11 @@ fn part2(parsed: &Parsed, bits: usize) -> usize {
} }
fn main() { fn main() {
let input = parse_input(&read_file(DAY)); let raw = read_file(DAY);
println!("Part 1: {}", part1(&input, 12)); let input = parse_input(&raw);
println!("Part 2: {}", part2(&input, 12)); let line_length = raw.find('\n').unwrap();
println!("Part 1: {}", part1(&input, line_length));
println!("Part 2: {}", part2(&input, line_length));
} }
#[cfg(test)] #[cfg(test)]
@ -82,7 +85,7 @@ mod tests {
#[test] #[test]
fn invert_test() { fn invert_test() {
let gamma = 0b10110; let gamma = 0b10110;
assert_eq!(invert(gamma), 0b01001); assert_eq!(invert(gamma, 4), 0b01001);
} }
#[test] #[test]