1use crate::util::bitset::*;
17use crate::util::iter::*;
18use crate::util::parse::*;
19
20struct Component {
21 left: usize,
22 right: usize,
23 weight: usize,
24 length: usize,
25}
26
27struct State {
28 possible: [usize; 64],
29 both: [usize; 64],
30 weight: [usize; 64],
31 length: [usize; 64],
32 bridge: [usize; 64],
33}
34
35pub fn parse(input: &str) -> [usize; 64] {
36 let mut components: Vec<_> = input
37 .iter_unsigned()
38 .chunk::<2>()
39 .map(|[left, right]| Component { left, right, weight: left + right, length: 1 })
40 .collect();
41
42 let mut indices = Vec::new();
45
46 for n in 1..64 {
47 for (index, component) in components.iter().enumerate() {
48 if component.left == n || component.right == n {
49 indices.push(index);
50 }
51 }
52
53 if indices.len() == 2 {
54 let second = components.swap_remove(indices[1]);
55 let first = components.swap_remove(indices[0]);
56
57 let left = if first.left == n { first.right } else { first.left };
58 let right = if second.left == n { second.right } else { second.left };
59 let weight = first.weight + second.weight;
60 let length = first.length + second.length;
61
62 components.push(Component { left, right, weight, length });
63 }
64
65 indices.clear();
66 }
67
68 components.sort_unstable_by(|a, b| {
71 (a.left ^ a.right).cmp(&(b.left ^ b.right)).then(a.left.cmp(&b.left))
72 });
73
74 let mut state = State {
75 possible: [0; 64],
76 both: [0; 64],
77 weight: [0; 64],
78 length: [0; 64],
79 bridge: [0; 64],
80 };
81
82 for (index, component) in components.iter().enumerate() {
83 let mask = 1 << index;
84 state.possible[component.left] |= mask;
85 state.possible[component.right] |= mask;
86
87 state.both[index] = component.left ^ component.right;
90 state.weight[index] = component.weight;
91 state.length[index] = component.length;
92 }
93
94 build(&mut state, 0, 0, 0, 0);
96 state.bridge
97}
98
99pub fn part1(input: &[usize]) -> usize {
101 *input.iter().max().unwrap()
102}
103
104pub fn part2(input: &[usize]) -> usize {
106 *input.iter().rfind(|&&n| n > 0).unwrap()
107}
108
109fn build(state: &mut State, current: usize, used: usize, strength: usize, length: usize) {
110 let remaining = state.possible[current] & !used;
112
113 for index in remaining.biterator() {
115 let next = current ^ state.both[index];
116 let used = used | (1 << index);
117 let strength = strength + state.weight[index];
118 let length = length + state.length[index];
119
120 if state.possible[next] & !used == 0 {
121 state.bridge[length] = state.bridge[length].max(strength);
123 } else {
124 build(state, next, used, strength, length);
125 if current == next {
129 break;
130 }
131 }
132 }
133}