year2017/
day17.rs

1use utils::prelude::*;
2
3/// Simulating a circular buffer.
4#[derive(Clone, Debug)]
5pub struct Day17 {
6    step_size: u32,
7}
8
9impl Day17 {
10    pub fn new(input: &str, _: InputType) -> Result<Self, InputError> {
11        Ok(Self {
12            step_size: parser::u32().parse_complete(input)?,
13        })
14    }
15
16    #[must_use]
17    pub fn part1(&self) -> u32 {
18        let mut buffer = Vec::with_capacity(2018);
19        buffer.push(0);
20
21        let mut i = 0;
22        for iteration in 1..=2017u16 {
23            i = (i + self.step_size as usize) % buffer.len();
24            buffer.insert(i + 1, iteration);
25            i += 1;
26        }
27
28        buffer[(i + 1) % buffer.len()] as u32
29    }
30
31    #[must_use]
32    pub fn part2(&self) -> u32 {
33        let mut result = 0u32;
34
35        // 0 is always at the start of the buffer, so the answer is the last value in position 1,
36        // which is the last value inserted when the spinlock is at 0.
37        let (mut i, mut iteration) = (0, 1);
38        while iteration <= 50_000_000 {
39            if i == 0 {
40                result = iteration;
41            }
42
43            // Skip iterations until the spinlock wraps around to the start of the buffer again
44            let skip_iterations = (iteration - i).div_ceil(self.step_size + 1);
45            iteration += skip_iterations;
46            i = (i + skip_iterations * (self.step_size + 1)) % iteration;
47        }
48
49        result
50    }
51}
52
53examples!(Day17 -> (u32, u32) [
54    {input: "3", part1: 638},
55]);