120 lines
3.4 KiB
Rust
120 lines
3.4 KiB
Rust
use std::fs::File;
|
|
use std::io::{self, BufRead};
|
|
use std::path::Path;
|
|
use std::collections::HashSet;
|
|
|
|
#[derive(Debug)]
|
|
struct Cell {
|
|
altitude: u8,
|
|
score: Option<u32>,
|
|
}
|
|
|
|
impl Cell {
|
|
pub fn new(altitude: u8) -> Self {
|
|
Self {
|
|
altitude,
|
|
score: None,
|
|
}
|
|
}
|
|
}
|
|
|
|
fn print_map(map: &Vec<Vec<Cell>>) {
|
|
for y in map.iter() {
|
|
for x in y.iter() {
|
|
let c;
|
|
match x.score {
|
|
Some(n) => {
|
|
let m = (n % 62) as u8;
|
|
if m < 26 {
|
|
c = m + b'a';
|
|
}
|
|
else if m < 52 {
|
|
c = m + b'A' - 26;
|
|
}
|
|
else {
|
|
c = m + b'0' - 52;
|
|
}
|
|
},
|
|
None => c = b'#'
|
|
};
|
|
print!("{}", c as char);
|
|
}
|
|
println!("");
|
|
}
|
|
}
|
|
|
|
fn main() {
|
|
let file_path = String::from("../aoc_12a/input");
|
|
let mut map = Vec::<Vec<Cell>>::new();
|
|
let mut start_coor: (usize, usize) = (0, 0);
|
|
let mut end_coor: (usize, usize) = (0, 0);
|
|
println!("In file {}", file_path);
|
|
|
|
if let Ok(lines) = read_lines(file_path) {
|
|
// Consumes the iterator, returns an (Optional) String
|
|
for (y, line) in lines.enumerate() {
|
|
if let Ok(ip) = line {
|
|
map.push(ip.bytes().enumerate().map(|(x, byte)| match byte {
|
|
b'a'..=b'z' => Cell::new(byte - b'a'),
|
|
b'S' => {
|
|
start_coor = (x, y);
|
|
Cell::new(0)
|
|
},
|
|
b'E' => {
|
|
end_coor = (x, y);
|
|
Cell::new(25)
|
|
}
|
|
_ => panic!("Parse error"),
|
|
}).collect());
|
|
}
|
|
}
|
|
}
|
|
|
|
let height = map.len();
|
|
let width = map[0].len();
|
|
let mut cursors = Vec::new();
|
|
for y in 0..height {
|
|
cursors.push((0, y));
|
|
}
|
|
let mut score = 0;
|
|
while !cursors.is_empty() {
|
|
let mut new_cursors = HashSet::<(usize, usize)>::new();
|
|
for cursor in cursors {
|
|
let (x, y) = cursor;
|
|
let altitude = map[y][x].altitude;
|
|
match map[y][x].score {
|
|
Some(_) => (),
|
|
None => {
|
|
map[y][x].score = Some(score);
|
|
if x + 1 < width && altitude + 1 >= map[y][x + 1].altitude {
|
|
new_cursors.insert((x + 1, y));
|
|
}
|
|
if x > 0 && altitude + 1 >= map[y][x - 1].altitude {
|
|
new_cursors.insert((x - 1, y));
|
|
}
|
|
if y + 1 < height && altitude + 1 >= map[y + 1][x].altitude {
|
|
new_cursors.insert((x, y + 1));
|
|
}
|
|
if y > 0 && altitude + 1 >= map[y - 1][x].altitude {
|
|
new_cursors.insert((x, y - 1));
|
|
}
|
|
},
|
|
};
|
|
}
|
|
score += 1;
|
|
cursors = Vec::<(usize, usize)>::new();
|
|
for cursor in new_cursors {
|
|
cursors.push(cursor);
|
|
}
|
|
}
|
|
|
|
print_map(&map);
|
|
println!("{}", map[end_coor.1][end_coor.0].score.unwrap());
|
|
}
|
|
|
|
fn read_lines<P>(filename: P) -> io::Result<io::Lines<io::BufReader<File>>>
|
|
where P: AsRef<Path>, {
|
|
let file = File::open(filename)?;
|
|
Ok(io::BufReader::new(file).lines())
|
|
}
|