|
@@ -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
|
}
|