aboutsummaryrefslogtreecommitdiff
path: root/2022
diff options
context:
space:
mode:
Diffstat (limited to '2022')
-rw-r--r--2022/16/a.rs135
-rw-r--r--2022/16/b.rs216
2 files changed, 351 insertions, 0 deletions
diff --git a/2022/16/a.rs b/2022/16/a.rs
new file mode 100644
index 0000000..d6f3569
--- /dev/null
+++ b/2022/16/a.rs
@@ -0,0 +1,135 @@
1use std::cmp::max;
2use std::collections::HashMap;
3
4#[derive(Debug, Clone)]
5struct Node {
6 name: u16,
7 rate: usize,
8 neighbors: Vec<u16>
9}
10
11#[derive(Debug, Copy, Clone)]
12struct MapState {
13 valves: usize,
14 pos_ind: usize,
15 max_pos: usize
16}
17
18#[derive(Debug, Clone)]
19struct Map {
20 index: HashMap<u16, usize>,
21 nodes: Vec<Node>
22}
23
24fn getname(line: &str) -> u16 {
25 100 * (line.chars().nth(0).unwrap() as u16) +
26 (line.chars().nth(1).unwrap() as u16)
27}
28
29impl Node {
30 fn from_line(line: &str) -> Node {
31 let name = getname(&line[6..]);
32 let j = line.find(';').unwrap();
33 let rate = line[23..j].parse::<usize>().unwrap();
34 let mut neighbors = vec![];
35 let mut i = j+24;
36 // "tunnels lead to valves" vs "tunnel lead to valve"
37 // What kind of sadistic animal made these inputs?
38 if line.chars().nth(i).unwrap() == ' ' { i += 1; }
39 while i < line.len() {
40 neighbors.push(getname(&line[i..]));
41 i += 4;
42 }
43 Node { name, rate, neighbors }
44 }
45}
46
47impl Map {
48 fn from_stdin() -> Map {
49 let mut line = String::new();
50 let mut nodes = Vec::<Node>::new();
51 while std::io::stdin().read_line(&mut line).unwrap() > 0 {
52 let node = Node::from_line(&line);
53 if nodes.len() > 0 && node.name == getname("AA") {
54 nodes.push(nodes[0].clone());
55 nodes[0] = node;
56 } else {
57 nodes.push(node);
58 }
59 line.clear();
60 }
61 let index = nodes.iter()
62 .enumerate()
63 .map(|(i, n)| (n.name, i))
64 .collect::<HashMap<_, _>>();
65 Map { index, nodes }
66 }
67
68 fn state_max(&self) -> usize {
69 let mut i: usize = 0;
70 let mut tot: usize = 0;
71 for n in &self.nodes {
72 if n.rate == 0 { continue; }
73 tot += 1 << i;
74 i += 1;
75 }
76 let len = self.nodes.len();
77 tot * len + len
78 }
79
80 fn released_pressure(&self) -> usize {
81 self.nodes.iter()
82 .map(|n| if n.valve_on { n.rate } else { 0 })
83 .sum()
84 }
85
86 fn most_pressure(&self, minutes: usize) -> usize {
87 let n = self.state_max();
88 let mut t = vec![0 as usize; n];
89 let mut u = vec![0 as usize; n];
90 let mut map = self.clone();
91
92 // Setup table for last minute
93 for s in 0..n {
94 map.set_state(s);
95 t[s] = map.released_pressure();
96 }
97
98 // Dynamic programming counting back to 0 minutes
99 for i in (0..minutes).rev() {
100 // Double buffer technique so we don't have to swap vectors
101 let (current, next) = if i % 2 == minutes % 2 {
102 (&mut t, &mut u)
103 } else {
104 (&mut u, &mut t)
105 };
106 for s in 0..n {
107 map.set_state(s);
108 let pos = map.pos;
109 let mut k = 0;
110 let ind = map.index[&pos];
111 let p = map.released_pressure();
112
113 // Try turning on the valve
114 if map.nodes[ind].rate > 0 && !map.nodes[ind].valve_on {
115 map.nodes[ind].valve_on = true;
116 k = max(k, p + next[map.get_state()]);
117 map.nodes[ind].valve_on = false;
118 }
119
120 // Try moving to a neighbor
121 for v in &map.nodes[ind].neighbors {
122 map.pos = *v;
123 k = max(k, p + next[map.get_state()]);
124 }
125 current[s] = k;
126 }
127 }
128 if 0 == minutes % 2 { t[0] } else { u[0] }
129 }
130}
131
132fn main() {
133 let map = Map::from_stdin();
134 println!("{}", map.most_pressure(29));
135}
diff --git a/2022/16/b.rs b/2022/16/b.rs
new file mode 100644
index 0000000..defd5d1
--- /dev/null
+++ b/2022/16/b.rs
@@ -0,0 +1,216 @@
1use std::cmp::{max, Eq, PartialEq};
2use std::collections::HashMap;
3use std::hash::{Hash, Hasher};
4
5#[derive(Debug, Clone)]
6struct Node {
7 name: u16,
8 rate: usize,
9 neighbors: Vec<u16>,
10 valve_on: bool
11}
12
13#[derive(Debug, Clone)]
14struct Map {
15 index: HashMap<u16, usize>,
16 nodes: Vec<Node>,
17 pos: u16
18}
19
20fn getname(line: &str) -> u16 {
21 100 * (line.chars().nth(0).unwrap() as u16) +
22 (line.chars().nth(1).unwrap() as u16)
23}
24
25impl Node {
26 fn from_line(line: &str) -> Node {
27 let name = getname(&line[6..]);
28 let j = line.find(';').unwrap();
29 let rate = line[23..j].parse::<usize>().unwrap();
30 let mut neighbors = vec![];
31 let mut i = j+24;
32 // "tunnels lead to valves" vs "tunnel lead to valve"
33 // What kind of sadistic animal made these inputs?
34 if line.chars().nth(i).unwrap() == ' ' { i += 1; }
35 while i < line.len() {
36 neighbors.push(getname(&line[i..]));
37 i += 4;
38 }
39 Node { name, rate, neighbors, valve_on: false }
40 }
41}
42
43impl Map {
44 fn from_stdin() -> Map {
45 let mut line = String::new();
46 let mut nodes = Vec::<Node>::new();
47 while std::io::stdin().read_line(&mut line).unwrap() > 0 {
48 let node = Node::from_line(&line);
49 if nodes.len() > 0 && node.name == getname("AA") {
50 nodes.push(nodes[0].clone());
51 nodes[0] = node;
52 } else {
53 nodes.push(node);
54 }
55 line.clear();
56 }
57 let index = nodes.iter()
58 .enumerate()
59 .map(|(i, n)| (n.name, i))
60 .collect::<HashMap<_, _>>();
61 Map { index, nodes, pos: getname("AA") }
62 }
63
64 fn get_state(&self) -> usize {
65 let mut i: usize = 0;
66 let mut tot: usize = 0;
67 for n in &self.nodes {
68 if n.rate == 0 { continue; }
69 if n.valve_on { tot += 1 << i; }
70 i += 1;
71 }
72 tot * self.nodes.len() + self.index[&self.pos]
73 }
74
75 fn set_state(&mut self, state: usize) {
76 let mut s = state;
77 let len = self.nodes.len();
78 self.pos = self.nodes[s%len].name;
79 s /= len;
80 for i in 0..len {
81 if self.nodes[i].rate == 0 { continue; }
82 self.nodes[i].valve_on = s % 2 == 1;
83 s /= 2;
84 }
85 }
86
87 fn state_max(&self) -> usize {
88 let mut i: usize = 0;
89 let mut tot: usize = 0;
90 for n in &self.nodes {
91 if n.rate == 0 { continue; }
92 tot += 1 << i;
93 i += 1;
94 }
95 let len = self.nodes.len();
96 tot * len + len
97 }
98
99 fn released_pressure(&self) -> usize {
100 self.nodes.iter()
101 .map(|n| if n.valve_on { n.rate } else { 0 })
102 .sum()
103 }
104
105/*
106 fn most_pressure(&self, minutes: usize) -> usize {
107 let n = self.state_max();
108 let mut t = vec![0 as usize; n];
109 let mut u = vec![0 as usize; n];
110 let mut map = self.clone();
111
112 // Setup table for last minute
113 for s in 0..n {
114 map.set_state(s);
115 t[s] = map.released_pressure();
116 }
117
118 // Dynamic programming counting back to 0 minutes
119 for i in (0..minutes).rev() {
120 // Double buffer technique so we don't have to swap vectors
121 let (current, next) = if i % 2 == minutes % 2 {
122 (&mut t, &mut u)
123 } else {
124 (&mut u, &mut t)
125 };
126 for s in 0..n {
127 map.set_state(s);
128 let pos = map.pos;
129 let mut k = 0;
130 let ind = map.index[&pos];
131 let p = map.released_pressure();
132
133 // Try turning on the valve
134 if map.nodes[ind].rate > 0 && !map.nodes[ind].valve_on {
135 map.nodes[ind].valve_on = true;
136 k = max(k, p + next[map.get_state()]);
137 map.nodes[ind].valve_on = false;
138 }
139
140 // Try moving to a neighbor
141 for v in &map.nodes[ind].neighbors {
142 map.pos = *v;
143 k = max(k, p + next[map.get_state()]);
144 }
145 current[s] = k;
146 }
147 }
148 if 0 == minutes % 2 { t[0] } else { u[0] }
149 }
150*/
151
152 fn most_pressure(&self, minutes: usize) -> usize {
153 let n = self.state_max();
154 let mut t = vec![0 as usize; n];
155 let mut u = vec![0 as usize; n];
156 let mut map = self.clone();
157
158 // Setup table for last minute
159 for s in 0..n {
160 map.set_state(s);
161 t[s] = map.released_pressure();
162 }
163
164 // Dynamic programming counting back to 0 minutes
165 for i in (0..minutes).rev() {
166 // Double buffer technique so we don't have to swap vectors
167 let (current, next) = if i % 2 == minutes % 2 {
168 (&mut t, &mut u)
169 } else {
170 (&mut u, &mut t)
171 };
172 for s in 0..n {
173 map.set_state(s);
174 let pos = map.pos;
175 let mut k = 0;
176 let ind = map.index[&pos];
177 let p = map.released_pressure();
178
179 // Try turning on the valve
180 if map.nodes[ind].rate > 0 && !map.nodes[ind].valve_on {
181 map.nodes[ind].valve_on = true;
182 k = max(k, p + next[map.get_state()]);
183 map.nodes[ind].valve_on = false;
184 }
185
186 // Try moving to a neighbor
187 for v in &map.nodes[ind].neighbors {
188 map.pos = *v;
189 k = max(k, p + next[map.get_state()]);
190 }
191 current[s] = k;
192 }
193 }
194 if 0 == minutes % 2 { t[0] } else { u[0] }
195 }
196}
197
198impl PartialEq for Map {
199 fn eq(&self, other: &Self) -> bool {
200 self.get_state() == other.get_state()
201 }
202}
203
204impl Eq for Map {}
205
206impl Hash for Map {
207 fn hash<H: Hasher>(&self, hasher: &mut H) {
208 hasher.write_usize(self.get_state());
209 }
210}
211
212fn main() {
213 let map = Map::from_stdin();
214 let mut t = HashMap::<Map, usize>::new();
215 println!("{}", map.most_pressure(29, t));
216}

Generated with cgit - Back to sebastiano.tronto.net