use std::env::args; use std::fs::File; use std::io::BufRead; use std::io::BufReader; fn get_sinks(map: &Vec, rows: usize, cols: usize) -> Vec { let mut sinks = vec![]; for y in 0..rows { for x in 0..cols { let i = y * cols + x; if (x == 0 || map[i] < map[i - 1]) && (x == cols - 1 || map[i] < map[i + 1]) && (y == 0 || map[i] < map[i - cols]) && (y == rows - 1 || map[i] < map[i + cols]) { sinks.push(i); } } } return sinks; } fn get_basins(map: &mut Vec, rows: usize, cols: usize) -> Vec { let mut basins: Vec = map .iter() .enumerate() .map(|(i, _)| i) .collect(); let mut dirty = true; while dirty { dirty = false; for y in 0..rows { for x in 0..cols { let i = y * cols + x; if x != 0 { if map[i - 1] > map[i] { if map[i - 1] != 9 { map[i - 1] = map[i]; basins[i - 1] = basins[i]; dirty = true; } } else if map[i - 1] < map[i] { if map[i] != 9 { map[i] = map[i - 1]; basins[i] = basins[i - 1]; dirty = true; } } } if y != 0 { if map[i - cols] > map[i] { if map[i - cols] != 9 { map[i - cols] = map[i]; basins[i - cols] = basins[i]; dirty = true; } } else if map[i - cols] < map[i] { if map[i] != 9 { map[i] = map[i - cols]; basins[i] = basins[i - cols]; dirty = true; } } } } } } return basins; } fn main() { let path = args().nth(1).unwrap(); let file = File::open(path).unwrap(); let mut rows = 0; let mut cols = 0; let mut map: Vec = vec![]; for line in BufReader::new(file).lines() { let l = line.unwrap(); cols = l.len(); rows += 1; for c in l.chars() { map.push(c.to_digit(10).unwrap()); } } let sinks = get_sinks(&map, rows, cols); let basins = get_basins(&mut map, rows, cols); let mut sizes: Vec = sinks .iter() .map(|i| basins.iter().filter(|j| *j == i).count()) .collect(); sizes.sort_unstable(); sizes.reverse(); print!("{}\n", sizes[0] * sizes[1] * sizes[2]); }