1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
|
use std::fs;
use std::path::Path;
const ENTRY_LENGTH: usize = 12;
/* AOC21 Day 3: https://adventofcode.com/2021/day/3 */
fn main() {
let input = Path::new("resources").join("input.txt");
let content = fs::read_to_string(input).expect("Unable to read input file");
let report: Vec<u32> = content.lines().map(|l| u32::from_str_radix(l,2).expect("Malformed input")).collect();
ex1(&report);
ex2(report);
}
fn ex1(report: &[u32]) {
let gamma = compute_gamma(&report);
let epsilon = compute_epsilon(gamma);
println!("Ex1: the result is {} ({} * {})", gamma*epsilon, gamma, epsilon);
}
fn compute_gamma(report: &[u32]) -> u32 {
let length = report.len() as u32;
let mut counter: Vec<u32> = vec![0; ENTRY_LENGTH];
report.iter().for_each(|entry| counter.iter_mut().enumerate().for_each(|(i,v)| *v += (entry >> i) & 1));
counter.iter().enumerate().map(|(i,v)| if v*2 > length { 1 << i } else { 0 }).sum()
}
fn compute_epsilon(gamma: u32) -> u32 {
gamma ^ ((1 << ENTRY_LENGTH)-1)
}
fn ex2(report: Vec<u32>) {
let o2 = compute_rating(report.clone(), ENTRY_LENGTH, 1);
let co2 = compute_rating(report, ENTRY_LENGTH, 0);
println!("Ex2: the result is {} ({} * {})", o2*co2, o2, co2);
}
fn compute_rating(mut ratings: Vec<u32>, bit: usize, criterion: u32) -> u32 {
if ratings.len() == 1 || bit == 0 {
ratings[0]
} else {
let ones = ratings.iter().filter(|&r| ((r >> bit-1) & 1) == 1).count();
let sel = if 2*ones < ratings.len() { 1^criterion } else { criterion };
ratings.retain(|&r| ((r >> bit-1) & 1) == sel);
compute_rating(ratings, bit-1, criterion)
}
}
#[cfg(test)]
mod tests {
use super::*;
const TEST_INPUT: [u32;12] = [0b00100, 0b11110, 0b10110, 0b10111, 0b10101, 0b01111, 0b00111, 0b11100, 0b10000, 0b11001, 0b00010, 0b01010];
const ENTRY_LENGTH: usize = 5;
#[test]
fn oxygen_generator_rating() {
assert_eq!(23,compute_rating(Vec::from(TEST_INPUT), ENTRY_LENGTH, 1))
}
#[test]
fn co2_scrubber_rating() {
assert_eq!(10,compute_rating(Vec::from(TEST_INPUT), ENTRY_LENGTH, 0))
}
}
|