Compare commits
	
		
			4 Commits
		
	
	
		
			285cefa670
			...
			cf5d423f50
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| 
						 | 
					cf5d423f50 | ||
| 
						 | 
					40b79950bd | ||
| 
						 | 
					6a39bf7002 | ||
| 
						 | 
					cfd13f68bf | 
@ -42,7 +42,6 @@ fn parse(input: &str) -> Input {
 | 
				
			|||||||
#[aoc(day20, part1)]
 | 
					#[aoc(day20, part1)]
 | 
				
			||||||
fn part1(input: &Input) -> usize {
 | 
					fn part1(input: &Input) -> usize {
 | 
				
			||||||
    let start = input.0;
 | 
					    let start = input.0;
 | 
				
			||||||
    let end = input.1;
 | 
					 | 
				
			||||||
    let map = &input.2;
 | 
					    let map = &input.2;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    #[cfg(not(test))]
 | 
					    #[cfg(not(test))]
 | 
				
			||||||
@ -124,7 +123,6 @@ fn part1(input: &Input) -> usize {
 | 
				
			|||||||
#[aoc(day20, part2)]
 | 
					#[aoc(day20, part2)]
 | 
				
			||||||
fn part2(input: &Input) -> usize {
 | 
					fn part2(input: &Input) -> usize {
 | 
				
			||||||
    let start = input.0;
 | 
					    let start = input.0;
 | 
				
			||||||
    let end = input.1;
 | 
					 | 
				
			||||||
    let map = &input.2;
 | 
					    let map = &input.2;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    #[cfg(not(test))]
 | 
					    #[cfg(not(test))]
 | 
				
			||||||
 | 
				
			|||||||
@ -1,56 +1,23 @@
 | 
				
			|||||||
use aoc_runner_derive::{aoc, aoc_generator};
 | 
					use aoc_runner_derive::{aoc, aoc_generator};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
 | 
					#[derive(Debug, PartialEq, Eq)]
 | 
				
			||||||
struct Path {
 | 
					struct Path {
 | 
				
			||||||
    steps: usize,
 | 
					    steps: usize,
 | 
				
			||||||
    path: [Option<DirButton>; 6],
 | 
					    path: [Option<DirButton>; 6],
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
impl Path {
 | 
					impl Path {
 | 
				
			||||||
    fn new() -> Self {
 | 
					    const fn from(buttons: &[DirButton]) -> Option<Self> {
 | 
				
			||||||
        Self {
 | 
					        let steps = buttons.len();
 | 
				
			||||||
            steps: 0,
 | 
					        let mut path = [None, None, None, None, None, None];
 | 
				
			||||||
            path: [None, None, None, None, None, None],
 | 
					        let mut i = 0;
 | 
				
			||||||
 | 
					        while i < steps {
 | 
				
			||||||
 | 
					            path[i] = Some(buttons[i]);
 | 
				
			||||||
 | 
					            i += 1;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					        let steps = steps + 1;
 | 
				
			||||||
 | 
					        path[i] = Some(DirButton::A);
 | 
				
			||||||
    fn push(&mut self, button: DirButton) {
 | 
					        Some(Self { steps, path })
 | 
				
			||||||
        self.path[self.steps] = Some(button);
 | 
					 | 
				
			||||||
        self.steps += 1;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    fn append(&mut self, other: &Self) {
 | 
					 | 
				
			||||||
        for i in 0..other.steps {
 | 
					 | 
				
			||||||
            self.push(other.path[i].unwrap());
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    fn reversed(&self) -> Self {
 | 
					 | 
				
			||||||
        let mut path = [None; 6];
 | 
					 | 
				
			||||||
        (0..self.steps).for_each(|i| {
 | 
					 | 
				
			||||||
            path[i] = match self.path[self.steps - i - 1] {
 | 
					 | 
				
			||||||
                Some(DirButton::Up) => Some(DirButton::Down),
 | 
					 | 
				
			||||||
                Some(DirButton::Down) => Some(DirButton::Up),
 | 
					 | 
				
			||||||
                Some(DirButton::Left) => Some(DirButton::Right),
 | 
					 | 
				
			||||||
                Some(DirButton::Right) => Some(DirButton::Left),
 | 
					 | 
				
			||||||
                Some(DirButton::A) => Some(DirButton::A),
 | 
					 | 
				
			||||||
                None => None,
 | 
					 | 
				
			||||||
            };
 | 
					 | 
				
			||||||
        });
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        Self {
 | 
					 | 
				
			||||||
            steps: self.steps,
 | 
					 | 
				
			||||||
            path,
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
impl IntoIterator for Path {
 | 
					 | 
				
			||||||
    type Item = DirButton;
 | 
					 | 
				
			||||||
    type IntoIter = std::iter::Flatten<std::array::IntoIter<Option<DirButton>, 6>>;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    fn into_iter(self) -> Self::IntoIter {
 | 
					 | 
				
			||||||
        self.path.into_iter().flatten()
 | 
					 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -63,18 +30,94 @@ enum DirButton {
 | 
				
			|||||||
    A,
 | 
					    A,
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
impl DirButton {
 | 
					const DIRBUTTON_PATHS: [[[Option<Path>; 2]; 5]; 5] = [
 | 
				
			||||||
    fn pos(&self) -> (usize, usize) {
 | 
					    // Up
 | 
				
			||||||
        match self {
 | 
					    [
 | 
				
			||||||
            DirButton::Up => (1, 0),
 | 
					        // Up
 | 
				
			||||||
            DirButton::Down => (1, 1),
 | 
					        [Path::from(&[]), None],
 | 
				
			||||||
            DirButton::Left => (0, 1),
 | 
					        // Down
 | 
				
			||||||
            DirButton::Right => (2, 1),
 | 
					        [Path::from(&[DirButton::Down]), None],
 | 
				
			||||||
            DirButton::A => (2, 0),
 | 
					        // Left
 | 
				
			||||||
        }
 | 
					        [Path::from(&[DirButton::Down, DirButton::Left]), None],
 | 
				
			||||||
    }
 | 
					        // Right
 | 
				
			||||||
 | 
					        [
 | 
				
			||||||
 | 
					            Path::from(&[DirButton::Down, DirButton::Right]),
 | 
				
			||||||
 | 
					            Path::from(&[DirButton::Right, DirButton::Down]),
 | 
				
			||||||
 | 
					        ],
 | 
				
			||||||
 | 
					        // A
 | 
				
			||||||
 | 
					        [Path::from(&[DirButton::Right]), None],
 | 
				
			||||||
 | 
					    ],
 | 
				
			||||||
 | 
					    // Down
 | 
				
			||||||
 | 
					    [
 | 
				
			||||||
 | 
					        // Up
 | 
				
			||||||
 | 
					        [Path::from(&[DirButton::Up]), None],
 | 
				
			||||||
 | 
					        // Down
 | 
				
			||||||
 | 
					        [Path::from(&[]), None],
 | 
				
			||||||
 | 
					        // Left
 | 
				
			||||||
 | 
					        [Path::from(&[DirButton::Left]), None],
 | 
				
			||||||
 | 
					        // Right
 | 
				
			||||||
 | 
					        [Path::from(&[DirButton::Right]), None],
 | 
				
			||||||
 | 
					        // A
 | 
				
			||||||
 | 
					        [
 | 
				
			||||||
 | 
					            Path::from(&[DirButton::Up, DirButton::Right]),
 | 
				
			||||||
 | 
					            Path::from(&[DirButton::Right, DirButton::Up]),
 | 
				
			||||||
 | 
					        ],
 | 
				
			||||||
 | 
					    ],
 | 
				
			||||||
 | 
					    // Left
 | 
				
			||||||
 | 
					    [
 | 
				
			||||||
 | 
					        // Up
 | 
				
			||||||
 | 
					        [Path::from(&[DirButton::Right, DirButton::Up]), None],
 | 
				
			||||||
 | 
					        // Down
 | 
				
			||||||
 | 
					        [Path::from(&[DirButton::Right]), None],
 | 
				
			||||||
 | 
					        // Left
 | 
				
			||||||
 | 
					        [Path::from(&[]), None],
 | 
				
			||||||
 | 
					        // Right
 | 
				
			||||||
 | 
					        [Path::from(&[DirButton::Right, DirButton::Right]), None],
 | 
				
			||||||
 | 
					        // A
 | 
				
			||||||
 | 
					        [
 | 
				
			||||||
 | 
					            Path::from(&[DirButton::Right, DirButton::Right, DirButton::Up]),
 | 
				
			||||||
 | 
					            None,
 | 
				
			||||||
 | 
					        ],
 | 
				
			||||||
 | 
					    ],
 | 
				
			||||||
 | 
					    // Right
 | 
				
			||||||
 | 
					    [
 | 
				
			||||||
 | 
					        // Up
 | 
				
			||||||
 | 
					        [
 | 
				
			||||||
 | 
					            Path::from(&[DirButton::Up, DirButton::Left]),
 | 
				
			||||||
 | 
					            Path::from(&[DirButton::Left, DirButton::Up]),
 | 
				
			||||||
 | 
					        ],
 | 
				
			||||||
 | 
					        // Down
 | 
				
			||||||
 | 
					        [Path::from(&[DirButton::Left]), None],
 | 
				
			||||||
 | 
					        // Left
 | 
				
			||||||
 | 
					        [Path::from(&[DirButton::Left, DirButton::Left]), None],
 | 
				
			||||||
 | 
					        // Right
 | 
				
			||||||
 | 
					        [Path::from(&[]), None],
 | 
				
			||||||
 | 
					        // A
 | 
				
			||||||
 | 
					        [Path::from(&[DirButton::Up]), None],
 | 
				
			||||||
 | 
					    ],
 | 
				
			||||||
 | 
					    // A
 | 
				
			||||||
 | 
					    [
 | 
				
			||||||
 | 
					        // Up
 | 
				
			||||||
 | 
					        [Path::from(&[DirButton::Left]), None],
 | 
				
			||||||
 | 
					        // Down
 | 
				
			||||||
 | 
					        [
 | 
				
			||||||
 | 
					            Path::from(&[DirButton::Down, DirButton::Left]),
 | 
				
			||||||
 | 
					            Path::from(&[DirButton::Left, DirButton::Down]),
 | 
				
			||||||
 | 
					        ],
 | 
				
			||||||
 | 
					        // Left
 | 
				
			||||||
 | 
					        [
 | 
				
			||||||
 | 
					            Path::from(&[DirButton::Down, DirButton::Left, DirButton::Left]),
 | 
				
			||||||
 | 
					            None,
 | 
				
			||||||
 | 
					        ],
 | 
				
			||||||
 | 
					        // Right
 | 
				
			||||||
 | 
					        [Path::from(&[DirButton::Down]), None],
 | 
				
			||||||
 | 
					        // A
 | 
				
			||||||
 | 
					        [Path::from(&[]), None],
 | 
				
			||||||
 | 
					    ],
 | 
				
			||||||
 | 
					];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    fn index(&self) -> usize {
 | 
					impl DirButton {
 | 
				
			||||||
 | 
					    const fn index(&self) -> usize {
 | 
				
			||||||
        match self {
 | 
					        match self {
 | 
				
			||||||
            DirButton::Up => 0,
 | 
					            DirButton::Up => 0,
 | 
				
			||||||
            DirButton::Down => 1,
 | 
					            DirButton::Down => 1,
 | 
				
			||||||
@ -84,44 +127,12 @@ impl DirButton {
 | 
				
			|||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    fn to(&self, other: &DirButton) -> [Option<Path>; 2] {
 | 
					    const fn paths_to(&self, other: &DirButton) -> &[Option<Path>; 2] {
 | 
				
			||||||
        let start = self.pos();
 | 
					        &DIRBUTTON_PATHS[self.index()][other.index()]
 | 
				
			||||||
        let end = other.pos();
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        let mut x = Path::new();
 | 
					 | 
				
			||||||
        let mut y = Path::new();
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        if start.0 < end.0 {
 | 
					 | 
				
			||||||
            (start.0..end.0).for_each(|_| x.push(DirButton::Right));
 | 
					 | 
				
			||||||
        } else {
 | 
					 | 
				
			||||||
            (end.0..start.0).for_each(|_| x.push(DirButton::Left));
 | 
					 | 
				
			||||||
        };
 | 
					 | 
				
			||||||
        if start.1 < end.1 {
 | 
					 | 
				
			||||||
            (start.1..end.1).for_each(|_| y.push(DirButton::Down));
 | 
					 | 
				
			||||||
        } else {
 | 
					 | 
				
			||||||
            (end.1..start.1).for_each(|_| y.push(DirButton::Up));
 | 
					 | 
				
			||||||
        };
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        if start.0 == 0 && end.1 == 0 {
 | 
					 | 
				
			||||||
            x.append(&y);
 | 
					 | 
				
			||||||
            x.push(DirButton::A);
 | 
					 | 
				
			||||||
            [Some(x), None]
 | 
					 | 
				
			||||||
        } else if end.0 == 0 && start.1 == 0 {
 | 
					 | 
				
			||||||
            y.append(&x);
 | 
					 | 
				
			||||||
            y.push(DirButton::A);
 | 
					 | 
				
			||||||
            [Some(y), None]
 | 
					 | 
				
			||||||
        } else {
 | 
					 | 
				
			||||||
            let x_copy = x;
 | 
					 | 
				
			||||||
            x.append(&y);
 | 
					 | 
				
			||||||
            x.push(DirButton::A);
 | 
					 | 
				
			||||||
            y.append(&x_copy);
 | 
					 | 
				
			||||||
            y.push(DirButton::A);
 | 
					 | 
				
			||||||
            [Some(x), Some(y)]
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
 | 
					#[derive(Debug, PartialEq, Eq)]
 | 
				
			||||||
enum NumButton {
 | 
					enum NumButton {
 | 
				
			||||||
    One,
 | 
					    One,
 | 
				
			||||||
    Two,
 | 
					    Two,
 | 
				
			||||||
@ -137,7 +148,7 @@ enum NumButton {
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
impl NumButton {
 | 
					impl NumButton {
 | 
				
			||||||
    fn pos(&self) -> (usize, usize) {
 | 
					    const fn pos(&self) -> (usize, usize) {
 | 
				
			||||||
        match self {
 | 
					        match self {
 | 
				
			||||||
            NumButton::One => (0, 2),
 | 
					            NumButton::One => (0, 2),
 | 
				
			||||||
            NumButton::Two => (1, 2),
 | 
					            NumButton::Two => (1, 2),
 | 
				
			||||||
@ -153,45 +164,84 @@ impl NumButton {
 | 
				
			|||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    #[inline(always)]
 | 
					    fn paths_to(&self, other: &NumButton) -> [Option<Path>; 2] {
 | 
				
			||||||
    fn to(&self, other: &NumButton) -> [Option<Path>; 2] {
 | 
					 | 
				
			||||||
        let start = self.pos();
 | 
					        let start = self.pos();
 | 
				
			||||||
        let end = other.pos();
 | 
					        let end = other.pos();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        let mut x = Path::new();
 | 
					        let bx = if start.0 < end.0 {
 | 
				
			||||||
        let mut y = Path::new();
 | 
					            DirButton::Right
 | 
				
			||||||
 | 
					        } else {
 | 
				
			||||||
 | 
					            DirButton::Left
 | 
				
			||||||
 | 
					        };
 | 
				
			||||||
 | 
					        let dx = start.0.abs_diff(end.0);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if start.0 < end.0 {
 | 
					        let by = if start.1 < end.1 {
 | 
				
			||||||
            (start.0..end.0).for_each(|_| x.push(DirButton::Right));
 | 
					            DirButton::Down
 | 
				
			||||||
        } else {
 | 
					        } else {
 | 
				
			||||||
            (end.0..start.0).for_each(|_| x.push(DirButton::Left));
 | 
					            DirButton::Up
 | 
				
			||||||
        };
 | 
					 | 
				
			||||||
        if start.1 < end.1 {
 | 
					 | 
				
			||||||
            (start.1..end.1).for_each(|_| y.push(DirButton::Down));
 | 
					 | 
				
			||||||
        } else {
 | 
					 | 
				
			||||||
            (end.1..start.1).for_each(|_| y.push(DirButton::Up));
 | 
					 | 
				
			||||||
        };
 | 
					        };
 | 
				
			||||||
 | 
					        let dy = start.1.abs_diff(end.1);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if start.0 == 0 && end.1 == 3 {
 | 
					        if start.0 == 0 && end.1 == 3 {
 | 
				
			||||||
            x.append(&y);
 | 
					            let mut x = [None, None, None, None, None, None];
 | 
				
			||||||
            x.push(DirButton::A);
 | 
					            (0..dx).for_each(|i| {
 | 
				
			||||||
            [Some(x), None]
 | 
					                x[i] = Some(bx);
 | 
				
			||||||
 | 
					            });
 | 
				
			||||||
 | 
					            (0..dy).for_each(|i| {
 | 
				
			||||||
 | 
					                x[i + dx] = Some(by);
 | 
				
			||||||
 | 
					            });
 | 
				
			||||||
 | 
					            x[dx + dy] = Some(DirButton::A);
 | 
				
			||||||
 | 
					            [
 | 
				
			||||||
 | 
					                Some(Path {
 | 
				
			||||||
 | 
					                    steps: dx + dy + 1,
 | 
				
			||||||
 | 
					                    path: x,
 | 
				
			||||||
 | 
					                }),
 | 
				
			||||||
 | 
					                None,
 | 
				
			||||||
 | 
					            ]
 | 
				
			||||||
        } else if end.0 == 0 && start.1 == 3 {
 | 
					        } else if end.0 == 0 && start.1 == 3 {
 | 
				
			||||||
            y.append(&x);
 | 
					            let mut y = [None, None, None, None, None, None];
 | 
				
			||||||
            y.push(DirButton::A);
 | 
					            (0..dx).for_each(|i| {
 | 
				
			||||||
            [Some(y), None]
 | 
					                y[i + dy] = Some(bx);
 | 
				
			||||||
 | 
					            });
 | 
				
			||||||
 | 
					            (0..dy).for_each(|i| {
 | 
				
			||||||
 | 
					                y[i] = Some(by);
 | 
				
			||||||
 | 
					            });
 | 
				
			||||||
 | 
					            y[dx + dy] = Some(DirButton::A);
 | 
				
			||||||
 | 
					            [
 | 
				
			||||||
 | 
					                Some(Path {
 | 
				
			||||||
 | 
					                    steps: dx + dy + 1,
 | 
				
			||||||
 | 
					                    path: y,
 | 
				
			||||||
 | 
					                }),
 | 
				
			||||||
 | 
					                None,
 | 
				
			||||||
 | 
					            ]
 | 
				
			||||||
        } else {
 | 
					        } else {
 | 
				
			||||||
            let x_copy = x;
 | 
					            let mut x = [None, None, None, None, None, None];
 | 
				
			||||||
            x.append(&y);
 | 
					            let mut y = [None, None, None, None, None, None];
 | 
				
			||||||
            x.push(DirButton::A);
 | 
					            (0..dx).for_each(|i| {
 | 
				
			||||||
            y.append(&x_copy);
 | 
					                x[i] = Some(bx);
 | 
				
			||||||
            y.push(DirButton::A);
 | 
					                y[i + dy] = Some(bx);
 | 
				
			||||||
            [Some(x), Some(y)]
 | 
					            });
 | 
				
			||||||
 | 
					            (0..dy).for_each(|i| {
 | 
				
			||||||
 | 
					                x[i + dx] = Some(by);
 | 
				
			||||||
 | 
					                y[i] = Some(by);
 | 
				
			||||||
 | 
					            });
 | 
				
			||||||
 | 
					            x[dx + dy] = Some(DirButton::A);
 | 
				
			||||||
 | 
					            y[dx + dy] = Some(DirButton::A);
 | 
				
			||||||
 | 
					            [
 | 
				
			||||||
 | 
					                Some(Path {
 | 
				
			||||||
 | 
					                    steps: dx + dy + 1,
 | 
				
			||||||
 | 
					                    path: x,
 | 
				
			||||||
 | 
					                }),
 | 
				
			||||||
 | 
					                Some(Path {
 | 
				
			||||||
 | 
					                    steps: dx + dy + 1,
 | 
				
			||||||
 | 
					                    path: y,
 | 
				
			||||||
 | 
					                }),
 | 
				
			||||||
 | 
					            ]
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
type Input = Vec<(usize, Vec<NumButton>)>;
 | 
					type Input = Vec<(DistanceSize, Vec<NumButton>)>;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#[aoc_generator(day21)]
 | 
					#[aoc_generator(day21)]
 | 
				
			||||||
fn parse(input: &str) -> Input {
 | 
					fn parse(input: &str) -> Input {
 | 
				
			||||||
@ -221,7 +271,8 @@ fn parse(input: &str) -> Input {
 | 
				
			|||||||
        .collect()
 | 
					        .collect()
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
type DistanceMatrix = [[usize; 5]; 5];
 | 
					type DistanceSize = u64;
 | 
				
			||||||
 | 
					type DistanceMatrix = [[DistanceSize; 5]; 5];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
fn precompute_steps(steps: &mut [DistanceMatrix]) {
 | 
					fn precompute_steps(steps: &mut [DistanceMatrix]) {
 | 
				
			||||||
    if steps.len() == 1 {
 | 
					    if steps.len() == 1 {
 | 
				
			||||||
@ -238,106 +289,74 @@ fn precompute_steps(steps: &mut [DistanceMatrix]) {
 | 
				
			|||||||
        DirButton::A,
 | 
					        DirButton::A,
 | 
				
			||||||
    ];
 | 
					    ];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    buttons.iter().enumerate().for_each(|(i, start)| {
 | 
					    buttons.iter().for_each(|start| {
 | 
				
			||||||
        buttons[i + 1..].iter().for_each(|end| {
 | 
					        buttons.iter().for_each(|end| {
 | 
				
			||||||
            let (forward, reversed) = start
 | 
					            steps[0][start.index()][end.index()] = start
 | 
				
			||||||
                .to(end)
 | 
					                .paths_to(end)
 | 
				
			||||||
                .into_iter()
 | 
					                .iter()
 | 
				
			||||||
                .flatten()
 | 
					                .flatten()
 | 
				
			||||||
                .map(|mut path| {
 | 
					                .map(|path| {
 | 
				
			||||||
                    path.steps -= 1;
 | 
					                    path.path
 | 
				
			||||||
                    let mut reversed = path.reversed();
 | 
					                        .iter()
 | 
				
			||||||
                    let mut forward = path;
 | 
					                        .flatten()
 | 
				
			||||||
                    reversed.push(DirButton::A);
 | 
					                        .fold((0, &DirButton::A), |acc, next| {
 | 
				
			||||||
                    forward.push(DirButton::A);
 | 
					                            (acc.0 + steps[1][acc.1.index()][next.index()], next)
 | 
				
			||||||
 | 
					                        })
 | 
				
			||||||
                    (
 | 
					                        .0
 | 
				
			||||||
                        forward
 | 
					 | 
				
			||||||
                            .path
 | 
					 | 
				
			||||||
                            .into_iter()
 | 
					 | 
				
			||||||
                            .flatten()
 | 
					 | 
				
			||||||
                            .fold((0, DirButton::A), |acc, next| {
 | 
					 | 
				
			||||||
                                let extension = steps[1][acc.1.index()][next.index()];
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
                                (acc.0 + extension, next)
 | 
					 | 
				
			||||||
                            })
 | 
					 | 
				
			||||||
                            .0,
 | 
					 | 
				
			||||||
                        reversed
 | 
					 | 
				
			||||||
                            .path
 | 
					 | 
				
			||||||
                            .into_iter()
 | 
					 | 
				
			||||||
                            .flatten()
 | 
					 | 
				
			||||||
                            .fold((0, DirButton::A), |acc, next| {
 | 
					 | 
				
			||||||
                                let extension = steps[1][acc.1.index()][next.index()];
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
                                (acc.0 + extension, next)
 | 
					 | 
				
			||||||
                            })
 | 
					 | 
				
			||||||
                            .0,
 | 
					 | 
				
			||||||
                    )
 | 
					 | 
				
			||||||
                })
 | 
					                })
 | 
				
			||||||
                .fold((usize::MAX, usize::MAX), |acc, next| {
 | 
					                .fold(DistanceSize::MAX, |acc, next| acc.min(next));
 | 
				
			||||||
                    (acc.0.min(next.0), acc.1.min(next.1))
 | 
					 | 
				
			||||||
                });
 | 
					 | 
				
			||||||
            steps[0][start.index()][end.index()] = forward;
 | 
					 | 
				
			||||||
            steps[0][end.index()][start.index()] = reversed;
 | 
					 | 
				
			||||||
        });
 | 
					        });
 | 
				
			||||||
    });
 | 
					    });
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
fn shortest_dir_path(path: Path, steps: &mut [DistanceMatrix]) -> usize {
 | 
					fn shortest_dir_path(path: Path, steps: &mut [DistanceMatrix]) -> DistanceSize {
 | 
				
			||||||
    path.path
 | 
					    path.path
 | 
				
			||||||
        .into_iter()
 | 
					        .iter()
 | 
				
			||||||
        .flatten()
 | 
					        .flatten()
 | 
				
			||||||
        .fold((0, DirButton::A), |acc, next| {
 | 
					        .fold((0, &DirButton::A), |acc, next| {
 | 
				
			||||||
            let sum = acc.0;
 | 
					            (acc.0 + steps[0][acc.1.index()][next.index()], next)
 | 
				
			||||||
            let pos = acc.1;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
            let extension = steps[0][pos.index()][next.index()];
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
            (sum + extension, next)
 | 
					 | 
				
			||||||
        })
 | 
					        })
 | 
				
			||||||
        .0
 | 
					        .0
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
fn shortest_path(path: Vec<NumButton>, steps: &mut [DistanceMatrix]) -> usize {
 | 
					fn shortest_path(path: &[NumButton], steps: &mut [DistanceMatrix]) -> DistanceSize {
 | 
				
			||||||
    path.into_iter()
 | 
					    path.iter()
 | 
				
			||||||
        .fold((0, NumButton::A), |acc, end| {
 | 
					        .fold((0, &NumButton::A), |acc, end| {
 | 
				
			||||||
            let sum = acc.0;
 | 
					            (
 | 
				
			||||||
            let start = acc.1;
 | 
					                acc.0
 | 
				
			||||||
 | 
					                    + acc
 | 
				
			||||||
            let extension = start
 | 
					                        .1
 | 
				
			||||||
                .to(&end)
 | 
					                        .paths_to(end)
 | 
				
			||||||
                .into_iter()
 | 
					                        .into_iter()
 | 
				
			||||||
                .flatten()
 | 
					                        .flatten()
 | 
				
			||||||
                .map(|path| shortest_dir_path(path, steps))
 | 
					                        .map(|path| shortest_dir_path(path, steps))
 | 
				
			||||||
                .min()
 | 
					                        .fold(DistanceSize::MAX, |acc, next| acc.min(next)),
 | 
				
			||||||
                .unwrap();
 | 
					                end,
 | 
				
			||||||
            (sum + extension, end)
 | 
					            )
 | 
				
			||||||
        })
 | 
					        })
 | 
				
			||||||
        .0
 | 
					        .0
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#[aoc(day21, part1)]
 | 
					#[aoc(day21, part1)]
 | 
				
			||||||
fn part1(input: &Input) -> usize {
 | 
					fn part1(input: &Input) -> DistanceSize {
 | 
				
			||||||
    let mut steps = vec![[[1; 5]; 5]; 3];
 | 
					    let mut steps = vec![[[1; 5]; 5]; 3];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    precompute_steps(&mut steps);
 | 
					    precompute_steps(&mut steps);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    input
 | 
					    input
 | 
				
			||||||
        .iter()
 | 
					        .iter()
 | 
				
			||||||
        .cloned()
 | 
					 | 
				
			||||||
        .map(|(num, path)| num * shortest_path(path, &mut steps))
 | 
					        .map(|(num, path)| num * shortest_path(path, &mut steps))
 | 
				
			||||||
        .sum()
 | 
					        .sum()
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#[aoc(day21, part2)]
 | 
					#[aoc(day21, part2)]
 | 
				
			||||||
fn part2(input: &Input) -> usize {
 | 
					fn part2(input: &Input) -> DistanceSize {
 | 
				
			||||||
    let mut steps = vec![[[1; 5]; 5]; 26];
 | 
					    let mut steps = vec![[[1; 5]; 5]; 26];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    precompute_steps(&mut steps);
 | 
					    precompute_steps(&mut steps);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    input
 | 
					    input
 | 
				
			||||||
        .iter()
 | 
					        .iter()
 | 
				
			||||||
        .cloned()
 | 
					 | 
				
			||||||
        .map(|(num, path)| num * shortest_path(path, &mut steps))
 | 
					        .map(|(num, path)| num * shortest_path(path, &mut steps))
 | 
				
			||||||
        .sum()
 | 
					        .sum()
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user