#![allow(dead_code)] #![allow(unused_variables)] #![allow(unused_mut)] use std::collections::HashSet; use std::env; use std::fs::File; use std::io::Read; fn dfs(x0: i64, y0: i64, map: &Vec>, mut hs: HashSet<(i64, i64)>) -> HashSet<(i64, i64)> { //println!("{} {}", x0, y0); let h = map.len() as i64; let w = map[0].len() as i64; let n = map[y0 as usize][x0 as usize]; if n == 9 { hs.insert((y0, x0)); return hs; } for (dx, dy) in [(0, 1), (0, -1), (1, 0), (-1, 0)] { let x = x0 + dx as i64; let y = y0 + dy as i64; if (0 <= x) && (x < w) && (0 <= y) && (y < h) { if map[y as usize][x as usize] == n + 1 { hs = dfs(x, y, map, hs); } } } return hs; } fn dfs2(x0: i64, y0: i64, map: &Vec>) -> i64 { let h = map.len() as i64; let w = map[0].len() as i64; let n = map[y0 as usize][x0 as usize]; if n == 9 { return 1; } let mut score = 0; for (dx, dy) in [(0, 1), (0, -1), (1, 0), (-1, 0)] { let x = x0 + dx as i64; let y = y0 + dy as i64; if (0 <= x) && (x < w) && (0 <= y) && (y < h) { if map[y as usize][x as usize] == n + 1 { score += dfs2(x, y, map); } } } return score; } fn main() { let args: Vec = env::args().collect(); let filename = if args.len() == 1 { "in/".to_owned() + args[0].split('/').last().unwrap() + ".pzl" } else { args[1].clone() }; let mut f = File::open(filename).expect("cannot open file"); let mut content = String::new(); f.read_to_string(&mut content).expect("cannot read file"); let lines = content.trim_end().split("\n"); let mut trailheads: Vec<(i64, i64)> = Vec::new(); let mut map: Vec> = Vec::new(); for (y, line) in lines.enumerate() { let mut l: Vec = Vec::new(); for (x, c) in line.chars().enumerate() { let n = c.to_digit(10).unwrap() as i64; l.push(n); if n == 0 { trailheads.push((x as i64, y as i64)); } } map.push(l); } let mut res1 = 0; let mut res2 = 0; for (x0, y0) in trailheads { let hs = dfs(x0, y0, &map, HashSet::new()); res1 += hs.len(); res2 += dfs2(x0, y0, &map); } println!("res1: {}", res1); println!("res2: {}", res2); assert_eq!(res1, 607); assert_eq!(res2, 1384); }