alchemysolver/src/main.rs
2021-04-20 22:30:14 +02:00

94 lines
2.5 KiB
Rust

use petgraph::dot::{Dot, Config};
use petgraph::{Graph, graph::NodeIndex};
use anyhow::Context;
use std::{collections::HashMap, str::FromStr};
use std::env;
fn main() -> anyhow::Result<()> {
let g = include_str!("../assets/combinations.txt").parse::<GraphGen>()?;
let searched = env::args().nth(1).context("Supply argument for searched element")?;
let graph = g.create_graph(&searched);
let dot = Dot::with_config(&graph, &[Config::EdgeNoLabel]);
println!("{}", dot);
Ok(())
}
#[derive(Debug, Default)]
struct GraphGen {
map: HashMap<String, (String, String)>,
graph: Graph<String, String>,
}
impl GraphGen {
fn try_parse_comb(&mut self, c: &str) -> anyhow::Result<()> {
let err = "Failed to Parse combination";
let mut split = c.splitn(2, '=');
let name = split.next().context(err)?.trim().to_owned();
let rest = split.next().context(err)?;
let mut split = rest.splitn(2, '+');
let ing_a = split.next().context(err)?.trim().to_owned();
let ing_b = split.next().context(err)?.trim().to_owned();
self.map.insert(name, (ing_a, ing_b));
Ok(())
}
fn populate(&mut self, elem: String) {
let ab = self.map.get(&elem);
if !self.graph.node_indices().any(|n| self.graph.node_weight(n).unwrap() == &elem) {
self.graph.add_node(elem);
}
if let Some((a, b)) = ab {
let a = a.clone();
let b = b.clone();
self.populate(a);
self.populate(b);
}
}
fn link(&mut self) {
for n in self.graph.node_indices() {
let w = self.graph.node_weight(n).unwrap();
if let Some((a, b)) = self.map.get(w) {
if let Some(i) = self.find_node(a) {
self.graph.add_edge(i, n, String::new());
}
if let Some(i) = self.find_node(b) {
self.graph.add_edge(i, n, String::new());
}
}
}
}
fn find_node(&self, w: &str) -> Option<NodeIndex>{
self.graph.node_indices().find(|g| &self.graph[*g] == w)
}
fn create_graph(mut self, node: &str) -> Graph<String, String> {
self.populate(node.to_owned());
self.link();
self.graph
}
}
impl FromStr for GraphGen {
type Err = anyhow::Error;
fn from_str(s: &str) -> Result<Self, Self::Err> {
let mut this = Self::default();
for l in s.lines() {
this.try_parse_comb(l)?;
}
Ok(this)
}
}