Skip to content

Commit

Permalink
Optimize 2017 day 5
Browse files Browse the repository at this point in the history
Reduces runtime from ~37ms to ~25ms
  • Loading branch information
ictrobot committed Oct 27, 2024
1 parent 9d7b538 commit b1558e0
Showing 1 changed file with 43 additions and 0 deletions.
43 changes: 43 additions & 0 deletions crates/year2017/src/day05.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,9 @@ pub struct Day05 {
jumps: Vec<i32>,
}

type Compressed = usize;
const BITS: usize = Compressed::BITS as usize;

impl Day05 {
pub fn new(input: &str, _: InputType) -> Result<Self, InputError> {
Ok(Self {
Expand Down Expand Up @@ -35,11 +38,51 @@ impl Day05 {
let mut steps = 0;
let mut pc = 0;

// After each jump instruction is run enough times the offset oscillates back and forth
// between 2 and 3. Once this happens, represent the jump as a single bit in a compressed
// bit mask, which allows processing multiple jumps at once without each one requiring a
// random memory read.
let mut threes: Vec<Compressed> = vec![0; jumps.len().next_multiple_of(BITS) / BITS];
// boundary represents the point where all prior jumps have stabilized on oscillating
// between 2 and 3
let mut boundary = 0;

while pc < jumps.len() {
let offset = jumps[pc];
jumps[pc] += if offset >= 3 { -1 } else { 1 };

if pc == boundary && (jumps[pc] == 2 || jumps[pc] == 3) {
// Next jump after the boundary stabilized on 2/3
boundary += 1;

let element_index = pc / BITS;
let bit_index = pc % BITS;
threes[element_index] |= ((jumps[pc] & 1) as Compressed) << bit_index;
}

pc = pc.wrapping_add_signed(offset as isize);
steps += 1;

while pc < boundary {
// While inside the boundary loop over each compressed element and handle the jumps
// in bulk
let element_index = pc / BITS;
let mut element = threes[element_index];

let bit_index = pc % BITS;
let mut bit = 1 << bit_index;

let max = boundary.min((element_index + 1) * BITS);
while pc < max {
let offset = 2 + usize::from(element & bit != 0);
element ^= bit;
bit <<= offset;
pc += offset;
steps += 1;
}

threes[element_index] = element;
}
}

steps
Expand Down

0 comments on commit b1558e0

Please sign in to comment.