Use char instead of String for step letter

More efficient and ergonomic.
This commit is contained in:
Tyler Hallada 2019-01-26 00:20:42 -05:00
parent f00091cbf0
commit 595605daaf

View File

@ -17,8 +17,8 @@ pub fn solve_part1() -> Result<String> {
Ok(get_step_sequence(&mut instructions)) Ok(get_step_sequence(&mut instructions))
} }
fn read_instructions(filename: &str) -> Result<HashMap<String, Vec<String>>> { fn read_instructions(filename: &str) -> Result<HashMap<char, Vec<char>>> {
let mut instructions: HashMap<String, Vec<String>> = HashMap::new(); let mut instructions: HashMap<char, Vec<char>> = HashMap::new();
lazy_static! { lazy_static! {
static ref INSTRUCTION_REGEX: Regex = Regex::new( static ref INSTRUCTION_REGEX: Regex = Regex::new(
r"Step (?P<dependency>\w) must be finished before step (?P<step>\w) can begin." 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>>> {
for line in BufReader::new(file).lines() { for line in BufReader::new(file).lines() {
match INSTRUCTION_REGEX.captures(&line?) { match INSTRUCTION_REGEX.captures(&line?) {
Some(captures) => { Some(captures) => {
let step = get_captured_field(&captures, "step")?.parse()?; let step = get_captured_field(&captures, "step")?;
let dependency: String = get_captured_field(&captures, "dependency")?.parse()?; let dependency: char = get_captured_field(&captures, "dependency")?;
instructions instructions
.entry(dependency.clone()) .entry(dependency)
.or_insert_with(Vec::new); .or_insert_with(Vec::new);
let dependencies = instructions.entry(step).or_insert_with(Vec::new); let dependencies = instructions.entry(step).or_insert_with(Vec::new);
dependencies.push(dependency); dependencies.push(dependency);
@ -47,9 +47,15 @@ fn read_instructions(filename: &str) -> Result<HashMap<String, Vec<String>>> {
Ok(instructions) Ok(instructions)
} }
fn get_captured_field(captures: &Captures, field: &str) -> Result<String> { fn get_captured_field(captures: &Captures, field: &str) -> Result<char> {
match captures.name(field) { match captures.name(field) {
Some(capture) => Ok(String::from(capture.as_str())), Some(capture) => match capture.as_str().chars().next() {
Some(letter) => Ok(letter),
None => Err(From::from(format!(
"Malformed instruction line, field {} not a char",
field
))),
},
None => Err(From::from(format!( None => Err(From::from(format!(
"Malformed instruction line, field {} could not be found", "Malformed instruction line, field {} could not be found",
field field
@ -57,13 +63,13 @@ fn get_captured_field(captures: &Captures, field: &str) -> Result<String> {
} }
} }
fn get_step_sequence(instructions: &mut HashMap<String, Vec<String>>) -> String { fn get_step_sequence(instructions: &mut HashMap<char, Vec<char>>) -> String {
let mut sequence: Vec<String> = Vec::new(); let mut sequence = String::new();
loop { loop {
let mut available: Vec<String> = instructions let mut available: Vec<char> = instructions
.iter() .iter()
.filter(|(_, dependencies)| dependencies.is_empty()) .filter(|(_, dependencies)| dependencies.is_empty())
.map(|(step, _)| step.clone()) .map(|(step, _)| *step)
.collect(); .collect();
if available.is_empty() { if available.is_empty() {
break; break;
@ -79,7 +85,7 @@ fn get_step_sequence(instructions: &mut HashMap<String, Vec<String>>) -> String
} }
sequence.push(next); sequence.push(next);
} }
sequence.join("") sequence
} }
#[cfg(test)] #[cfg(test)]
@ -88,41 +94,30 @@ mod tests {
const TEST_INPUT: &str = "inputs/7_test.txt"; const TEST_INPUT: &str = "inputs/7_test.txt";
#[test] fn test_instructions() -> HashMap<char, Vec<char>> {
fn reads_instructions_file() { [
let expected: HashMap<String, Vec<String>> = [ ('A', vec!['C']),
("A".to_string(), vec!["C".to_string()]), ('F', vec!['C']),
("F".to_string(), vec!["C".to_string()]), ('C', vec![]),
("C".to_string(), vec![]), ('B', vec!['A']),
("B".to_string(), vec!["A".to_string()]), ('D', vec!['A']),
("D".to_string(), vec!["A".to_string()]),
( (
"E".to_string(), 'E',
vec!["B".to_string(), "D".to_string(), "F".to_string()], vec!['B', 'D', 'F'],
), ),
] ]
.iter() .iter()
.cloned() .cloned()
.collect(); .collect()
assert_eq!(read_instructions(TEST_INPUT).unwrap(), expected); }
#[test]
fn reads_instructions_file() {
assert_eq!(read_instructions(TEST_INPUT).unwrap(), test_instructions());
} }
#[test] #[test]
fn gets_step_sequence() { fn gets_step_sequence() {
let mut instructions: HashMap<String, Vec<String>> = [ assert_eq!(get_step_sequence(&mut test_instructions()), "CABDFE");
("A".to_string(), vec!["C".to_string()]),
("F".to_string(), vec!["C".to_string()]),
("C".to_string(), vec![]),
("B".to_string(), vec!["A".to_string()]),
("D".to_string(), vec!["A".to_string()]),
(
"E".to_string(),
vec!["B".to_string(), "D".to_string(), "F".to_string()],
),
]
.iter()
.cloned()
.collect();
assert_eq!(get_step_sequence(&mut instructions), "CABDFE");
} }
} }