aoc/year2017/
day17.rs

1//! # Spinlock
2//!
3//! For part one, we simulate 2017 rounds and record the position (index) at which each number
4//! is inserted. We then find the index after the number 2017. Finally, we iterate backwards
5//! through the stored indexes to find the first (i.e. last) number inserted at that index.
6//!
7//! There are two insights that speed up part two.
8//!
9//! The first is that we don't need a buffer. We only need to preserve the last value inserted
10//! whenever the index becomes zero. Once 50 million values have been inserted then this value
11//! is the final result.
12//!
13//! The second trick is realizing that we can insert multiple values at a time before the index
14//! wraps around. For example if the index is 1, the current value 10,000 and the step 300,
15//! then we can insert 34 values at once. The [`div_ceil`] method is perfect for this computation.
16//!
17//! This reduces the number of loops needed to approximately √50000000 = 7071.
18//!
19//! [`div_ceil`]: usize::div_ceil
20use crate::util::parse::*;
21
22pub fn parse(input: &str) -> usize {
23    input.unsigned()
24}
25
26pub fn part1(input: &usize) -> usize {
27    let step = input + 1;
28    let mut index = 0;
29    let mut indexes = vec![0; 2017];
30    for len in 1..=2017 {
31        index = (index + step) % len;
32        indexes[len - 1] = index;
33    }
34    let mut next = (indexes[2016] + 1) % 2017;
35
36    let mut result = 0;
37    for (i, &o) in indexes.iter().enumerate().rev() {
38        if o == next {
39            result = i + 1;
40            break;
41        }
42        if o < next {
43            next -= 1;
44        }
45    }
46
47    result
48}
49
50pub fn part2(input: &usize) -> usize {
51    let step = input + 1;
52    let mut n: usize = 1;
53    let mut index = 0;
54    let mut result = 0;
55
56    while n <= 50_000_000 {
57        if index == 0 {
58            result = n;
59        }
60
61        let skip = (n - index).div_ceil(step);
62        n += skip;
63        index = (index + skip * step) % n;
64    }
65
66    result
67}