Skip to content

Commit 34f1bcc

Browse files
committed
Day 17
1 parent 4f23c53 commit 34f1bcc

File tree

2 files changed

+303
-0
lines changed

2 files changed

+303
-0
lines changed

input/day17.txt

+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
>><<<>>>><<<>><>>>><<>>><<<<>><<<<><<<><<<>><<>>><<<<><>>>><<<>>><<>>>><<>>>><>>>><<><<<>><>><<<<>><<<<>>><<>><<>>>><<<<>>>><<>><<<>>><<<<>><><>>><<<<><<>>>><<>>><><<>><<<<>>><<<<>>><<<<><>>><<<>>>><<>>>><<>><<<>><<<><<<>><<>><<><<<><<>>>><<<<><<<<>>>><>><<<><>><<>>><<<<>><><<>><<<>>><<>>>><>>>><<>><><<<>><<<<><<<>><<<><<<<>><<>>>><<><<<>>>><<<<>>>><<><<<<>><>>>><>><<<>>>><<<>><>>><>>><<>>>><<<<>>>><<<<>>><<>>>><<<<>>><<>>>><<<>>>><<><<><>><>><<<<><<<<>><><>><<<<><>><<<>><<<>>><>>>><<<<>>><<>>><<<>><<<><>>>><<>>><<<<>>>><><<<>><>><<><<<<><><<<><<<<>>>><>>>><><<>>>><>>>><<<<>>><<<>><<<>>><<<<>>>><<<<>>><<<>>>><<<<><<>>>><<><<<<>><<<><<>>><<<>>><<>>>><>>>><>>><><>>><>>>><>>>><><>>>><>><>>>><<<>><<<<><<><<<<><<>><<>><<>>><<>><>>><>><<<>>><<<>>>><>>><>><<<<><<<>>><>>><><<>><>><<<<>>>><><<<>><<<<>><<>>><<>>><>>>><<<<>><<><><<>>>><<<>>>><<>>><<><<><<>>><<><<<><<>><<>><<><<<<>>><<>>>><<>>><<<>><<<<>><<<>><<>><<>><<<><>><<><<<>>>><<<<>>><>><>>>><<<<><<>>>><><<<><<>><<>>>><>><<<>>><<><<>>><>>>><<>>><>>><<<<>>><<<>><<<<><<<><<<<><<<<>><<<<>>><<<<>>><<<<><>>>><<<>>><<><<>>>><<>>><>><<>><><<<>>>><<>><>>>><<<><>>><<<<>><<<<>>>><<<<>><<<<>><>><<<<>>><<<>>><<<>>>><<>><<<<>><<<<>>><<><<<><<<<>>><<<<>>><><<><<>>><<<<>><>>><>>><<<><<<>>><<<>>>><<>>><><<>>><<<>><<>><<<<><<><<<<>><<<<>><><<<>>><<>><<<<><<<>>><>>>><<>>>><>>>><<<<>><>>><>><<>><<<><<>><<><<<<>><<<<>>><<<><<<<>>><<<<>>><<<>><<>>><<<>><<<<><<<>>><<>>><<><>>>><<<><<<>>><<<<>>><<<<>><<><<<<><<<>>><<>>>><<<>>><<>>>><>>>><<><<><>>><<<>>><<<<>>><<>>><<<<><>>>><<<<><<<>><<<<>>><>>><<<>>>><<<<><>><>>><<<<>>><<<><<<>>><>><<><<<<><<>>>><<<<>>><>>>><<<>>>><<<>>>><>>><>>><<<>>>><<<>>>><<<>><<>><<>>>><<<>><<>><><>><>>>><<<><<<<>>><<<<>><<>><<>>><<<>><<<<>>>><<<<>>>><>>>><<>>>><<<<><<<>><<><>>>><>><<<>>><<<>>>><<<<>>>><<>><<<<>>>><<>>>><<<<>><<<>>>><<<><<<><<<<>>>><>><<<><<<<><<<<>>>><<>><<<<>>>><<<>>>><<<><>>>><<<>><<<><<>>>><<<<>><<>><<<>><<<>>>><<<>>><>>><<>>>><<<><>>><<<<>><<<><<<><<<<><<>>>><>>><>>>><>><<<><<<><<<>>>><><<><>>>><<<><<>>>><<<>><<<<>>>><<<>>>><>>><>><<<<>>><>><<><<<<>>>><<><><<<><>><<>>>><>>>><<<>>>><<>><<<<><<<><<><<<<>><><<<<><<<>><>><<<<><<<<>><<<>>><<>>>><<>><<<>>>><<>>><<><>>>><<<<><<><<>>>><<<>>>><<><<<>>><>><<<<><>><>><>>><<<<>><<<><<<>>>><<>>>><<>>><<<<>>>><<><<<<>>><<<><><>>><<<<>>><<<<>>>><<<<>>><><<<<><<<><<<<>>>><>>>><>>>><<<<>>><>>>><<<><<<>>><<><<<<><<<>>><<><<<>>>><<>><<><<<>>>><<<>>><<<<><<<>><<<<>>>><>>><<<<><>>><<<<>><<<<>>>><>><<<>>><>><<<<><<<><<<>>>><<<>>>><<<>>>><<<<><>><<<<><<<<><<>>><<<<>>><<<>>>><<<>>>><<>>><<<<><<<<>>>><<<>>>><<<>>>><>>><<<><<<<><>><<>>><<<>>>><<><>>><<<<><<><<>>><<>>>><>>><>>>><<>>>><<>>>><<<<>><<>>><<>>><<<><<>>>><<>>>><<<>>>><>>>><<>>><><<>>><<<>><<<>><<<><<<<>><<<><<<<><>><>>>><<>><<<>><>>><<>>>><<>>><><<<>>>><<<><>>>><<<<>><<<>>>><<<<>>><<<>>>><<>><<>><<>>>><<>>>><><<<><<<<>><<>>>><<<<>><>>>><<>>><<<>>><<>><>>>><<<>>><<<><<><<<<><><<><<<<>><<>><<>>>><><>>>><>>>><<<<>><<<>>><<<<>>>><<>><<<<>>>><<<<><<<><<<<>><>><><<<<><<<>>><<><>>><><<<<>>><<>><><<<<>>><<<<><><<<<><<<>>><><>>>><<<>><<<<>>>><<<>>>><<>>><>>>><>><>><><<<>>>><<><><>><<>><<<<>>><<<<>>><<<>>>><<<<>><<>><<<<><>>><>>><>><<>>>><>>>><<<<>><<>>><<<<><<<>>><<<<>><>>><<>>>><<<>>><>>><<>><<<>>>><<<>>><<><><<<>>>><<<>>>><<<<>>>><<<>>><<<>>>><<>>>><<>><<<>>><<<<>><<<>>>><<>><<<>>>><<<>><><<<>><<><>>>><<<<>><>>>><>><>><<>>><><<><>><<<<>><<<>><<>>>><<<<>><><<>>><<<<><<<><>>><<<>>>><<><<>><>>><<<<>>>><<><<<>><<<><<>>><<<<><<<<>><<<<>>>><><<>>>><<<>>><<<>>><>><>>><<<>>><>>><><<<<>>><<<<>>>><<><>><><<><<<<>>><<<<>>>><<<<>>>><<<<>><<<><>>><<<>><<<<>>>><>>><<<>><>>>><<<><<>>><<<<><<<>>><<>>>><<><<<>>>><<<>><>>>><<>>>><>>><<<<>><<><<<>><<<>>>><<><>><<>>>><<<<>>><<<<>>><<<<>><>>>><<<<>>><<>><<<<>>><<<>>>><>>><<>>><<<<>><<<><<<<>>>><<<><<><>>>><>>>><<<<>><<<>>><>><<<<>>><><<>>>><<>>><><<>>><><<>><<><<>><<<<><<<<>>><<>><<>>><>><>><<>>><<><<>><<>><<<>>><<>>><<>><<>>>><><<<<>><<<<>>>><<<>><>><<<><<><>>>><<<<>>>><>><<<<>><><>>><<><<<<><<<>>><<<>><<>>><>>><<>>>><<<>><<<><<>>>><<<>>><<<<>>>><<<<>>>><<<>><<<<><>>><<<<>>><>>>><<<<>>><<<>>><<<>><<>>>><<>><<<<>>><<>><<<>>><<<<>><<<><<>>>><<<>><<<<><>>><<<>>>><<>>><<>><<><<<>>>><<<>>><<>><<<>>><<<<>>><<<>><><<<<>><><<<>>>><><<<>>><<>>><<>><<>><<<<><<<<>>>><<><<<>>>><<<>><<>>><<<>>>><><<<>><<>>>><<<<><<<>><<>><<<<>><<><<>>><>>><<<><<<<>>><<<>><<<<>><>><<<>>><<<<><<<<><<<>>><<<<>>><<>>>><<>><<<<><<>><>>><<>>>><>>>><<><<<>>>><<<>>><><<>>>><<<<>><<<>>><><<>>>><<><<<>>>><<<>><<<>>>><><<<><<>>>><<<>><>>><><><<<<>><<>><>>><<<<>>><<><<><<<><<<>>><<<>><<<>><<<>><<>>><>>><<<<><<<<>>>><<><<<><<<<><<<<><<<>><>>><<<>>><<<><<<>>><>>>><<>>>><>>><<<<><<<<>>><<<>><<<>><>>>><<<>><<<<>>>><<<<><>>><>>>><<<<>>>><<<<>><<<>>>><<<>>><<<<>><<<><<<>>>><<>>><<>>><>>>><><>>><<<<>>><<<>>>><>>><<<<>><>>>><<<<>><>>>><>>><><>><<>>>><<><><<><<<>>>><<<<>>><<>>><<<<>><><<<>><>><<<><<>>><<<>>>><<>><<<>>>><<<<>><<>><<<>><<<>>>><<<<>><>><<<><<<<>>>><<>>>><<><<<<><<<><<<<><<<<>><><>>>><<<<><>>>><<<><<<><>>>><<<<>>>><>>>><<<<>>>><<<>><>>>><<>>>><<<>>><>><<>>>><<<<>><<<><<<>><<>>>><<>>><<<<>>><<><<<>>><<<>><<<<>>>><<<<>><<>><>>>><><><>>>><<>>><>>>><<>>>><<<>>>><><<>>><<><><<<><<<><<<>><><<>>><<>>><<<<>>>><>>>><<>><<<<>><<<>>>><<<<>>><<>>><<>><>>><<<<><>>>><<<>>>><<<>>><>>><<><<<>>><>>><<><<<<>><<<>>>><<<>>>><<<<>>><<<<><<<>>>><><><<<<>>>><<<>>>><<<<>>><<<>><<<<><<>><<>><>><>><>><<>><<<><<<<>>><<>>><<>>>><>>>><>>>><<<<>><<<>>>><<<>>><<<<>>><>>>><<<>>><><<><<<<>><<<>>><<>><>><<><<<>><<<<>>>><<<>>><<<<>>><>>>><<<>>><<>><<>><<<<>><<<><<<>>>><<<<>><<<><>>>><<<<>>>><>><>><<>><<<<>>><>>><<>>><<<>>>><<<<>><<<>>>><>>><<<<>>>><>>><<<><<<><<<>>>><>>>><>><<<<><<<>><<<<>><<>><<<>>><<<>>>><<<<><<<>><<>><>><<<>>>><<>>><<><<<<><<<>>>><<<<>>>><<>>>><<<<>>><<<<>><<>><<<<>>>><><<<><<><>>><<<><<<<>>>><><<><>>>><<>><>>><><<<>>><<><<>>><<<<>>><><><<<>>><>><<<><<<<><<<>>>><>>>><>>>><<<>>>><<><<<>>><><><<<<>><<<>>>><<<<>>>><<<<><<>><<<><><>>><>>>><<<>>><<<>><<>><<<>><>><<><>>>><>><<<<><<<<>>>><<<<><<<><<>><>>>><><<<><<<>><<><<>>><<<<>>>><<<>>>><>><>><<>>><<<>><<>>>><>>><<>><<>>>><<>>>><<>>><<<><<<<>>>><>><>>>><<>>><><<<>><>><>>>><<<<>>><<><<<><>><><>>>><<>>><<>>>><<>>><<>>><<<><<<>><<<>><<<><<<>>><><<<>>>><<>><<<><<<<>><<<><>>>><>>><<<><<<<><>>>><<<>>><>>>><<<>>>><<<<>>><>>><<<>>>><<>><><<><<<<>>>><<>><<<<>>>><><>>>><>>><><<<<>>><<><<<<>>><<<<>>>><<<<>><<<<>>>><>><<<<><>>><><<<<>>><<>><>>><<<>><<<<>>><<<<><<>><<>><>>>><<<<>><<<<><<>><>>>><<<>><<<<>>><<>>><<<<>>><<<<><<<<><>>>><<<<>>><<>><<<<>>>><<<<>>>><<<<>>>><<<>>>><<<>>><<<>>>><<<><>><><<<<><<<>>>><>>><<<<><<<<>>><<<<>>>><<<<>><>><<>>><>>>><<>>>><<<><<<>>>><<<>>>><<><>>>><<>><>>>><<>>><<<>>>><<<>><<><>>>><<<<>>>><><<>><<><<<<>>><<<<>>><<<<>>><>>>><<<>><<><<>><<><<<>>><<<<><<<<><<<<><>><<<<>>>><<>>>><<<<><<<>><<>>><><<>><<<>>>><<<<>>><<>>>><>>><<<<><<<<>>>><<>>>><>><><<<<>>><>><<<<>><<<<>><<<>><<>>>><<<>><<<>><<<><<>><<<<>>>><<<<>><<<<><<<<><<>>><<>>><<<<>>>><><>>>><<<><<<>>><>><<<<>>>><<>>>><<>>>><<>><<<><>><<<><<>>>><>><<<<>><>>>><<>><<>>>><>><>>>><><<<<>>><<>>>><<<<>>><>><<>>>><>>><<<><>>><<<><>>>><>>>><<<>><<>>><>><<<<><<<<>><<<>>><<<<>>><<<>><<<>><>><<<<>><<>>>><<>>><<<>>><<<><>>>><<>><>>><<<>>>><<<<>><<<>>>><<<>>>><><<><<<>>><<<<><<>><>>><<>>><<<>>><<>><<<><<<<>><<<<><<>>>><<<<>>>><<<<>>><<<><>>><<>><>><<<><<<>>>><<<>>><<>><<>><<<>>><>>><<<>>>><<<>>><<<>><<<>><>>><<>>><<>>>><<<><<<>>>><<>>><<<<>>>><<<>><>><<<<>>>><<<<>>><<<>><<<><<<>>>><>>><<<>><><<>><<<<>>>><<<><<<><<<>>>><><>>>><<<>><<<>>><<>>>><<><<<>>>><<<<><<>>><<<<>>>><<><>>><<<>>><<<>>>><<<<><<>>><<<<>>>><>>>><<<>><<<<><>>>><<>><<>><<<<><>>><<<><<<<><<<>>>><<<<>>><<>>><>><><>>><<<<><<><<<<>>>><<<<>>><<<><<<><<<><><<>><<<>><<>><>>><<>>><<>><<<>><<<<>>>><<<<>><>>>><<<<><<>>>><>><<<>>><<<>>>><>>><<<><<<<><<<>><<<>><<<<>>>><<>>><<<>>>><<>>>><<<<>>>><<>>>><<>><<<>>>><<<<>>><<<<><<<<>>><<>>>><<<>>>><<>>>><>>><<>>><<<<>><<<<>>><>>><<<<>>><><<<<>>><<<<>>><><><<>>>><<<<>>><<<<>>><>><<<<>><<>>><<<<>><>><<>><<<>>>><<<<>>>><><<>>>><<<<>>><<<>>><>>>><<<<>>><<<>>><<>><<<<>>>><>><>><<<>>><<<>>>><<><<>><<<<><>>><><<<><>>>><>>>><<<>>><<<>>>><<>>>><<<>>><<<>><<><>>>><<<>>>><<><<><>>><<<<><>><<>><><<>>>><<<<>>><>>><>>><<>>><<<<><>>><>>><>><<<<>><><<<<>>>><<<>>><<>>>><<>>><<<<><<><<<><<<>>>><<<>>>><<<<>>><<<>>><<<<>><>>><<>><>>>><<<<><>><<>>>><<>>>><<<>>><<<<>>>><<>>>><<><<<><<<<>>>><<>>>><<<><<<>>>><<<>>><<<<>><<<>>><<<>><<>><<<<>><<<>>>><<>>>><<<<>>>><<><>>><<>><<<>>><<<>>>><<<<>><<><<<<>><>>>><<>>>><>><<><<>>><><<>><<<<>>><<>>>><<<>>><<>><<>><>><><<><<<><<<<>>><<>>><<><<>>>><<<>><<>><<<>><<>><<<<>><<>>><<>><>>><<>><<>>>><<<<>>>><>><><>>>><>><<>>>><>>><>>>><<<><<<<>><>><>>>><<>>><<<<>>>><<<<>>><<<<>><<>>>><<<<>>><<<>><<<>>>><>>>><<>>><<>>>><>><<<<>>><><<<>>>><<<>><>>><<<<><><<>><<>>>><>>>><<>><><<<>>><>>><<<<>><<>><<<<>><>>><<>>>><<<<>>>><<<<><<<<>>><><<<>>><>><<<>><<<<>><<>>><<<<><<<>>>><<>>><<<<>><>>>><<>>>><<<<>><<<<>><<<>><<<<>>><>>>><<>><<><>><>>><<>>>><<<>>><<<>>><>>><>>><<<>><<<><<><<<<>><<><>>><>>><<<>>><<<>>><>>><<<<>>><<>><<<>>>><<<>>><<<<>>>><<<<>>><><<<>><>>><<<>>>><<>>>><<><>><<>><<<>>><><<<>><<>>><<<<>>><>><<<<><><>>><>><>>><>>><<>>>><<<><<<<>>><>>>><<>><>><<<<>><<<>>><<>>>><<>>>><><<>>><<<><<<<>><<>>>><>>>><<<>>><<>>><<>><<>>>><<<>>>><<<<>><<<><<<>>>><<<<>>>><<<<>>><><<>>><>><><<<<>>>><<<<><<>>>><>>>><<<<>><<<>><<<>>><><<<<><<<<><<<<><<<>>><<<<><<<<>>>><<><<><<<>>>><>>>><>><<<<>>><>>><<<<>>>><>>><<<<>><<><<<<>>>><<<<><<<<>>>><<<>>><><<<<>>>><<<<><<><<<<>><><<><>>><>><<<<>>><<<<>>><<<<><>>>><<>>>><<<<>>>><<<>><<><<>><<>>><<>>>><<<>><>>><<><<<<><<<><<<>><<><>>><>>><<<>>>><<<<>>><>>><<>>><>><<<<><<<>>><<>>>><<<>><<<>>>><<<<>>>><<<<>>>><<<>><>>><<<>><<><<<<>><<>><<>><<>>><><<<>><<<<>>>><<>>><<>>>><<><<>>>><>>><<<><><<>>>><>>><>>><><<><<><<<>><<<>><<<<>><><<<<>>>><<>><<>>><<>>><>>><>><<<<>>><>><>><<<><<<>>>><<<<>><<<>>><<<><<<><<<<>>><>>><>>>><<><<<<>><<><<>><>>><<<>><<>>>><<<<>>><<>>>><<><<<<>><>>>><<<<>><>>>><<<<><<>>><<<>>>><<<><<<>>>><<><<<>><<>><<>><<<>><<<>><>>>><<<>>>><>>><<<<>>>><<><><<>><<<<><>>><<<<>><<<><>>>><><<<<>>><<<><<<>>>><<<<>>><<<<>>><<<>>><<<<>><><<<>>><<>>><><<<<>>><<>>><<<<><<<<>><<>>><>>>><<<><<>><<<<>>>><<<<>>><<<<>><><<>>><<<<>>>><<>>><<<<><<><>>>><<<<>>>>

src/bin/day17.rs

+302
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,302 @@
1+
use std::{
2+
collections::HashMap,
3+
fmt::Display,
4+
fs::File,
5+
hash::{Hash, Hasher},
6+
io::{BufRead, BufReader},
7+
ops::{Index, IndexMut},
8+
};
9+
10+
const WIDTH: usize = 7;
11+
const SPAWN_X: usize = 2;
12+
const SPAWN_Y: usize = 3;
13+
const TARGET_PART_1: usize = 2022;
14+
const TARGET_PART_2: usize = 1000000000000;
15+
16+
#[derive(Debug, Clone)]
17+
struct Chamber {
18+
cells: [Vec<bool>; WIDTH],
19+
height: usize, // relative
20+
}
21+
22+
impl Chamber {
23+
fn new() -> Self {
24+
Self {
25+
cells: Default::default(),
26+
height: 0,
27+
}
28+
}
29+
30+
fn fit(&mut self, target: usize) {
31+
if target < self.height {
32+
return;
33+
}
34+
35+
for col in self.cells.iter_mut() {
36+
col.resize(target + 1, false);
37+
}
38+
self.height = target + 1;
39+
}
40+
41+
fn trim_bottom(&mut self) -> usize {
42+
let y = (0..self.height).rev().find(|&y| {
43+
self.cells.iter().all(|col| col[y])
44+
});
45+
46+
if let Some(y) = y {
47+
self.height -= y + 1;
48+
for col in self.cells.iter_mut() {
49+
col.drain(0..=y);
50+
}
51+
y + 1
52+
} else {
53+
0
54+
}
55+
}
56+
57+
fn collides(&self, x: isize, y: isize) -> bool {
58+
if x < 0 || x >= WIDTH as isize || y < 0 {
59+
return true;
60+
}
61+
let x = x as usize;
62+
let y = y as usize;
63+
64+
if y >= self.height {
65+
false
66+
} else {
67+
self.cells[x][y]
68+
}
69+
}
70+
71+
fn piece_collides(&self, piece: &[(usize, usize)], dx: isize, dy: isize) -> bool {
72+
piece
73+
.iter()
74+
.any(|(x, y)| self.collides(*x as isize + dx, *y as isize + dy))
75+
}
76+
77+
fn place(&mut self, piece: &[(usize, usize)]) {
78+
for (x, y) in piece.iter() {
79+
let x = *x;
80+
let y = *y;
81+
self.fit(y);
82+
self.cells[x][y] = true;
83+
}
84+
}
85+
}
86+
87+
impl Index<(usize, usize)> for Chamber {
88+
type Output = bool;
89+
90+
fn index(&self, (x, y): (usize, usize)) -> &Self::Output {
91+
self.cells.index(x).index(y)
92+
}
93+
}
94+
95+
impl IndexMut<(usize, usize)> for Chamber {
96+
fn index_mut(&mut self, (x, y): (usize, usize)) -> &mut Self::Output {
97+
self.cells.index_mut(x).index_mut(y)
98+
}
99+
}
100+
101+
impl PartialEq for Chamber {
102+
fn eq(&self, other: &Self) -> bool {
103+
self.height == other.height && self.cells == other.cells
104+
}
105+
}
106+
107+
impl Eq for Chamber {}
108+
109+
impl Hash for Chamber {
110+
fn hash<H: Hasher>(&self, state: &mut H) {
111+
self.height.hash(state);
112+
}
113+
}
114+
115+
impl Display for Chamber {
116+
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
117+
for y in (0..self.height).rev() {
118+
write!(f, "|")?;
119+
for x in 0..WIDTH {
120+
if self.cells[x][y] {
121+
write!(f, "#")?;
122+
} else {
123+
write!(f, ".")?;
124+
}
125+
}
126+
writeln!(f, "|")?;
127+
}
128+
writeln!(f, "+-------+")?;
129+
Ok(())
130+
}
131+
}
132+
133+
// the anchor is the bottom-left corner
134+
#[derive(Debug, PartialEq, Eq, Clone, Copy, Hash)]
135+
enum Piece {
136+
Horizontal,
137+
Cross,
138+
Angle,
139+
Vertical,
140+
Square,
141+
}
142+
143+
impl Piece {
144+
fn cells(&self) -> &'static [(usize, usize)] {
145+
match self {
146+
Piece::Horizontal => &[(0, 0), (1, 0), (2, 0), (3, 0)],
147+
Piece::Vertical => &[(0, 0), (0, 1), (0, 2), (0, 3)],
148+
Piece::Cross => &[(1, 0), (0, 1), (1, 1), (2, 1), (1, 2)],
149+
Piece::Angle => &[(0, 0), (1, 0), (2, 0), (2, 1), (2, 2)],
150+
Piece::Square => &[(0, 0), (1, 0), (0, 1), (1, 1)],
151+
}
152+
}
153+
154+
fn for_id(id: usize) -> Self {
155+
match id % 5 {
156+
0 => Self::Horizontal,
157+
1 => Self::Cross,
158+
2 => Self::Angle,
159+
3 => Self::Vertical,
160+
4 => Self::Square,
161+
_ => panic!(),
162+
}
163+
}
164+
}
165+
166+
#[derive(Debug, PartialEq, Eq, Clone, Hash)]
167+
struct State {
168+
piece: Piece,
169+
seq_offset: usize,
170+
chamber: Chamber,
171+
}
172+
173+
impl State {
174+
fn new() -> Self {
175+
State {
176+
piece: Piece::for_id(0),
177+
seq_offset: 0,
178+
chamber: Chamber::new(),
179+
}
180+
}
181+
182+
fn spawn(&self) -> Vec<(usize, usize)> {
183+
let mut cells = self.piece.cells().to_vec();
184+
cells.iter_mut().for_each(|(x, y)| {
185+
*x += SPAWN_X;
186+
*y += self.chamber.height + SPAWN_Y;
187+
});
188+
cells
189+
}
190+
}
191+
192+
impl Display for State {
193+
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
194+
write!(
195+
f,
196+
"State(piece: {}, seq: {})",
197+
self.piece as usize, self.seq_offset
198+
)
199+
}
200+
}
201+
202+
struct CacheValue {
203+
piece_count: usize,
204+
floor_offset: usize,
205+
}
206+
207+
impl CacheValue {
208+
fn new(piece_count: usize, floor_offset: usize) -> Self {
209+
Self {
210+
piece_count,
211+
floor_offset,
212+
}
213+
}
214+
}
215+
216+
#[allow(unused)]
217+
fn show(chamber: &Chamber, piece: &[(usize, usize)]) {
218+
let mut chamber = chamber.clone();
219+
chamber.place(piece);
220+
println!("{}", chamber);
221+
}
222+
223+
fn main() {
224+
let f = File::open("input/day17.txt").unwrap();
225+
let read = BufReader::new(f);
226+
let mut lines = read.lines();
227+
228+
let Some(Ok(line)) = lines.next() else {
229+
panic!("cannot read line");
230+
};
231+
232+
// initial state
233+
let mut state = State::new();
234+
let mut piece_count: usize = 0;
235+
let mut floor_offset: usize = 0;
236+
237+
let mut cache = HashMap::<State, CacheValue>::new(); // stores the previous ground offset
238+
let seq_len = line.len();
239+
cache.insert(state.clone(), CacheValue::new(piece_count, floor_offset));
240+
241+
let mut piece = state.spawn();
242+
243+
for mov in line.chars().cycle() {
244+
// update state
245+
state.seq_offset = (state.seq_offset + 1) % seq_len;
246+
247+
// push left/right
248+
let dx: isize = match mov {
249+
'<' => -1,
250+
'>' => 1,
251+
_ => panic!("invalid move"),
252+
};
253+
if !state.chamber.piece_collides(&piece, dx, 0) {
254+
piece.iter_mut().for_each(|(x, _)| {
255+
*x = (*x as isize + dx) as usize;
256+
});
257+
}
258+
259+
// push down
260+
if !state.chamber.piece_collides(&piece, 0, -1) {
261+
piece.iter_mut().for_each(|(_, y)| {
262+
*y -= 1;
263+
});
264+
continue;
265+
}
266+
267+
// rest
268+
state.chamber.place(&piece);
269+
let trimmed = state.chamber.trim_bottom();
270+
floor_offset += trimmed;
271+
272+
// update state
273+
piece_count += 1;
274+
state.piece = Piece::for_id(piece_count);
275+
piece = state.spawn();
276+
277+
// cache
278+
if let Some(cached) = cache.get(&state) {
279+
// determine the period
280+
let piece_incr = piece_count - cached.piece_count;
281+
let floor_incr = floor_offset - cached.floor_offset;
282+
// take the shortcut
283+
let periods = (TARGET_PART_2 - piece_count) / piece_incr;
284+
piece_count += periods * piece_incr;
285+
floor_offset += periods * floor_incr;
286+
// further states should not do the same
287+
cache.clear();
288+
} else {
289+
cache.insert(state.clone(), CacheValue::new(piece_count, floor_offset));
290+
}
291+
292+
// termination
293+
if piece_count < TARGET_PART_2 {
294+
if piece_count == TARGET_PART_1 {
295+
println!("{}", state.chamber.height + floor_offset);
296+
}
297+
} else {
298+
println!("{}", state.chamber.height + floor_offset);
299+
break;
300+
}
301+
}
302+
}

0 commit comments

Comments
 (0)