Add --bidi flag to path command

This commit is contained in:
Joscha 2024-12-31 15:51:58 +01:00
parent 535d7ff236
commit 6611dd3160

View file

@ -3,6 +3,7 @@ use std::io;
use crate::{ use crate::{
algo::Dijkstra, algo::Dijkstra,
data::Data, data::Data,
graph::NodeIdx,
util::{self, TitleNormalizer}, util::{self, TitleNormalizer},
}; };
@ -11,6 +12,46 @@ use crate::{
pub struct Cmd { pub struct Cmd {
start: String, start: String,
goal: String, goal: String,
// Search for a path in both directions.
#[arg(long, short)]
bidi: bool,
}
fn search_path(data: &Data, start: NodeIdx, goal: NodeIdx) -> Option<(u32, Vec<NodeIdx>)> {
println!("> Preparing dijkstra");
let mut dijkstra = Dijkstra::new(&data.graph);
println!("> Running dijkstra");
dijkstra.run(
start,
|node| node == goal,
|source, _edge, _target| !data.pages[source.usize()].redirect as u32,
);
if dijkstra.cost(goal) == u32::MAX {
return None;
}
println!("> Collecting path");
let cost = dijkstra.cost(goal);
let path = dijkstra.path(goal);
Some((cost, path))
}
fn print_path(data: &Data, start: NodeIdx, goal: NodeIdx, path: Option<(u32, Vec<NodeIdx>)>) {
let start = &data.pages[start.usize()].title;
let goal = &data.pages[goal.usize()].title;
let Some((cost, path)) = path else {
println!("No path found from {start} to {goal}");
return;
};
println!("Path found (cost {cost}, length {}):", path.len());
for page in path {
println!("{}", util::fmt_page(&data.pages[page.usize()]));
}
} }
impl Cmd { impl Cmd {
@ -23,29 +64,22 @@ impl Cmd {
println!("Start: {}", data.pages[start.usize()].title); println!("Start: {}", data.pages[start.usize()].title);
println!("Goal: {}", data.pages[goal.usize()].title); println!("Goal: {}", data.pages[goal.usize()].title);
println!(">> Find path"); if self.bidi {
println!("> Preparing dijkstra"); println!(">> Find path forward");
let mut dijkstra = Dijkstra::new(&data.graph); let forward = search_path(&data, start, goal);
println!("> Running dijkstra"); println!(">> Find path backward");
dijkstra.run( let backward = search_path(&data, goal, start);
start,
|node| node == goal,
|source, _edge, _target| !data.pages[source.usize()].redirect as u32,
);
if dijkstra.cost(goal) == u32::MAX {
println!("No path found");
return Ok(());
}
println!("> Collecting path");
let path = dijkstra.path(goal);
let cost = dijkstra.cost(goal);
println!(); println!();
println!("Path found (cost {cost}, length {}):", path.len()); print_path(&data, start, goal, forward);
for page in path { println!();
println!("{}", util::fmt_page(&data.pages[page.usize()])); print_path(&data, goal, start, backward);
} else {
println!(">> Find path");
let path = search_path(&data, start, goal);
println!();
print_path(&data, start, goal, path);
} }
Ok(()) Ok(())