aboutsummaryrefslogtreecommitdiff
path: root/2022/16/a.rs
diff options
context:
space:
mode:
authorSebastiano Tronto <sebastiano@tronto.net>2025-07-03 11:10:12 +0200
committerSebastiano Tronto <sebastiano@tronto.net>2025-07-03 11:10:12 +0200
commit36c94296df6edce01db71afeadb8940e33ecdd4a (patch)
tree72a48963ad79e99819339ac865e8a4f89e8d68aa /2022/16/a.rs
parentda1e366c3d6fd6b746a7eb34cf7124adcbd15805 (diff)
downloadaoc-36c94296df6edce01db71afeadb8940e33ecdd4a.tar.gz
aoc-36c94296df6edce01db71afeadb8940e33ecdd4a.zip
Day 16 2022, but part b is slow
Diffstat (limited to '2022/16/a.rs')
-rw-r--r--2022/16/a.rs112
1 files changed, 71 insertions, 41 deletions
diff --git a/2022/16/a.rs b/2022/16/a.rs
index d6f3569..da9a881 100644
--- a/2022/16/a.rs
+++ b/2022/16/a.rs
@@ -10,14 +10,16 @@ struct Node {
10 10
11#[derive(Debug, Copy, Clone)] 11#[derive(Debug, Copy, Clone)]
12struct MapState { 12struct MapState {
13 max_pos: usize,
13 valves: usize, 14 valves: usize,
14 pos_ind: usize, 15 pub pos: usize
15 max_pos: usize
16} 16}
17 17
18#[derive(Debug, Clone)] 18#[derive(Debug, Clone)]
19struct Map { 19struct Map {
20 index: HashMap<u16, usize>, 20 index: HashMap<u16, usize>,
21 state_index: HashMap<u16, usize>,
22 pressure: Vec<usize>,
21 nodes: Vec<Node> 23 nodes: Vec<Node>
22} 24}
23 25
@@ -44,9 +46,34 @@ impl Node {
44 } 46 }
45} 47}
46 48
49impl MapState {
50 fn from_usize(i: usize, map: &Map) -> MapState {
51 let max_pos = map.index.len();
52 MapState {
53 max_pos,
54 valves: i / max_pos,
55 pos: i % max_pos
56 }
57 }
58
59 fn to_usize(&self) -> usize {
60 self.max_pos * self.valves + self.pos
61 }
62
63 fn get_valve(&self, i: usize) -> bool {
64 self.valves & (1 << i) != 0
65 }
66
67 fn toggle_valve(&mut self, i: usize) {
68 self.valves ^= 1 << i;
69 }
70}
71
47impl Map { 72impl Map {
48 fn from_stdin() -> Map { 73 fn from_stdin() -> Map {
49 let mut line = String::new(); 74 let mut line = String::new();
75
76 // Get the nodes
50 let mut nodes = Vec::<Node>::new(); 77 let mut nodes = Vec::<Node>::new();
51 while std::io::stdin().read_line(&mut line).unwrap() > 0 { 78 while std::io::stdin().read_line(&mut line).unwrap() > 0 {
52 let node = Node::from_line(&line); 79 let node = Node::from_line(&line);
@@ -58,78 +85,81 @@ impl Map {
58 } 85 }
59 line.clear(); 86 line.clear();
60 } 87 }
61 let index = nodes.iter()
62 .enumerate()
63 .map(|(i, n)| (n.name, i))
64 .collect::<HashMap<_, _>>();
65 Map { index, nodes }
66 }
67 88
68 fn state_max(&self) -> usize { 89 // Compute the node-name-to-index tables
69 let mut i: usize = 0; 90 let mut j = 0;
70 let mut tot: usize = 0; 91 let mut index = HashMap::<u16, usize>::new();
71 for n in &self.nodes { 92 let mut state_index = HashMap::<u16, usize>::new();
72 if n.rate == 0 { continue; } 93 let mut pressure = vec![0];
73 tot += 1 << i; 94 for i in 0..nodes.len() {
74 i += 1; 95 index.insert(nodes[i].name, i);
96 if nodes[i].rate != 0 {
97 state_index.insert(nodes[i].name, j);
98 j += 1;
99
100 // Pre-compute flow rate for all states with node[i] turned on
101 for k in 0..pressure.len() {
102 pressure.push(pressure[k] + nodes[i].rate);
103 }
104 }
75 } 105 }
76 let len = self.nodes.len(); 106
77 tot * len + len 107 Map { index, state_index, pressure, nodes }
78 } 108 }
79 109
80 fn released_pressure(&self) -> usize { 110 fn state_max(&self) -> usize {
81 self.nodes.iter() 111 self.index.len() * (1 << self.state_index.len())
82 .map(|n| if n.valve_on { n.rate } else { 0 })
83 .sum()
84 } 112 }
85 113
86 fn most_pressure(&self, minutes: usize) -> usize { 114 fn most_pressure(&self, minutes: usize) -> usize {
87 let n = self.state_max(); 115 let n = self.state_max();
88 let mut t = vec![0 as usize; n]; 116 let mut t = vec![0 as usize; n];
89 let mut u = vec![0 as usize; n]; 117 let mut u = vec![0 as usize; n];
90 let mut map = self.clone();
91 118
92 // Setup table for last minute 119 // Setup table for last minute
93 for s in 0..n { 120 for s in 0..n {
94 map.set_state(s); 121 t[s] = self.pressure[MapState::from_usize(s, self).valves];
95 t[s] = map.released_pressure(); 122 u[s] = t[s];
96 } 123 }
97 124
98 // Dynamic programming counting back to 0 minutes 125 // Dynamic programming counting back to 0 minutes
99 for i in (0..minutes).rev() { 126 for i in 0..minutes-1 {
100 // Double buffer technique so we don't have to swap vectors 127 // Double buffer technique so we don't have to swap vectors
101 let (current, next) = if i % 2 == minutes % 2 { 128 let (current, next) = if i % 2 == 0 {
102 (&mut t, &mut u) 129 (&mut t, &u)
103 } else { 130 } else {
104 (&mut u, &mut t) 131 (&mut u, &t)
105 }; 132 };
106 for s in 0..n { 133 for s in 0..n {
107 map.set_state(s); 134 let mut state = MapState::from_usize(s, self);
108 let pos = map.pos;
109 let mut k = 0; 135 let mut k = 0;
110 let ind = map.index[&pos]; 136 let ind = self.index[&self.nodes[state.pos].name];
111 let p = map.released_pressure(); 137 let p = self.pressure[state.valves];
112 138
113 // Try turning on the valve 139 // Try turning on the valve
114 if map.nodes[ind].rate > 0 && !map.nodes[ind].valve_on { 140 if self.nodes[ind].rate > 0 {
115 map.nodes[ind].valve_on = true; 141 let si = self.state_index[&self.nodes[ind].name];
116 k = max(k, p + next[map.get_state()]); 142 if !state.get_valve(si) {
117 map.nodes[ind].valve_on = false; 143 state.toggle_valve(si);
144 k = max(k, p + next[state.to_usize()]);
145 state.toggle_valve(si);
146 }
118 } 147 }
119 148
120 // Try moving to a neighbor 149 // Try moving to a neighbor
121 for v in &map.nodes[ind].neighbors { 150 for v in &self.nodes[ind].neighbors {
122 map.pos = *v; 151 state.pos = self.index[v];
123 k = max(k, p + next[map.get_state()]); 152 k = max(k, p + next[state.to_usize()]);
124 } 153 }
125 current[s] = k; 154 current[s] = k;
126 } 155 }
127 } 156 }
128 if 0 == minutes % 2 { t[0] } else { u[0] } 157 if 0 == minutes % 2 { t[0] } else { u[0] } // Initial state = 0
129 } 158 }
130} 159}
131 160
132fn main() { 161fn main() {
133 let map = Map::from_stdin(); 162 let map = Map::from_stdin();
134 println!("{}", map.most_pressure(29)); 163 let result = map.most_pressure(30);
164 println!("{result}");
135} 165}

Generated with cgit - Back to sebastiano.tronto.net