-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathsolution_2021_03.rs
102 lines (83 loc) · 2.44 KB
/
solution_2021_03.rs
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
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
use advent_of_code_common::utils::transpose;
use itertools::Itertools;
fn parse(input: &str) -> Vec<Vec<char>> {
input
.lines()
.filter(|x| !x.is_empty())
.map(|x| x.chars().collect())
.collect()
}
fn helper_for_something_common(line: &[char], arr: [char; 2]) -> char {
let zeros = line.iter().filter(|ch| **ch == '0').count();
if zeros > line.len() / 2 {
arr[0]
} else {
arr[1]
}
}
fn most_common(line: &[char]) -> char {
helper_for_something_common(line, ['0', '1'])
}
fn least_common(line: &[char]) -> char {
helper_for_something_common(line, ['1', '0'])
}
fn to_binary(a: &[char]) -> usize {
usize::from_str_radix(&a.to_vec().iter().join(""), 2).unwrap()
}
fn binary_mult(a: &[char], b: &[char]) -> usize {
to_binary(a) * to_binary(b)
}
fn part_1(input: &str) -> usize {
let lines = parse(input);
let transposed: Vec<Vec<char>> = transpose(&lines);
let gamma_rate: Vec<char> = transposed.iter().map(|x| most_common(x)).collect();
let epsilon_rate: Vec<char> = transposed.iter().map(|x| least_common(x)).collect();
binary_mult(&gamma_rate, &epsilon_rate)
}
fn solve_2(numbers: &[Vec<char>], idx: usize, f: fn(&[char]) -> char) -> Vec<char> {
let transposed: Vec<Vec<char>> = transpose(numbers);
if numbers.len() == 1 {
numbers[0].clone()
} else {
let appropriate_chars = &transposed[idx];
let needed = f(appropriate_chars);
let valid: Vec<_> = numbers
.iter()
.filter(|s| s[idx] == needed)
.cloned()
.collect();
solve_2(&valid, idx + 1, f)
}
}
fn part_2(input: &str) -> usize {
let lines = parse(input);
let oxygen_generator_rating = solve_2(&lines, 0, most_common);
let co2_scrubber_rating = solve_2(&lines, 0, least_common);
binary_mult(&oxygen_generator_rating, &co2_scrubber_rating)
}
#[allow(clippy::unreadable_literal)]
fn main() {
let test_data = "00100
11110
10110
10111
10101
01111
00111
11100
10000
11001
00010
01010";
let test_result_1 = part_1(test_data);
assert_eq!(test_result_1, 198);
let data = include_str!("../../resources/03.txt");
let result_1 = part_1(data);
assert_eq!(result_1, 2261546);
println!("Part 1: {result_1}");
let test_result_2 = part_2(test_data);
assert_eq!(test_result_2, 230);
let result_2 = part_2(data);
assert_eq!(result_2, 6775520);
println!("Part 2: {result_2}");
}