---cargo [profile.dev] opt-level = 3 [dependencies] nalgebra = "0.34" --- use nalgebra::DMatrix; use std::collections::HashMap; static CONTENT: &'static str = include_str!("./inputs/07_1.txt"); #[derive(Debug, PartialEq)] enum Cell { Empty, Split, Sourc, TBeam, } fn main() { let mut grid: Vec<_> = CONTENT.lines().map(|l| l.trim()).filter(|l| !l.is_empty()).map(|l| { l.chars().map(|c| match c { '.' => Cell::Empty, 'S' => Cell::Sourc, '^' => Cell::Split, other => unreachable!("Unexpected Input {:?}", other), }).collect::>() }).collect(); let height = grid.len(); let width = grid[0].len(); let nodes: Vec<(usize, usize)> = grid.iter().enumerate().flat_map(|(y, row)| { core::iter::repeat(y).zip(row.iter().enumerate().filter(|(_, c)| c != &&Cell::Empty)).map(|(y, (x, c))| (x, y)) }).chain((0..width).zip(core::iter::repeat(height))).collect(); println!("Nodes: {:?}", nodes.len()); let node_map: HashMap<(usize, usize), usize> = nodes.iter().copied().enumerate().map(|(idx, v)| (v, idx)).collect(); let mut adj_matrix = DMatrix::from_element(nodes.len(), nodes.len(), 0); for (sx, sy) in nodes.iter().copied() { match grid.get(sy).map(|r| &r[sx]) { Some(Cell::Empty) | Some(Cell::TBeam) => unreachable!(), Some(Cell::Sourc) => { let x = sx; let mut y = sy+1; while grid.get(y).map(|r| &r[x]) == Some(&Cell::Empty) { y += 1; } let s_idx = node_map.get(&(sx, sy)).unwrap(); let t_idx = node_map.get(&(x, y)).unwrap(); adj_matrix[(*s_idx, *t_idx)] = 1; } Some(Cell::Split) => { for x in [sx-1, sx+1] { let mut y = sy+1; while grid.get(y).map(|r| &r[x]) == Some(&Cell::Empty) { y += 1; } let s_idx = node_map.get(&(sx, sy)).unwrap(); let t_idx = node_map.get(&(x, y)).unwrap(); adj_matrix[(*s_idx, *t_idx)] = 1; } } None => {} }; } let source = nodes.iter().copied().find(|(x, y)| matches!(grid.get(*y).map(|r| &r[*x]), Some(Cell::Sourc))).unwrap(); println!("Source: {:?}", source); // println!("{}", adj_matrix); let mut routes = 0; let mut result_matrix = DMatrix::identity(nodes.len(), nodes.len()); for i in 1..height { result_matrix *= &adj_matrix; let versions = (0..width).map(|x| { let s_idx = node_map.get(&source).unwrap(); let t_idx = node_map.get(&(x, height)).unwrap(); let routes = result_matrix[(*s_idx, *t_idx)]; routes }).sum::(); println!("[{}] Routes {}", i, versions); routes += versions; } println!("Total Routes: {:?}", routes); }