Skip to content

Commit c844659

Browse files
committed
2017 day 24
1 parent 91d33c3 commit c844659

File tree

2 files changed

+92
-0
lines changed

2 files changed

+92
-0
lines changed

crates/year2017/src/day24.rs

Lines changed: 91 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,91 @@
1+
use utils::bit::BitIterator;
2+
use utils::prelude::*;
3+
4+
/// Finding the longest and strongest bridge.
5+
#[derive(Clone, Debug)]
6+
pub struct Day24 {
7+
part1: u32,
8+
part2: u32,
9+
}
10+
11+
impl Day24 {
12+
pub fn new(input: &str, _: InputType) -> Result<Self, InputError> {
13+
let mut components: Vec<[u32; 2]> = parser::number_range(0..=63)
14+
.repeat_n(b'/')
15+
.parse_lines(input)?;
16+
if components.len() >= 64 {
17+
return Err(InputError::new(input, input.len(), "too many components"));
18+
}
19+
20+
// Sort all the components with matching pin counts first
21+
components.sort_unstable_by_key(|&[a, b]| a != b);
22+
23+
let mut bitsets = [0u64; 64];
24+
let mut sums = [0u32; 64];
25+
for (i, &[a, b]) in components.iter().enumerate() {
26+
bitsets[a as usize] |= 1 << i;
27+
bitsets[b as usize] |= 1 << i;
28+
sums[i] = a + b;
29+
}
30+
if bitsets[0] == 0 {
31+
return Err(InputError::new(input, 0, "no zero pin components"));
32+
}
33+
34+
let mut out = [0u32; 64];
35+
Self::search(&bitsets, &sums, &mut out, 0, 0, 0, 0);
36+
37+
Ok(Self {
38+
part1: out.iter().max().copied().unwrap(),
39+
part2: out.iter().rfind(|&&s| s > 0).copied().unwrap(),
40+
})
41+
}
42+
43+
fn search(
44+
bitsets: &[u64],
45+
sum: &[u32],
46+
best: &mut [u32],
47+
pins: u32,
48+
used: u64,
49+
strength: u32,
50+
length: usize,
51+
) {
52+
let remaining = bitsets[pins as usize] & !used;
53+
if remaining == 0 {
54+
best[length] = best[length].max(strength);
55+
return;
56+
}
57+
58+
for (component_index, component_bit) in BitIterator::ones(remaining) {
59+
let component_sum = sum[component_index as usize];
60+
61+
Self::search(
62+
bitsets,
63+
sum,
64+
best,
65+
component_sum - pins,
66+
used | component_bit,
67+
strength + component_sum,
68+
length + 1,
69+
);
70+
71+
// It is always optimal to choose a component with matching pins if available
72+
if component_sum == pins * 2 {
73+
break;
74+
}
75+
}
76+
}
77+
78+
#[must_use]
79+
pub fn part1(&self) -> u32 {
80+
self.part1
81+
}
82+
83+
#[must_use]
84+
pub fn part2(&self) -> u32 {
85+
self.part2
86+
}
87+
}
88+
89+
examples!(Day24 -> (u32, u32) [
90+
{input: "0/2\n2/2\n2/3\n3/4\n3/5\n0/1\n10/1\n9/10", part1: 31, part2: 19},
91+
]);

crates/year2017/src/lib.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,4 +27,5 @@ utils::year!(2017 => year2017, ${
2727
21 => day21::Day21,
2828
22 => day22::Day22,
2929
23 => day23::Day23,
30+
24 => day24::Day24,
3031
});

0 commit comments

Comments
 (0)