feat: improved path rendering

This commit is contained in:
antifallobst 2023-09-15 00:04:28 +02:00
parent ddedf745f4
commit 6804359aff
Signed by: antifallobst
GPG Key ID: 2B4F402172791BAF
2 changed files with 70 additions and 56 deletions

View File

@ -22,6 +22,8 @@ pub struct Graph {
nodes: Slab<Node>, nodes: Slab<Node>,
start: usize, start: usize,
end: usize, end: usize,
maps: Vec<Vec<Vec<char>>>,
} }
#[derive(Debug)] #[derive(Debug)]
@ -42,7 +44,10 @@ pub enum Action {
ChangeFloor(usize, usize), ChangeFloor(usize, usize),
} }
pub struct Actions(pub Vec<Action>); pub struct Actions {
pub actions: Vec<Action>,
pub maps: Vec<Vec<Vec<char>>>,
}
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
struct DijkstraNode { struct DijkstraNode {
@ -78,74 +83,53 @@ impl DijkstraNode {
impl Display for Actions { impl Display for Actions {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
let mut x1 = usize::MAX;
let mut x2 = 0usize;
let mut y1 = usize::MAX;
let mut y2 = 0usize;
for action in self.0.iter() {
match action {
Action::Start(x, y)
| Action::End(x, y)
| Action::Up(x, y)
| Action::Down(x, y)
| Action::Right(x, y)
| Action::Left(x, y)
| Action::ChangeFloor(x, y) => {
let x_pos = x.to_owned();
let y_pos = y.to_owned();
if x_pos < x1 {
x1 = x_pos;
}
if x_pos > x2 {
x2 = x_pos;
}
if y_pos < y1 {
y1 = y_pos;
}
if y_pos > y2 {
y2 = y_pos;
}
}
}
}
let mut layers = vec![vec![vec![' '; x2 - x1 + 1]; y2 - y1 + 1]; 2];
let mut z = 0usize; let mut z = 0usize;
let mut start = true; let mut start = true;
for action in self.0.iter() { let mut maps = self.maps.to_owned();
for action in self.actions.iter() {
match action { match action {
Action::Start(x, y) => { Action::Start(x, y) => {
layers[z][y - y1][x - x1] = 'A'; maps[z][y.to_owned()][x.to_owned()] = 'A';
} }
Action::End(x, y) => { Action::End(x, y) => {
layers[z][y - y1][x - x1] = 'B'; maps[z][y.to_owned()][x.to_owned()] = 'B';
start = false; start = false;
} }
Action::Up(x, y) => { Action::Up(x, y) => {
layers[z][y - y1][x - x1] = '↑'; maps[z][y.to_owned()][x.to_owned()] = '↑';
start = false; start = false;
} }
Action::Down(x, y) => { Action::Down(x, y) => {
layers[z][y - y1][x - x1] = '↓'; maps[z][y.to_owned()][x.to_owned()] = '↓';
start = false; start = false;
} }
Action::Left(x, y) => { Action::Left(x, y) => {
layers[z][y - y1][x - x1] = '←'; maps[z][y.to_owned()][x.to_owned()] = '←';
start = false; start = false;
} }
Action::Right(x, y) => { Action::Right(x, y) => {
layers[z][y - y1][x - x1] = '→'; maps[z][y.to_owned()][x.to_owned()] = '→';
start = false; start = false;
} }
Action::ChangeFloor(x, y) => { Action::ChangeFloor(x, y) => {
if !start { if !start {
layers[z][y - y1][x - x1] = '!'; maps[z][y.to_owned()][x.to_owned()] = '!';
} }
z = (z + 1) % 2; z = (z + 1) % 2;
layers[z][y - y1][x - x1] = '!'; maps[z][y.to_owned()][x.to_owned()] = '!';
}
}
}
for layer in maps.iter_mut() {
for line in layer {
for i in 1..(line.len() * 2) {
if (i % 2) == 0 {
continue;
}
line.insert(i, ' ');
} }
} }
} }
@ -153,12 +137,12 @@ impl Display for Actions {
write!( write!(
f, f,
"Layer 0:\n{}\n\nLayer 1:\n{}", "Layer 0:\n{}\n\nLayer 1:\n{}",
layers[0] maps[0]
.iter() .iter()
.map(|chrs| String::from_iter(chrs)) .map(|chrs| String::from_iter(chrs))
.collect::<Vec<String>>() .collect::<Vec<String>>()
.join("\n"), .join("\n"),
layers[1] maps[1]
.iter() .iter()
.map(|chrs| String::from_iter(chrs)) .map(|chrs| String::from_iter(chrs))
.collect::<Vec<String>>() .collect::<Vec<String>>()
@ -167,12 +151,29 @@ impl Display for Actions {
} }
} }
impl Actions {
pub fn seconds(&self) -> usize {
let mut seconds = 0usize;
for action in self.actions.iter() {
seconds += match action {
Action::ChangeFloor(..) => 3,
Action::Start(..) | Action::End(..) => 0,
_ => 1,
};
}
seconds
}
}
impl Graph { impl Graph {
fn default() -> Self { fn default() -> Self {
Self { Self {
nodes: Slab::new(), nodes: Slab::new(),
start: 0, start: 0,
end: 0, end: 0,
maps: Vec::new(),
} }
} }
@ -181,36 +182,42 @@ impl Graph {
let file_content = std::fs::read_to_string(path)?; let file_content = std::fs::read_to_string(path)?;
// Split the raw content into two vectors of vectors of MapNodes graph.maps = file_content
// Each vector represents a map layer that's split into rows.
let maps = file_content
.split_once('\n') .split_once('\n')
.unwrap() .unwrap()
.1 .1
.split("\n\n") .split("\n\n")
.map(|block| block.lines().map(|str| str.chars().collect()).collect())
.collect();
// Split the raw content into two vectors of vectors of MapNodes
// Each vector represents a map layer that's split into rows.
let maps = graph
.maps
.iter()
.enumerate() .enumerate()
.map(|(z, block)| { .map(|(z, block)| {
block block
.lines() .iter()
.enumerate() .enumerate()
.map(|(y, line)| { .map(|(y, line)| {
line.chars() line.iter()
.enumerate() .enumerate()
.map(|(x, c)| match c { .map(|(x, c)| match c {
'#' => MapNode::Wall, '#' => MapNode::Wall,
'.' | 'A' | 'B' => { '.' | 'A' | 'B' => {
let id = graph.nodes.insert(Node::new(x, y, z)); let id = graph.nodes.insert(Node::new(x, y, z));
if c == 'A' { if c.to_owned() == 'A' {
graph.start = id; graph.start = id;
} }
if c == 'B' { if c.to_owned() == 'B' {
graph.end = id; graph.end = id;
} }
MapNode::Floor(id) MapNode::Floor(id)
} }
c => MapNode::Unknown(c), c => MapNode::Unknown(c.to_owned()),
}) })
.collect() .collect()
}) })
@ -360,6 +367,9 @@ impl Graph {
actions.push(Action::End(x, y)); actions.push(Action::End(x, y));
Ok(Actions(actions)) Ok(Actions {
actions,
maps: self.maps.clone(),
})
} }
} }

View File

@ -22,7 +22,11 @@ fn main() -> Result<()> {
let graph = Graph::new(Path::new(&args.file))?; let graph = Graph::new(Path::new(&args.file))?;
let path = graph.dijkstra()?; let path = graph.dijkstra()?;
let actions = graph.path_to_actions(&path)?; let actions = graph.path_to_actions(&path)?;
println!("{}", actions); println!("{}\n", actions);
println!(
"Ron needs {} seconds to travel from A to B.",
actions.seconds()
);
Ok(()) Ok(())
} }