year2017/
day11.rs

1use utils::point::Point2D;
2use utils::prelude::*;
3
4/// Calculating distances in a hexagonal grid.
5///
6/// See <https://www.redblobgames.com/grids/hexagons/>, in particular:
7/// - <https://www.redblobgames.com/grids/hexagons/#neighbors-axial>
8/// - <https://www.redblobgames.com/grids/hexagons/#distances-axial>
9#[derive(Clone, Debug)]
10pub struct Day11 {
11    part1: u32,
12    part2: u32,
13}
14
15impl Day11 {
16    pub fn new(input: &str, _: InputType) -> Result<Self, InputError> {
17        let steps = parser::literal_map!(
18            "ne" => Point2D::new(1, -1),
19            "nw" => Point2D::new(-1, 0),
20            "se" => Point2D::new(1, 0),
21            "sw" => Point2D::new(-1, 1),
22            "n" => Point2D::new(0, -1),
23            "s" => Point2D::new(0, 1),
24        )
25        .with_suffix(b','.or(parser::eof()))
26        .parse_iterator(input);
27
28        let mut pos = Point2D::new(0, 0);
29        let mut max = 0;
30        for step in steps {
31            pos += step?;
32            max = max.max(Self::hex_dist_to_origin(pos));
33        }
34
35        Ok(Self {
36            part1: Self::hex_dist_to_origin(pos),
37            part2: max,
38        })
39    }
40
41    fn hex_dist_to_origin(p: Point2D<i32>) -> u32 {
42        (p.x.unsigned_abs() + (p.x + p.y).unsigned_abs() + p.y.unsigned_abs()) / 2
43    }
44
45    #[must_use]
46    pub fn part1(&self) -> u32 {
47        self.part1
48    }
49
50    #[must_use]
51    pub fn part2(&self) -> u32 {
52        self.part2
53    }
54}
55
56examples!(Day11 -> (u32, u32) [
57    {input: "ne,ne,ne", part1: 3},
58    {input: "ne,ne,sw,sw", part1: 0},
59    {input: "ne,ne,s,s", part1: 2},
60    {input: "se,sw,se,sw,sw", part1: 3},
61]);