year2016/
day19.rs

1use utils::prelude::*;
2
3/// Finding the winners of counting-out games.
4#[derive(Clone, Debug)]
5pub struct Day19 {
6    elves: u32,
7}
8
9impl Day19 {
10    pub fn new(input: &str, _: InputType) -> Result<Self, InputError> {
11        Ok(Self {
12            elves: parser::u32().parse_complete(input)?,
13        })
14    }
15
16    /// See <https://en.wikipedia.org/wiki/Josephus_problem#k_=_2>.
17    #[must_use]
18    pub fn part1(&self) -> u32 {
19        2 * (self.elves - (1 << self.elves.ilog2())) + 1
20    }
21
22    /// See <https://www.reddit.com/r/adventofcode/comments/5j4lp1/2016_day_19_solutions/>.
23    ///
24    /// If the number of elves is a power of 3, the final elf wins. Otherwise, calculate the
25    /// largest power of 3 smaller or equal to the number of elves (`pow3`). Less than `2 * pow3`
26    /// the winner is `elves - pow3`, and after that it `2 * (elves - pow3) + pow3`.
27    #[must_use]
28    pub fn part2(&self) -> u32 {
29        let pow3 = 3u32.pow(self.elves.ilog(3));
30        if pow3 == self.elves {
31            pow3
32        } else {
33            let remainder = self.elves - pow3;
34            if remainder <= pow3 {
35                remainder
36            } else {
37                2 * remainder - pow3
38            }
39        }
40    }
41}
42
43examples!(Day19 -> (u32, u32) [
44    {input: "5", part1: 3, part2: 2},
45]);