Skip to content

Commit ff64ba7

Browse files
committed
Move the cycle/checksumming into the implementation
Having it here means we don't need to copy the logic twice, which is helpful -- especially since the tricky part is that the this doesn't just settle, but rather produces a cycle of a certain length. This allows to skip the long part as soon as we know that length. # Please enter the commit message for your changes. Lines starting # with '#' will be ignored, and an empty message aborts the commit. # # On branch main # Your branch is ahead of 'origin/main' by 5 commits. # (use "git push" to publish your local commits) # # Changes to be committed: # modified: src/day14.rs #
1 parent 4cc76e5 commit ff64ba7

File tree

1 file changed

+32
-27
lines changed

1 file changed

+32
-27
lines changed

src/day14.rs

+32-27
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,35 @@ impl Platform {
3636
self.tilt(Direction::East);
3737
}
3838

39+
pub fn cycle_n(&mut self, n: usize) {
40+
// Eventually things cycle back a previous state. It seems that happens
41+
// after a few 10 cycles, so keep track of them in a simple vector.
42+
// As soon as we found it, we can fast-forward the cycle counter, and then
43+
// complete the remaining cycles.
44+
let mut previous_states = vec![self.checksum()];
45+
for cycle in 0..n {
46+
self.cycle();
47+
48+
let checksum = self.checksum();
49+
println!("cycle {} checksum = {}", cycle, checksum);
50+
for (i, previous_checksum) in previous_states.iter().rev().enumerate() {
51+
if checksum == *previous_checksum {
52+
println!("cycle {} matches cycle {} ({} cycles ago)", cycle, cycle-i, i);
53+
let cycle_length = i + 1;
54+
let remaining_cycles = n - cycle - 1;
55+
println!("remaining cycles = {}, cycle length = {}", remaining_cycles, cycle_length);
56+
let remaining_cycles = remaining_cycles % cycle_length;
57+
println!("fast-forwarding and finishing the last {} cycles", remaining_cycles);
58+
for _ in 0..remaining_cycles {
59+
self.cycle();
60+
}
61+
return;
62+
}
63+
}
64+
previous_states.push(checksum);
65+
}
66+
}
67+
3968
fn tilt_north_south(&mut self, rows: impl std::iter::Iterator<Item = usize>, source_rows: impl Fn(usize) -> Box<dyn std::iter::Iterator<Item = usize>>) {
4069
for r in rows {
4170
for c in 0..self.tiles[r].len() {
@@ -171,20 +200,7 @@ pub fn main() {
171200
platform.tilt(Direction::East);
172201

173202
// Complete the remaining cycles
174-
let mut previous_checksum = platform.checksum();
175-
for cycle in 0..CYCLES-1 {
176-
platform.cycle();
177-
178-
let checksum = platform.checksum();
179-
println!("cycle {} checksum = {}", cycle, checksum);
180-
if checksum == previous_checksum {
181-
break;
182-
}
183-
previous_checksum = checksum;
184-
if cycle % 1000 == 0 {
185-
println!("complete {}%", cycle/CYCLES*100);
186-
}
187-
}
203+
platform.cycle_n(CYCLES-1);
188204
println!("total load after {} cycles = {}", CYCLES, platform.total_load(Direction::North));
189205
},
190206
Err(reason) => println!("error = {}", reason),
@@ -344,19 +360,8 @@ OO....OO..
344360
fn test_part2() {
345361
let mut platform: Platform = INITIAL.parse().unwrap();
346362
println!("initial\n{}", platform);
347-
348-
let mut previous_checksum = platform.checksum();
349-
for cycle in 0..CYCLES {
350-
platform.cycle();
351-
352-
let checksum = platform.checksum();
353-
println!("cycle {} checksum = {}", cycle, checksum);
354-
if checksum == previous_checksum {
355-
break;
356-
}
357-
previous_checksum = checksum;
358-
}
359-
println!("after tilt\n{}", platform);
363+
platform.cycle_n(CYCLES);
364+
println!("after cycle\n{}", platform);
360365
assert_eq!(platform.total_load(Direction::North), 64);
361366
}
362367
}

0 commit comments

Comments
 (0)