feat: implemented file to graph parsing and dijkstra

This commit is contained in:
antifallobst 2023-09-14 14:35:55 +02:00
parent fbcdc63d64
commit 0f479302dd
Signed by: antifallobst
GPG Key ID: 2B4F402172791BAF
4 changed files with 475 additions and 2 deletions

239
zauberschule/Cargo.lock generated
View File

@ -2,6 +2,245 @@
# It is not intended for manual editing.
version = 3
[[package]]
name = "anstream"
version = "0.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b1f58811cfac344940f1a400b6e6231ce35171f614f26439e80f8c1465c5cc0c"
dependencies = [
"anstyle",
"anstyle-parse",
"anstyle-query",
"anstyle-wincon",
"colorchoice",
"utf8parse",
]
[[package]]
name = "anstyle"
version = "1.0.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b84bf0a05bbb2a83e5eb6fa36bb6e87baa08193c35ff52bbf6b38d8af2890e46"
[[package]]
name = "anstyle-parse"
version = "0.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "938874ff5980b03a87c5524b3ae5b59cf99b1d6bc836848df7bc5ada9643c333"
dependencies = [
"utf8parse",
]
[[package]]
name = "anstyle-query"
version = "1.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5ca11d4be1bab0c8bc8734a9aa7bf4ee8316d462a08c6ac5052f888fef5b494b"
dependencies = [
"windows-sys",
]
[[package]]
name = "anstyle-wincon"
version = "2.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "58f54d10c6dfa51283a066ceab3ec1ab78d13fae00aa49243a45e4571fb79dfd"
dependencies = [
"anstyle",
"windows-sys",
]
[[package]]
name = "anyhow"
version = "1.0.75"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a4668cab20f66d8d020e1fbc0ebe47217433c1b6c8f2040faf858554e394ace6"
[[package]]
name = "autocfg"
version = "1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa"
[[package]]
name = "clap"
version = "4.4.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "84ed82781cea27b43c9b106a979fe450a13a31aab0500595fb3fc06616de08e6"
dependencies = [
"clap_builder",
"clap_derive",
]
[[package]]
name = "clap_builder"
version = "4.4.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2bb9faaa7c2ef94b2743a21f5a29e6f0010dff4caa69ac8e9d6cf8b6fa74da08"
dependencies = [
"anstream",
"anstyle",
"clap_lex",
"strsim",
]
[[package]]
name = "clap_derive"
version = "4.4.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0862016ff20d69b84ef8247369fabf5c008a7417002411897d40ee1f4532b873"
dependencies = [
"heck",
"proc-macro2",
"quote",
"syn",
]
[[package]]
name = "clap_lex"
version = "0.5.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cd7cc57abe963c6d3b9d8be5b06ba7c8957a930305ca90304f24ef040aa6f961"
[[package]]
name = "colorchoice"
version = "1.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "acbf1af155f9b9ef647e42cdc158db4b64a1b61f743629225fde6f3e0be2a7c7"
[[package]]
name = "heck"
version = "0.4.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8"
[[package]]
name = "proc-macro2"
version = "1.0.66"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "18fb31db3f9bddb2ea821cde30a9f70117e3f119938b5ee630b7403aa6e2ead9"
dependencies = [
"unicode-ident",
]
[[package]]
name = "quote"
version = "1.0.33"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5267fca4496028628a95160fc423a33e8b2e6af8a5302579e322e4b520293cae"
dependencies = [
"proc-macro2",
]
[[package]]
name = "slab"
version = "0.4.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8f92a496fb766b417c996b9c5e57daf2f7ad3b0bebe1ccfca4856390e3d3bb67"
dependencies = [
"autocfg",
]
[[package]]
name = "strsim"
version = "0.10.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623"
[[package]]
name = "syn"
version = "2.0.32"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "239814284fd6f1a4ffe4ca893952cdd93c224b6a1571c9a9eadd670295c0c9e2"
dependencies = [
"proc-macro2",
"quote",
"unicode-ident",
]
[[package]]
name = "unicode-ident"
version = "1.0.12"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b"
[[package]]
name = "utf8parse"
version = "0.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "711b9620af191e0cdc7468a8d14e709c3dcdb115b36f838e601583af800a370a"
[[package]]
name = "windows-sys"
version = "0.48.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9"
dependencies = [
"windows-targets",
]
[[package]]
name = "windows-targets"
version = "0.48.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9a2fa6e2155d7247be68c096456083145c183cbbbc2764150dda45a87197940c"
dependencies = [
"windows_aarch64_gnullvm",
"windows_aarch64_msvc",
"windows_i686_gnu",
"windows_i686_msvc",
"windows_x86_64_gnu",
"windows_x86_64_gnullvm",
"windows_x86_64_msvc",
]
[[package]]
name = "windows_aarch64_gnullvm"
version = "0.48.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8"
[[package]]
name = "windows_aarch64_msvc"
version = "0.48.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc"
[[package]]
name = "windows_i686_gnu"
version = "0.48.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e"
[[package]]
name = "windows_i686_msvc"
version = "0.48.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406"
[[package]]
name = "windows_x86_64_gnu"
version = "0.48.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e"
[[package]]
name = "windows_x86_64_gnullvm"
version = "0.48.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc"
[[package]]
name = "windows_x86_64_msvc"
version = "0.48.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538"
[[package]]
name = "zauberschule"
version = "0.1.0"
dependencies = [
"anyhow",
"clap",
"slab",
]

View File

@ -6,3 +6,6 @@ edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
anyhow = "1.0"
clap = { version = "4.4.2", features = ["derive"] }
slab = "0.4.9"

207
zauberschule/src/graph.rs Normal file
View File

@ -0,0 +1,207 @@
use anyhow::{Error, Result};
use slab::Slab;
use std::path::Path;
#[derive(Debug)]
struct Edge {
node: usize,
gravity: usize,
}
#[derive(Debug)]
struct Node {
edges: Slab<Edge>,
}
#[derive(Debug)]
pub struct Graph {
nodes: Slab<Node>,
start: usize,
end: usize,
}
#[derive(Debug)]
enum MapNode {
Wall,
Floor(usize),
Unknown(char),
}
#[derive(Debug, Clone)]
struct DijkstraNode {
parent: usize,
distance: usize,
}
impl Edge {
fn new(id: usize, gravity: usize) -> Self {
Self { node: id, gravity }
}
}
impl Node {
fn new() -> Self {
Self { edges: Slab::new() }
}
}
impl DijkstraNode {
fn new() -> Self {
Self {
parent: 0,
distance: 0,
}
}
}
impl Graph {
fn default() -> Self {
Self {
nodes: Slab::new(),
start: 0,
end: 0,
}
}
pub fn new(path: &Path) -> Result<Self> {
let mut graph = Self::default();
let file_content = std::fs::read_to_string(path)?;
// Split the raw content into two vectors of vectors of MapNodes
// Each vector represents a map layer that's split into rows.
let maps = file_content
.split_once('\n')
.unwrap()
.1
.split("\n\n")
.map(|block| {
block
.lines()
.map(|line| {
line.chars()
.map(|c| match c {
'#' => MapNode::Wall,
'.' | 'A' | 'B' => {
let id = graph.nodes.insert(Node::new());
if c == 'A' {
graph.start = id;
}
if c == 'B' {
graph.end = id;
}
MapNode::Floor(id)
}
c => MapNode::Unknown(c),
})
.collect()
})
.collect()
})
.collect::<Vec<Vec<Vec<MapNode>>>>();
// connect nodes
for (z, map) in maps.iter().enumerate() {
print!("\n");
for (y, row) in map.iter().enumerate() {
print!("\n");
for (x, map_node) in row.iter().enumerate() {
match map_node {
MapNode::Wall => print!("--- "),
MapNode::Floor(id) => {
let node = graph.nodes.get_mut(id.to_owned()).unwrap();
print!("{:03} ", id);
if let MapNode::Floor(i) = row[x - 1] {
node.edges.insert(Edge::new(i, 1));
}
if let MapNode::Floor(i) = row[x + 1] {
node.edges.insert(Edge::new(i, 1));
}
if let MapNode::Floor(i) = maps[z][y - 1][x] {
node.edges.insert(Edge::new(i, 1));
}
if let MapNode::Floor(i) = maps[z][y + 1][x] {
node.edges.insert(Edge::new(i, 1));
}
if let MapNode::Floor(i) = maps[(z + 1) % 2][y][x] {
node.edges.insert(Edge::new(i, 3));
}
}
MapNode::Unknown(c) => {
return Err(Error::msg(format!("Unknown character: '{c}'")))
}
}
}
}
}
print!("\n");
Ok(graph)
}
pub fn dijkstra(&self) -> Result<Vec<usize>> {
let mut visited = Vec::new();
let mut distances = vec![DijkstraNode::new(); self.nodes.len()];
let mut queue = Vec::new();
queue.push(self.start);
loop {
let id = queue.pop().unwrap();
// println!("{id}");
if id == self.end {
break;
}
let node = self.nodes.get(id).unwrap();
visited.push(id);
for (_, edge) in node.edges.iter() {
if visited.contains(&edge.node) {
continue;
}
if distances[edge.node].distance == 0
|| distances[id].distance + edge.gravity < distances[edge.node].distance
{
if distances[edge.node].distance == 0 {
queue.push(edge.node);
}
distances[edge.node].parent = id;
distances[edge.node].distance = distances[id].distance + edge.gravity;
// println!(" {}: {}", edge.node, distances[edge.node].distance);
}
}
queue.sort_unstable_by(|a, b| {
distances[b.to_owned()]
.distance
.cmp(&distances[a.to_owned()].distance)
});
// println!(
// " {:?}",
// queue
// .iter()
// .map(|id| (id, distances[id.to_owned()].distance))
// .collect::<Vec<(&usize, usize)>>()
// );
}
let mut id = self.end;
let mut path = Vec::new();
while id != self.start {
path.push(id);
id = distances[id].parent;
}
path.push(self.start);
path.reverse();
Ok(path)
}
}

View File

@ -1,3 +1,27 @@
fn main() {
println!("Hello, world!");
mod graph;
use anyhow::Result;
use clap::Parser;
use graph::Graph;
use std::path::Path;
/// BWINF 42.1
/// <Name Censored>
/// Aufgabe 3: Zauberschule
#[derive(Parser, Debug)]
#[command(author, version, about, long_about = None)]
struct Args {
/// The file containing the two maps
file: String,
}
fn main() -> Result<()> {
println!("BWINF 42.1 - <Name Censored> - Aufgabe 3: Zauberschule");
let args = Args::parse();
let graph = Graph::new(Path::new(&args.file))?;
let path = graph.dijkstra()?;
println!("Path: {:?}", path);
Ok(())
}