1
+ use std:: fmt:: Display ;
2
+
3
+ enum Instruction < T : Display + Clone > {
4
+ AddNode ( T ) ,
5
+ AddEdge ( i32 , T , T ) ,
6
+ AddDoubleEdge ( i32 , T , T ) ,
7
+ }
8
+
9
+ struct Instructions < T : Display + Clone > {
10
+ instructions : Vec < Instruction < T > > ,
11
+ }
12
+
13
+ impl < T : Display + Clone > From < & Vec < String > > for Instructions < T > {
14
+ /// Constructs a graph from a list of instructions. This is meant to be used by reading the instructions form a file.
15
+ ///
16
+ /// The order in which the instructions are stored in the vector does not matter.
17
+ ///
18
+ /// # Instructions
19
+ ///
20
+ /// ## Nodes
21
+ ///
22
+ /// ```txt
23
+ /// node: LABEL1
24
+ /// ```
25
+ /// This declares a new node labeled `LABEL1`
26
+ ///
27
+ /// ## Edge
28
+ ///
29
+ /// ```txt
30
+ /// edge: LABEL1 WEIGHT LABEL2
31
+ /// ```
32
+ /// This adds an edge from `LABEL1` to `LABEL2` with `WEIGHT`
33
+ ///
34
+ /// ```txt
35
+ /// double_edge: LABEL1 WEIGHT LABEL2
36
+ /// ```
37
+ /// This adds a double edge between `LABEL1` and `LABEL2` with `WEIGHT`
38
+ ///
39
+ /// # Example
40
+ ///
41
+ /// ```rust
42
+ /// //use lmh01_pathfinding::algorithms::dijkstra;
43
+ /// use simple_graph_algorithms::Graph;
44
+ ///
45
+ /// // This lines vector should ideally constructed by parsing a file, below insertions are just for demonstration.
46
+ /// let mut lines = Vec::new();
47
+ /// lines.push(String::from("node: a"));
48
+ /// lines.push(String::from("node: b"));
49
+ /// lines.push(String::from("node: c"));
50
+ /// lines.push(String::from("node: d"));
51
+ /// lines.push(String::from("edge: a 7 b"));
52
+ /// lines.push(String::from("edge: a 4 c"));
53
+ /// lines.push(String::from("edge: b 2 d"));
54
+ /// lines.push(String::from("edge: c 9 d"));
55
+ /// lines.push(String::from("edge: c 2 b"));
56
+ /// lines.push(String::from("double_edge: a 1 d"));
57
+ /// let mut graph = Graph::<String>::from_instructions(&lines);
58
+ /// //assert_eq!(1, dijkstra(&mut graph, &String::from("a"), &String::from("d")).unwrap_or(-1));
59
+ /// ```
60
+ pub fn from ( value : & Vec < String > ) -> Instructions < T > { //TODO Remove function from here when from_instructions feature works
61
+ // Stores all node labels of nodes that should be added to the graph
62
+ let mut node_labels = Vec :: new ( ) ;
63
+ // Stores all edges that should be added to the graph, (WEIGHT, LABEL1, LABEL2, double)
64
+ let mut edges: Vec < ( i32 , String , String , bool ) > = Vec :: new ( ) ;
65
+
66
+ let mut Instructions = Vec :: new ( ) ;
67
+
68
+ // Parse lines
69
+ for line in value {
70
+ let split: Vec < & str > = line. split ( ' ' ) . collect ( ) ;
71
+ match split[ 0 ] . to_lowercase ( ) . as_str ( ) {
72
+ "node:" => {
73
+ Instructions . push ( Instruction :: AddNode ( String :: from ( split[ 1 ] ) ) ) ;
74
+ } ,
75
+ "edge:" => {
76
+ Instructions . push ( Instruction :: AddEdge ( split[ 2 ] . parse ( ) :: <i32>, String :: from ( split[ 1 ] ) , String :: From ( split[ 3 ] ) ) ) ;
77
+ //TODO decide if I want to change impl to TryFrom and return with err or if i want to cach it and just not parse ddefective lines
78
+ // I should do an implementation for TryFrom
79
+ edges. push ( ( split[ 2 ] . parse :: < i32 > ( ) . expect ( "Unable to parse edge weight!" ) , String :: from ( split[ 1 ] ) , String :: from ( split[ 3 ] ) , false ) ) ;
80
+ } ,
81
+ "double_edge:" => {
82
+ edges. push ( ( split[ 2 ] . parse :: < i32 > ( ) . expect ( "Unable to parse edge weight!" ) , String :: from ( split[ 1 ] ) , String :: from ( split[ 3 ] ) , true ) ) ;
83
+ } ,
84
+ _ => ( ) ,
85
+ }
86
+ }
87
+
88
+ let mut graph = Graph :: new ( ) ;
89
+
90
+ // Add nodes to graph
91
+ for label in node_labels {
92
+ graph. add_node ( label. clone ( ) ) ;
93
+ }
94
+ // Add edges to graph
95
+ for edge in edges {
96
+ if edge. 3 {
97
+ graph. add_double_edge ( edge. 0 , & edge. 1 , & edge. 2 ) ;
98
+ } else {
99
+ graph. add_edge ( edge. 0 , & edge. 1 , & edge. 2 ) ;
100
+ }
101
+ }
102
+
103
+ graph
104
+ }
105
+ }
106
+
107
+ impl < T : Display + Clone > TryFrom < String > for Instructions < T > {
108
+ type Error = InstructionParseError ;
109
+
110
+ /// Tries to parse each line of the string as instruction
111
+ fn try_from ( value : String ) -> Result < Self , Self :: Error > {
112
+ todo ! ( )
113
+ }
114
+ }
0 commit comments