-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathmain.rs
121 lines (105 loc) · 2.89 KB
/
main.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
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
#![warn(clippy::all, clippy::pedantic, clippy::nursery)]
use std::fmt::Display;
pub fn main() {
let data = include_str!("input.txt");
println!("Part 1: {}", part_one::<28>(data));
println!("Part 2: {}", part_two::<28>(data));
}
fn part_one<const N: usize>(data: &str) -> u64 {
let inputs = read_in::<N>(data);
let target: u16 = inputs.iter().sum::<u16>() / 3;
let min = min_selection(target, &inputs[..], Selection::new(), Selection::max());
min.quantum_entanglement
}
fn part_two<const N: usize>(data: &str) -> u64 {
let inputs = read_in::<N>(data);
let target: u16 = inputs.iter().sum::<u16>() / 4;
let min = min_selection(target, &inputs[..], Selection::new(), Selection::max());
min.quantum_entanglement
}
#[derive(Clone, Copy, Debug)]
struct Selection {
count: usize,
quantum_entanglement: u64,
items: [u16; 10],
}
impl Display for Selection {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "Selected Items: ")?;
for i in (1..self.count).rev() {
write!(f, "{}, ", self.items[i])?;
}
writeln!(f, "{} - ({} items)", self.items[0], self.count)?;
writeln!(f, "Quantum Entaglement: {}", self.quantum_entanglement)?;
writeln!(f)?;
Ok(())
}
}
impl Selection {
const fn new() -> Self {
Self {
count: 0,
quantum_entanglement: 1,
items: [0; 10],
}
}
const fn max() -> Self {
Self {
count: 10,
quantum_entanglement: u64::MAX,
items: [0; 10],
}
}
fn add(&mut self, item: u16) {
self.items[self.count] = item;
self.count += 1;
self.quantum_entanglement *= u64::from(item);
}
const fn still_valid(&self, test: Self) -> bool {
self.count <= test.count && self.quantum_entanglement < test.quantum_entanglement
}
}
fn min_selection(
target: u16,
mut list: &[u16],
current: Selection,
mut min: Selection,
) -> Selection {
while let Some((elem, rest)) = list.split_last() {
list = rest;
if elem > &target {
continue;
}
let mut next = current;
next.add(*elem);
if !next.still_valid(min) {
continue;
}
if elem == &target {
return next;
}
min = min_selection(target - *elem, rest, next, min);
}
min
}
fn read_in<const N: usize>(data: &str) -> [u16; N] {
let mut out = [0; N];
for (elem, line) in out.iter_mut().zip(data.lines()) {
*elem = line.parse().unwrap();
}
out
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn one() {
let data = include_str!("test.txt");
assert_eq!(99, part_one::<10>(data));
}
#[test]
fn two() {
let data = include_str!("test.txt");
assert_eq!(44, part_two::<10>(data));
}
}