aboutsummaryrefslogtreecommitdiff
path: root/2022/22/b.rs
diff options
context:
space:
mode:
authorSebastiano Tronto <sebastiano@tronto.net>2025-07-08 17:10:53 +0200
committerSebastiano Tronto <sebastiano@tronto.net>2025-07-08 17:10:53 +0200
commitdbb5a4e5711fba371fbb011356bcd8a28cc963e4 (patch)
tree75bb0574d4553eea96b45e2171d3849eee45a3ef /2022/22/b.rs
parent2641a35d5473beb6889b299b54de294fbf782b1f (diff)
downloadaoc-dbb5a4e5711fba371fbb011356bcd8a28cc963e4.tar.gz
aoc-dbb5a4e5711fba371fbb011356bcd8a28cc963e4.zip
Day 22 2022
Diffstat (limited to '2022/22/b.rs')
-rw-r--r--2022/22/b.rs314
1 files changed, 314 insertions, 0 deletions
diff --git a/2022/22/b.rs b/2022/22/b.rs
new file mode 100644
index 0000000..1d292ee
--- /dev/null
+++ b/2022/22/b.rs
@@ -0,0 +1,314 @@
1use std::mem::swap;
2mod common;
3use common::*;
4
5// Use 4 for the test input, 50 for the real one
6//const CUBE_SIZE: usize = 4;
7const CUBE_SIZE: usize = 50;
8
9// Connections between faces to make the cube 3D.
10// This is hard coded to work for my specific input.
11// To make it work for a different input you have to change this.
12// The faces are in top-to-bottom, left-to-right order of input.
13// For each face, the 4 connections are in order right, down, left, up.
14
15// Test case. Configuration:
16// 0 U = 0, D = 4
17// 123 R = 5, L = 2
18// 45 F = 3, B = 1
19/*
20const CONNECTIONS: [[Connection; 4]; 6] = [
21 // Face 0 = U
22 [
23 Connection { face: 5, side: Direction::Right },
24 Connection { face: 3, side: Direction::Up },
25 Connection { face: 2, side: Direction::Up },
26 Connection { face: 1, side: Direction::Up },
27 ],
28
29 // Face 1
30 [
31 Connection { face: 2, side: Direction::Left },
32 Connection { face: 4, side: Direction::Down },
33 Connection { face: 5, side: Direction::Down },
34 Connection { face: 0, side: Direction::Up },
35 ],
36
37 // Face 2
38 [
39 Connection { face: 3, side: Direction::Left },
40 Connection { face: 4, side: Direction::Left },
41 Connection { face: 1, side: Direction::Right },
42 Connection { face: 0, side: Direction::Left },
43 ],
44
45 // Face 3
46 [
47 Connection { face: 5, side: Direction::Up },
48 Connection { face: 4, side: Direction::Up },
49 Connection { face: 2, side: Direction::Right },
50 Connection { face: 0, side: Direction::Down },
51 ],
52
53 // Face 4
54 [
55 Connection { face: 5, side: Direction::Left },
56 Connection { face: 1, side: Direction::Down },
57 Connection { face: 2, side: Direction::Down },
58 Connection { face: 3, side: Direction::Down },
59 ],
60
61 // Face 5
62 [
63 Connection { face: 0, side: Direction::Right },
64 Connection { face: 1, side: Direction::Left },
65 Connection { face: 4, side: Direction::Right },
66 Connection { face: 3, side: Direction::Right },
67 ],
68];
69*/
70
71// Input. Configuration:
72// 01
73// 2
74// 34
75// 5
76const CONNECTIONS: [[Connection; 4]; 6] = [
77 // Face 0 = U
78 [
79 Connection { face: 1, side: Direction::Left },
80 Connection { face: 2, side: Direction::Up },
81 Connection { face: 3, side: Direction::Left },
82 Connection { face: 5, side: Direction::Left },
83 ],
84
85 // Face 1
86 [
87 Connection { face: 4, side: Direction::Right },
88 Connection { face: 2, side: Direction::Right },
89 Connection { face: 0, side: Direction::Right },
90 Connection { face: 5, side: Direction::Down },
91 ],
92
93 // Face 2
94 [
95 Connection { face: 1, side: Direction::Down },
96 Connection { face: 4, side: Direction::Up },
97 Connection { face: 3, side: Direction::Up },
98 Connection { face: 0, side: Direction::Down },
99 ],
100
101 // Face 3
102 [
103 Connection { face: 4, side: Direction::Left },
104 Connection { face: 5, side: Direction::Up },
105 Connection { face: 0, side: Direction::Left },
106 Connection { face: 2, side: Direction::Left },
107 ],
108
109 // Face 4
110 [
111 Connection { face: 1, side: Direction::Right },
112 Connection { face: 5, side: Direction::Right },
113 Connection { face: 3, side: Direction::Right },
114 Connection { face: 2, side: Direction::Down },
115 ],
116
117 // Face 5
118 [
119 Connection { face: 4, side: Direction::Down },
120 Connection { face: 1, side: Direction::Up },
121 Connection { face: 0, side: Direction::Up },
122 Connection { face: 3, side: Direction::Down },
123 ],
124];
125
126
127#[derive(Copy, Clone, Debug)]
128struct Connection {
129 pub face: usize,
130 pub side: Direction
131}
132
133struct Face {
134 pub tiles: [[Tile; CUBE_SIZE]; CUBE_SIZE],
135 offset_i: usize,
136 offset_j: usize
137}
138
139#[derive(PartialEq, Debug, Copy, Clone)]
140struct Position {
141 f: usize,
142 i: usize,
143 j: usize,
144 d: Direction
145}
146
147#[allow(dead_code)]
148impl Face {
149 pub fn empty() -> Face {
150 Face {
151 tiles: [[Tile::Skip; CUBE_SIZE]; CUBE_SIZE],
152 offset_i: 0,
153 offset_j: 0
154 }
155 }
156
157 pub fn is_empty(&self) -> bool {
158 self.tiles[0][0] == Tile::Skip
159 }
160
161 pub fn print(&self) {
162 for i in 0..CUBE_SIZE {
163 for j in 0..CUBE_SIZE {
164 print!("{}", self.tiles[i][j].to_char());
165 }
166 println!();
167 }
168 }
169}
170
171struct Cube {
172 pub faces: Vec<Face>
173}
174
175type StepFn = fn(&Cube, Position) -> Position;
176
177impl Cube {
178 pub fn from_stdin() -> Cube {
179 let mut faces = vec![];
180 let mut line = String::new();
181 let mut offset_i = 0;
182 while faces.len() < 6 {
183 let mut row = [Face::empty(), Face::empty(), Face::empty(),
184 Face::empty(), Face::empty(), Face::empty()];
185 for k in 0..CUBE_SIZE {
186 let _ = std::io::stdin().read_line(&mut line);
187 let bytes = &line.as_bytes();
188 for l in 0..line.len()-1 {
189 row[l / CUBE_SIZE].tiles[k][l % CUBE_SIZE] =
190 Tile::from_byte(bytes[l]);
191 }
192 line.clear();
193 }
194 let mut offset_j = 0;
195 for mut r in row {
196 r.offset_i = offset_i;
197 r.offset_j = offset_j;
198 if !r.is_empty() {
199 faces.push(r);
200 }
201 offset_j += CUBE_SIZE;
202 }
203 offset_i += CUBE_SIZE;
204 }
205 let _ = std::io::stdin().read_line(&mut line); // Read empty line
206 assert!(faces.len() == 6, "Cube has {} faces", faces.len());
207 Cube { faces }
208 }
209
210 fn start_position(&self) -> Position {
211 let j = self.faces[0].tiles[0].iter()
212 .position(|t| *t == Tile::Walk).unwrap();
213 Position { f: 0, i: 0, j, d: Direction::Right }
214 }
215
216 pub fn walk(&self, pos: Position, n: usize, step: StepFn) -> Position {
217 let mut p = pos;
218 for _ in 0..n { p = step(self, p); }
219 p
220 }
221}
222
223fn flips(d1: Direction, d2: Direction) -> bool {
224 match d1 {
225 Direction::Right | Direction::Up =>
226 d2 == Direction::Right || d2 == Direction::Up,
227 Direction::Down | Direction::Left =>
228 d2 == Direction::Down || d2 == Direction::Left
229 }
230}
231
232fn swaps(d1: Direction, d2: Direction) -> bool {
233 match d1 {
234 Direction::Right | Direction::Left =>
235 d2 == Direction::Up || d2 == Direction::Down,
236 Direction::Up | Direction::Down =>
237 d2 == Direction::Right || d2 == Direction::Left
238 }
239}
240
241fn validate_connections(conn: &[[Connection; 4]; 6]) {
242 for i in 0..6 {
243 for j in 0..4 {
244 let c = conn[i][j];
245 let d = conn[c.face][c.side.value()];
246 assert!(d.face == i, "Bad connection: face {}-{}", i, j);
247 assert!(d.side.value() == j, "Bad connection: side {}-{}", i, j);
248 }
249 }
250}
251
252fn overflow(i: i64, j: i64) -> Option<Direction> {
253 if i == -1 { return Some(Direction::Up) }
254 if j == -1 { return Some(Direction::Left) }
255 if i as usize == CUBE_SIZE { return Some(Direction::Down) }
256 if j as usize == CUBE_SIZE { return Some(Direction::Right) }
257 None
258}
259
260fn on_other_side(i: i64, flip: bool, positive: bool) -> usize {
261 const CUBE_SIZE_I64: i64 = CUBE_SIZE as i64;
262 (if i >= 0 && i < CUBE_SIZE_I64 {
263 if flip { CUBE_SIZE_I64 - i - 1 } else { i }
264 } else {
265 if positive { 0 } else { CUBE_SIZE_I64 - 1 }
266 }) as usize
267}
268
269fn step(cube: &Cube, p: Position) -> Position {
270 let s = p.d.step();
271 let mut inext = s.0 + p.i as i64;
272 let mut jnext = s.1 + p.j as i64;
273
274 let ret = if let Some(d) = overflow(inext, jnext) {
275 let conn = CONNECTIONS[p.f][d.value()];
276 let flip = flips(p.d, conn.side);
277 let new_direction = conn.side.opposite();
278 let positive = new_direction.is_positive();
279 if swaps(p.d, conn.side) { swap(&mut inext, &mut jnext) }
280 Position {
281 f: conn.face,
282 i: on_other_side(inext, flip, positive),
283 j: on_other_side(jnext, flip, positive),
284 d: conn.side.opposite()
285 }
286 } else {
287 Position {
288 f: p.f,
289 i: inext as usize,
290 j: jnext as usize,
291 d: p.d
292 }
293 };
294
295 if cube.faces[ret.f].tiles[ret.i][ret.j] == Tile::Wall { p } else { ret }
296}
297
298fn password(cube: &Cube, p: Position) -> usize {
299 let f = &cube.faces[p.f];
300 1000 * (p.i + f.offset_i + 1) + 4 * (p.j + f.offset_j + 1) + p.d.value()
301}
302
303fn main() {
304 validate_connections(&CONNECTIONS);
305 let cube = Cube::from_stdin();
306 let mut position = cube.start_position();
307 let (turns, steps) = read_instruction_line_from_stdin();
308 for i in 0..turns.len() {
309 position = cube.walk(position, steps[i], step);
310 position.d = position.d.turn(turns[i]);
311 }
312 position = cube.walk(position, steps[steps.len()-1], step);
313 println!("{}", password(&cube, position));
314}

Generated with cgit - Back to sebastiano.tronto.net