82 lines
2.4 KiB
Rust
82 lines
2.4 KiB
Rust
use aoc_runner_derive::{aoc, aoc_generator};
|
|
type Data = Vec<u16>;
|
|
fn make_histogram(input: &[u16]) -> Vec<(usize, i64)> {
|
|
let counts: &mut [Option<i64>] = &mut [None; 64];
|
|
input.iter().for_each(|val| {
|
|
for (n, count) in counts.iter_mut().enumerate().take(12) {
|
|
let v = count.get_or_insert(0);
|
|
if ((val >> n) & 1) == 1 {
|
|
*v += 1;
|
|
} else {
|
|
*v -= 1;
|
|
}
|
|
}
|
|
});
|
|
counts.reverse();
|
|
counts
|
|
.iter()
|
|
.enumerate()
|
|
.filter_map(|(a, b)| b.map(|b| (a, b)))
|
|
.collect::<Vec<_>>()
|
|
}
|
|
#[aoc_generator(day03)]
|
|
pub fn input_generator(input: &str) -> Vec<u16> {
|
|
input
|
|
.lines()
|
|
.map(|l| u16::from_str_radix(l, 2).unwrap())
|
|
.collect()
|
|
}
|
|
#[derive(Debug)]
|
|
enum Mode {
|
|
MostCommon,
|
|
LeastCommon,
|
|
}
|
|
fn tree_filter(data: &[u16], mut pos: usize, mode: Mode) -> u16 {
|
|
let (zero, one) = data
|
|
.iter()
|
|
.partition::<Vec<u16>, _>(|&v| ((v >> pos) & 1) == 0);
|
|
if data.is_empty() {
|
|
panic!("Uh Oh!");
|
|
}
|
|
if data.len() == 1 {
|
|
return data[0];
|
|
}
|
|
pos=pos.wrapping_sub(1);
|
|
if zero.len() == one.len() {
|
|
match mode {
|
|
Mode::MostCommon => tree_filter(&one, pos, mode),
|
|
Mode::LeastCommon => tree_filter(&zero, pos, mode),
|
|
}
|
|
} else {
|
|
let mut srt = vec![zero, one];
|
|
srt.sort_by_key(|v| v.len());
|
|
match mode {
|
|
Mode::MostCommon => tree_filter(&srt[1], pos, mode),
|
|
Mode::LeastCommon => tree_filter(&srt[0], pos, mode),
|
|
}
|
|
}
|
|
}
|
|
const ASCII_ZERO: u8 = 0x30;
|
|
#[aoc(day03, part1)] // 1997414
|
|
pub fn solve_part1(input: &Data) -> usize {
|
|
let counts = make_histogram(input);
|
|
let (gamma, epsilon): (String, String) = counts
|
|
.iter()
|
|
.map(|(_, v)| {
|
|
(
|
|
(ASCII_ZERO + (*v >= 0) as u8) as char,
|
|
(ASCII_ZERO + (*v < 0) as u8) as char,
|
|
)
|
|
})
|
|
.unzip();
|
|
let gamma = usize::from_str_radix(&gamma, 2).unwrap();
|
|
let epsilon = usize::from_str_radix(&epsilon, 2).unwrap();
|
|
gamma * epsilon
|
|
}
|
|
#[aoc(day03, part2)] // 1032597
|
|
pub fn solve_part2(input: &[u16]) -> usize {
|
|
// let input: Vec<bool> = input.iter().for_each(|v| v[0]).collect();
|
|
let a = tree_filter(input, 11, Mode::MostCommon) as usize;
|
|
let b = tree_filter(input, 11, Mode::LeastCommon) as usize;
|
|
a * b
|
|
} |