refactor(day01): more idiomatic, cleaner, optimal (because fun!)

This commit is contained in:
swaits committed 2023-12-01 19:45:00 -07:00
1 parent 16d8a196e5
commit 34af78c853
1 file changed
+23 -39
+23 -39
View File
@@ -9,23 +9,18 @@ inventory::submit! {
} }
fn first_and_last_digit(s: &str) -> usize { fn first_and_last_digit(s: &str) -> usize {
// Find the first character in the string that is an ASCII digit // Find the first ASCII digit in the string
let first = s let first = s.chars().filter_map(|c| c.to_digit(10)).next().unwrap() as usize; // Safe to use unwrap as a digit is always present
.chars()
.find(|c| c.is_ascii_digit()) // Use find to get an Option containing the first digit character
.unwrap() // Unwrap the Option, panicking if no digit is found
.to_digit(10) // Convert the character to a digit in base 10
.unwrap() as usize; // Convert the digit to a usize
// Find the last character in the string that is an ASCII digit // Find the last ASCII digit in the string
let last = s let last = s
.chars() .chars()
.rfind(|c| c.is_ascii_digit()) // Use rfind to get an Option containing the last digit character .rev() // Reverse the iteration for the last digit
.unwrap() // Unwrap the Option, panicking if no digit is found .filter_map(|c| c.to_digit(10))
.to_digit(10) // Convert the character to a digit in base 10 .next()
.unwrap() as usize; // Convert the digit to a usize .unwrap() as usize; // Safe to use unwrap here as well
// Return the result // Combine the first and last digits to form a new number
first * 10 + last first * 10 + last
} }
@@ -35,34 +30,23 @@ lazy_static! {
} }
fn first_and_last_digit_regex(s: &str) -> usize { fn first_and_last_digit_regex(s: &str) -> usize {
// Initialize variables to keep track of the positions and values of the first and last digits. // Find the first digit in the string by testing against each sice from [0..] to [n-1..]
let mut first_start = usize::MAX; let first_digit = s
let mut last_end = 0; .char_indices()
let mut first_digit = String::new(); .find_map(|(index, _)| REGEX.find(&s[index..]).map(|mat| mat.as_str().to_string()))
let mut last_digit = String::new(); .unwrap(); // Safe to use unwrap because a digit is always expected
// Iterate over each character index in the string. // Iterate from the end of the string, checking each slice for the last match
for (index, _) in s.char_indices() { let last_digit = s
// Check if there is a digit at the current index or beyond. .char_indices()
if let Some(mat) = REGEX.find(&s[index..]) { .rev()
// Calculate the start and end positions of the matched digit. .find_map(|(index, _)| {
let match_start = index + mat.start(); // Check if the slice from this index to the end of the string matches the regex
let match_end = index + mat.end(); REGEX.find(&s[index..]).map(|mat| mat.as_str().to_string())
})
.unwrap(); // Safe to use unwrap as a digit is always expected
// If the current match starts before any previously found digit, it's the new first digit. // Convert the found digits to numbers and calculate the result
if match_start < first_start {
first_start = match_start;
first_digit = mat.as_str().to_string();
}
// If the current match ends after any previously found digit, it's the new last digit.
if match_end > last_end {
last_end = match_end;
last_digit = mat.as_str().to_string();
}
}
}
// Convert the first and last digit strings to their numeric values and return the result
digit_value(&first_digit) * 10 + digit_value(&last_digit) digit_value(&first_digit) * 10 + digit_value(&last_digit)
} }