Browse Source

Use char instead of String for step letter

More efficient and ergonomic.
Tyler Hallada 5 years ago
parent
commit
595605daaf
1 changed files with 34 additions and 39 deletions
  1. 34 39
      src/day7.rs

+ 34 - 39
src/day7.rs

@@ -17,8 +17,8 @@ pub fn solve_part1() -> Result<String> {
17 17
     Ok(get_step_sequence(&mut instructions))
18 18
 }
19 19
 
20
-fn read_instructions(filename: &str) -> Result<HashMap<String, Vec<String>>> {
21
-    let mut instructions: HashMap<String, Vec<String>> = HashMap::new();
20
+fn read_instructions(filename: &str) -> Result<HashMap<char, Vec<char>>> {
21
+    let mut instructions: HashMap<char, Vec<char>> = HashMap::new();
22 22
     lazy_static! {
23 23
         static ref INSTRUCTION_REGEX: Regex = Regex::new(
24 24
             r"Step (?P<dependency>\w) must be finished before step (?P<step>\w) can begin."
@@ -29,10 +29,10 @@ fn read_instructions(filename: &str) -> Result<HashMap<String, Vec<String>>> {
29 29
     for line in BufReader::new(file).lines() {
30 30
         match INSTRUCTION_REGEX.captures(&line?) {
31 31
             Some(captures) => {
32
-                let step = get_captured_field(&captures, "step")?.parse()?;
33
-                let dependency: String = get_captured_field(&captures, "dependency")?.parse()?;
32
+                let step = get_captured_field(&captures, "step")?;
33
+                let dependency: char = get_captured_field(&captures, "dependency")?;
34 34
                 instructions
35
-                    .entry(dependency.clone())
35
+                    .entry(dependency)
36 36
                     .or_insert_with(Vec::new);
37 37
                 let dependencies = instructions.entry(step).or_insert_with(Vec::new);
38 38
                 dependencies.push(dependency);
@@ -47,9 +47,15 @@ fn read_instructions(filename: &str) -> Result<HashMap<String, Vec<String>>> {
47 47
     Ok(instructions)
48 48
 }
49 49
 
50
-fn get_captured_field(captures: &Captures, field: &str) -> Result<String> {
50
+fn get_captured_field(captures: &Captures, field: &str) -> Result<char> {
51 51
     match captures.name(field) {
52
-        Some(capture) => Ok(String::from(capture.as_str())),
52
+        Some(capture) => match capture.as_str().chars().next() {
53
+            Some(letter) => Ok(letter),
54
+            None => Err(From::from(format!(
55
+                "Malformed instruction line, field {} not a char",
56
+                field
57
+            ))),
58
+        },
53 59
         None => Err(From::from(format!(
54 60
             "Malformed instruction line, field {} could not be found",
55 61
             field
@@ -57,13 +63,13 @@ fn get_captured_field(captures: &Captures, field: &str) -> Result<String> {
57 63
     }
58 64
 }
59 65
 
60
-fn get_step_sequence(instructions: &mut HashMap<String, Vec<String>>) -> String {
61
-    let mut sequence: Vec<String> = Vec::new();
66
+fn get_step_sequence(instructions: &mut HashMap<char, Vec<char>>) -> String {
67
+    let mut sequence = String::new();
62 68
     loop {
63
-        let mut available: Vec<String> = instructions
69
+        let mut available: Vec<char> = instructions
64 70
             .iter()
65 71
             .filter(|(_, dependencies)| dependencies.is_empty())
66
-            .map(|(step, _)| step.clone())
72
+            .map(|(step, _)| *step)
67 73
             .collect();
68 74
         if available.is_empty() {
69 75
             break;
@@ -79,7 +85,7 @@ fn get_step_sequence(instructions: &mut HashMap<String, Vec<String>>) -> String
79 85
         }
80 86
         sequence.push(next);
81 87
     }
82
-    sequence.join("")
88
+    sequence
83 89
 }
84 90
 
85 91
 #[cfg(test)]
@@ -88,41 +94,30 @@ mod tests {
88 94
 
89 95
     const TEST_INPUT: &str = "inputs/7_test.txt";
90 96
 
91
-    #[test]
92
-    fn reads_instructions_file() {
93
-        let expected: HashMap<String, Vec<String>> = [
94
-            ("A".to_string(), vec!["C".to_string()]),
95
-            ("F".to_string(), vec!["C".to_string()]),
96
-            ("C".to_string(), vec![]),
97
-            ("B".to_string(), vec!["A".to_string()]),
98
-            ("D".to_string(), vec!["A".to_string()]),
97
+    fn test_instructions() -> HashMap<char, Vec<char>> {
98
+        [
99
+            ('A', vec!['C']),
100
+            ('F', vec!['C']),
101
+            ('C', vec![]),
102
+            ('B', vec!['A']),
103
+            ('D', vec!['A']),
99 104
             (
100
-                "E".to_string(),
101
-                vec!["B".to_string(), "D".to_string(), "F".to_string()],
105
+                'E',
106
+                vec!['B', 'D', 'F'],
102 107
             ),
103 108
         ]
104 109
         .iter()
105 110
         .cloned()
106
-        .collect();
107
-        assert_eq!(read_instructions(TEST_INPUT).unwrap(), expected);
111
+        .collect()
112
+    }
113
+
114
+    #[test]
115
+    fn reads_instructions_file() {
116
+        assert_eq!(read_instructions(TEST_INPUT).unwrap(), test_instructions());
108 117
     }
109 118
 
110 119
     #[test]
111 120
     fn gets_step_sequence() {
112
-        let mut instructions: HashMap<String, Vec<String>> = [
113
-            ("A".to_string(), vec!["C".to_string()]),
114
-            ("F".to_string(), vec!["C".to_string()]),
115
-            ("C".to_string(), vec![]),
116
-            ("B".to_string(), vec!["A".to_string()]),
117
-            ("D".to_string(), vec!["A".to_string()]),
118
-            (
119
-                "E".to_string(),
120
-                vec!["B".to_string(), "D".to_string(), "F".to_string()],
121
-            ),
122
-        ]
123
-        .iter()
124
-        .cloned()
125
-        .collect();
126
-        assert_eq!(get_step_sequence(&mut instructions), "CABDFE");
121
+        assert_eq!(get_step_sequence(&mut test_instructions()), "CABDFE");
127 122
     }
128 123
 }